目录

前言

一、概述

微服务中网关的位置

GateWay的特性

Zuul 1.x模型

Gateway模型

二、GateWay详解

三大核心概念

Gateway工作流程——核心逻辑:路由转发 + 执行过滤器链。

配置路由的第一种方式

配置路由的第二种方式

GateWay配置动态路由

GateWay常用的Predicate

GateWay的Filter


前言

近些年,为了应对日益复杂的业务场景,网关选型成为了各大互联网公司的一个技术关切点。而 Spring Cloud GateWay 作为微服务的入口,地位可见一斑。它集成了对负载均衡,动态路由,访问控制,限流熔断,埋点监控等功能的支持,旨在为微服务架构提供一种简单有效的、统一的 API 路由管理方式。

SpringCloud Gateway作为Spring Cloud 生态系统中的网关,目标是替代Zuul,在Spring Cloud 2.0以上版本中,没有对新版本的Zul 2.0以上最新高性能版本进行集成,仍然还是使用的Zuul 1.x非Reactor模式的老版本。而为了提升网关的性能,SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty。

GateWay官方网站

一、概述

微服务中网关的位置

GateWay的特性

基于Spring Framework 5,Project Reactor和Spring Boot 2.0进行构建;
动态路由:能够匹配任何请求属性;
可以对路由指定Predicate (断言)和Filter(过滤器);
集成Hystrix的断路器功能;
集成Spring Cloud 服务发现功能;
易于编写的Predicate (断言)和Filter (过滤器);
请求限流功能;
支持路径重写。

Zuul 1.x模型

Springcloud中所集成的Zuul版本,采用的是Tomcat容器,使用的是传统的Serviet IO处理模型。

Servlet的生命周期?servlet由servlet container进行生命周期管理。

container启动时构造servlet对象并调用servlet init()进行初始化;
container运行时接受请求,并为每个请求分配一个线程(一般从线程池中获取空闲线程)然后调用service);
container关闭时调用servlet destory()销毁servlet。

上述模式的缺点:

Servlet是一个简单的网络IO模型,当请求进入Servlet container时,Servlet container就会为其绑定一个线程,在并发不高的场景下这种模型是适用的。但是一旦高并发(如抽风用Jmeter压),线程数量就会上涨,而线程资源代价是昂贵的(上线文切换,内存消耗大)严重影响请求的处理时间。在一些简单业务场景下,不希望为每个request分配一个线程,只需要1个或几个线程就能应对极大并发的请求,这种业务场景下servlet模型没有优势。

所以Zuul 1.X是基于servlet之上的一个阻塞式处理模型,即Spring实现了处理所有request请求的一个servlet (DispatcherServlet)并由该servlet阻塞式处理处理。所以SpringCloud Zuul无法摆脱servlet模型的弊端。

Gateway模型

传统的Web框架,比如说: Struts2,SpringMVC等都是基于Servlet APl与Servlet容器基础之上运行的。

但是在Servlet3.1之后有了异步非阻塞的支持。而WebFlux是一个典型非阻塞异步的框架,它的核心是基于Reactor的相关API实现的。相对于传统的web框架来说,它可以运行在诸如Netty,Undertow及支持Servlet3.1的容器上。非阻塞式+函数式编程(Spring 5必须让你使用Java 8)。

Spring WebFlux是Spring 5.0 引入的新的响应式框架,区别于Spring MVC,它不需要依赖Servlet APl,它是完全异步非阻塞的,并且基于Reactor来实现响应式流规范。

Spring Cloud Gateway requires the Netty runtime provided by Spring Boot and Spring Webflux. It does not work in a traditional Servlet Container or when built as a WAR

同步、异步、阻塞、非阻塞IO总结

二、GateWay详解

三大核心概念

Route(路由) - 路由是构建网关的基本模块,它由ID,目标URI,一系列的断言过滤器组成,如断言为true则匹配该路由;
Predicate(断言) - 参考的是Java8的java.util.function.Predicate,开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由
Filter(过滤) - 指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。

web请求,通过一些匹配条件,定位到真正的服务节点。并在这个转发过程的前后,进行一些精细化控制。

predicate就是我们的匹配条件;而fliter,就可以理解为一个无所不能的拦截器。有了这两个元素,再加上目标uri,就可以实现一个具体的路由了

Gateway工作流程——核心逻辑:路由转发 + 执行过滤器链。

Clients make requests to Spring Cloud Gateway. If the Gateway Handler Mapping determines that a request matches a route, it is sent to the Gateway Web Handler. This handler runs the request through a filter chain that is specific to the request. The reason the filters are divided by the dotted line is that filters can run logic both before and after the proxy request is sent. All “pre” filter logic is executed. Then the proxy request is made. After the proxy request is made, the “post” filter logic is run.

客户端向Spring Cloud Gateway发出请求。然后在Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到GatewayWeb Handler。Handler再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(“pre”)或之后(“post")执行业务逻辑。Filter在“pre”类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等,在“post”类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等有着非常重要的作用。

配置路由的第一种方式

Gateway9527搭建

(1)建moudle——Module - cloud-gateway-gateway9527

(2)改pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>LearnCloud</artifactId><groupId>com.lun.springcloud</groupId><version>1.0.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>cloud-gateway-gateway9527</artifactId><dependencies><!--gateway--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><!--eureka-client--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity --><dependency><groupId>com.lun.springcloud</groupId><artifactId>cloud-api-commons</artifactId><version>${project.version}</version></dependency><!--一般基础配置类--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies></project>

(3)YML

server:port: 9527spring:application:name: cloud-gatewayeureka:instance:hostname: cloud-gateway-serviceclient: #服务提供者provider注册进eureka服务列表内service-url:register-with-eureka: truefetch-registry: truedefaultZone: http://eureka7001.com:7001/eureka

(4)主启动

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;@SpringBootApplication
@EnableEurekaClient
public class GateWayMain9527
{public static void main(String[] args) {SpringApplication.run(GateWayMain9527.class, args);}
}

(5)业务类

我们目前不想暴露8001端口,希望在8001外面套一层9527

更改YML

server:port: 9527spring:application:name: cloud-gateway
#############################新增网关配置###########################cloud:gateway:routes:- id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名uri: http://localhost:8001          #匹配后提供服务的路由地址#uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path=/payment/get/**         # 断言,路径相匹配的进行路由- id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名uri: http://localhost:8001          #匹配后提供服务的路由地址#uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path=/payment/lb/**         # 断言,路径相匹配的进行路由
####################################################################eureka:instance:hostname: cloud-gateway-serviceclient: #服务提供者provider注册进eureka服务列表内service-url:register-with-eureka: truefetch-registry: truedefaultZone: http://eureka7001.com:7001/eureka

测试:

先启动7001,8001,9527网关

添加网关前 - http://localhost:8001/payment/get/1

添加网关后 - http://localhost:9527/payment/get/1

两者访问成功,返回相同结果

配置路由的第二种方式

代码中注入RouteLocator的Bean

业务类实现

import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class GateWayConfig
{@Beanpublic RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder){RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();routes.route("path_route_atguigu",r -> r.path("/guonei").uri("http://news.baidu.com/guonei")).build();return routes.build();}
}

测试

浏览器输入http://localhost:9527/guonei,返回http://news.baidu.com/guonei相同的页面。

GateWay配置动态路由

默认情况下Gateway会根据注册中心注册的服务列表,以注册中心上微服务名为路径创建动态路由进行转发,从而实现动态路由的功能(不写死一个地址)。

改pom

<!--eureka-client-->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

写yml

需要注意的是uri的协议为lb,表示启用Gateway的负载均衡功能。

lb://serviceName是spring cloud gateway在微服务中自动为我们创建的负载均衡uri。

server:port: 9527spring:application:name: cloud-gateway
#############################新增网关配置###########################cloud:gateway:discovery:locator:enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由routes:- id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名#uri: http://localhost:8001          #匹配后提供服务的路由地址uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path=/payment/get/**         # 断言,路径相匹配的进行路由- id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名#uri: http://localhost:8001          #匹配后提供服务的路由地址uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path=/payment/lb/**         # 断言,路径相匹配的进行路由
####################################################################eureka:instance:hostname: cloud-gateway-serviceclient: #服务提供者provider注册进eureka服务列表内service-url:register-with-eureka: truefetch-registry: truedefaultZone: http://eureka7001.com:7001/eureka

测试

浏览器输入 - http://localhost:9527/payment/lb

结果

不停刷新页面,8001/8002两个端口切换。

GateWay常用的Predicate

Route Predicate Factories是什么

Spring Cloud Gateway matches routes as part of the Spring WebFlux HandlerMapping infrastructure. Spring Cloud Gateway includes many built-in route predicate factories. All of these predicates match on different attributes of the HTTP request. You can combine multiple route predicate factories with logical and statements.

Spring Cloud Gateway将路由匹配作为Spring WebFlux HandlerMapping基础架构的一部分。Spring Cloud Gateway包括许多内置的Route Predicate工厂。所有这些Predicate都与HTTP请求的不同属性匹配。多个RoutePredicate工厂可以进行组合。Spring Cloud Gateway创建Route 对象时,使用RoutePredicateFactory 创建 Predicate对象,Predicate 对象可以赋值给Route。Spring Cloud Gateway包含许多内置的Route Predicate Factories。所有这些谓词都匹配HTTP请求的不同属性。多种谓词工厂可以组合,并通过逻辑and。

常用的Route Predicate Factory

The After Route Predicate Factory
The Before Route Predicate Factory
The Between Route Predicate Factory
The Cookie Route Predicate Factory
The Header Route Predicate Factory
The Host Route Predicate Factory
The Method Route Predicate Factory
The Path Route Predicate Factory
The Query Route Predicate Factory
The RemoteAddr Route Predicate Factory
The weight Route Predicate Factory.

The After Route Predicate Factory

spring:cloud:gateway:routes:- id: after_routeuri: https://example.orgpredicates:# 这个时间后才能起效- After=2017-01-20T17:42:47.789-07:00[America/Denver]

可以通过下述方法获得上述格式的时间戳字符串

import java.time.ZonedDateTime;public class T2
{public static void main(String[] args){ZonedDateTime zbj = ZonedDateTime.now(); // 默认时区System.out.println(zbj);//2021-02-22T15:51:37.485+08:00[Asia/Shanghai]}
}

The Cookie Route Predicate Factory

spring:cloud:gateway:routes:- id: cookie_routeuri: https://example.orgpredicates:#Cokkie中带有下面内容才生效- Cookie=chocolate, ch.p

GateWay的Filter

Route filters allow the modification of the incoming HTTP request or outgoing HTTP response in some manner. Route filters are scoped to a particular route. Spring Cloud Gateway includes many built-in GatewayFilter Factories.
路由过滤器可用于修改进入的HTTP请求和返回的HTTP响应,路由过滤器只能指定路由进行使用。Spring Cloud Gateway内置了多种路由过滤器,他们都由GatewayFilter的工厂类来产生。

Spring Cloud Gateway的Filter:

  • 生命周期:

    • pre
    • post
  • 种类(具体看官方文档):官方文档

    • GatewayFilter - 有31种——主要是配置在yml文件中
    • GlobalFilter - 有10种——主要是使用两个接口

GlobalFilter的案例分析

import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import java.util.Date;@Component
@Slf4j
public class MyLogGateWayFilter implements GlobalFilter,Ordered
{@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain){log.info("***********come in MyLogGateWayFilter:  "+new Date());String uname = exchange.getRequest().getQueryParams().getFirst("uname");if(uname == null){log.info("*******用户名为null,非法用户,o(╥﹏╥)o");exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);return exchange.getResponse().setComplete();}return chain.filter(exchange);}@Overridepublic int getOrder(){return 0;}
}

启动7001,8001,9527,8002

http://localhost:9527/payment/lb - 访问异常

http://localhost:9527/payment/lb?uname=abc - 正常访问

Spring Cloud H (五)服务网关 GateWay相关推荐

  1. Spring Cloud中查看服务网关(Zuul)中的所有路由节点

    问题描述:在Spring Cloud的早期版本(例如1.X版本)中如果想查看Zuul的所有路由节点,我们除了在pom.xml中引入依赖外,还需要在application.yml文件中添加如下配置: # ...

  2. Spring Cloud入门-Admin服务监控中心(Hoxton版本)

    文章目录 Spring Cloud入门系列汇总 摘要 Spring Boot Admin 简介 创建admin-server模块 创建admin-client模块 监控信息演示 结合注册中心使用 修改 ...

  3. Spring Cloud入门-Ribbon服务消费者(Hoxton版本)

    文章目录 Spring Cloud入门系列汇总 摘要 Ribbon简介 RestTemplate的使用 GET请求方法 getForObject方法 getForEntity方法 POST请求方法 p ...

  4. Spring Cloud(六) 服务网关GateWay 入门

    前文回顾: Spring Cloud(一)Eureka Server-单体及集群搭建 Spring Cloud(二) 配置Eureka Client Spring Cloud(三) 熔断器Hystri ...

  5. Spring Cloud 终于按捺不住推出了自己的服务网关 Gateway

    转载自  Spring Cloud 终于按捺不住推出了自己的服务网关 Gateway Spring 官方最终还是按捺不住推出了自己的网关组件:Spring Cloud Gateway ,相比之前我们使 ...

  6. Spring Cloud之(十八)微服务网关GateWay

    十八.微服务网关GateWay Zuul 1.x 是一个基于阻塞 IO 的 API Gateway 以及 Servlet:直到 2018 年 5 月,Zuul 2.x(基于Netty,也是非阻塞的,支 ...

  7. Spring Cloud构建微服务架构(五)服务网关

    通过之前几篇Spring Cloud中几个核心组件的介绍,我们已经可以构建一个简略的(不够完善)微服务架构了.比如下图所示: alt 我们使用Spring Cloud Netflix中的Eureka实 ...

  8. 从0到1手把手搭建spring cloud alibaba 微服务大型应用框架(十五) swagger篇 : gateway 集成swagger 与 knife4j实现在线api文档并嵌入到自己项目内

    背景 我们日常开发中基本都是协同开发的,当然极个别的项目整体前后端都是一个人开发的,当多人协作时,尤其是前后端人员协同开发时 必然会面临着前端需要了解后端api接口的情况,两个选择,提前设计好文档,然 ...

  9. 《深入理解 Spring Cloud 与微服务构建》第十一章 服务网关

    <深入理解 Spring Cloud 与微服务构建>第十一章 服务网关 文章目录 <深入理解 Spring Cloud 与微服务构建>第十一章 服务网关 一.服务网关简介 二. ...

  10. 《深入理解 Spring Cloud 与微服务构建》第五章 Kubernetes

    <深入理解 Spring Cloud 与微服务构建>第五章 Kubernetes 文章目录 <深入理解 Spring Cloud 与微服务构建>第五章 Kubernetes 一 ...

最新文章

  1. 【Qt】获取、比较Qt版本的宏和函数
  2. mysql存储过程与自定义函数
  3. 时间选择控件在不同场景下的应用
  4. matlab中画花瓣,matlab画心,画玫瑰花,表白合集
  5. 远程连接Windows服务器
  6. 儿童手表怎么删除联系人_双11儿童手表选购指南:全天候24小时定位,做孩子的贴身保镖...
  7. event php,PHP event 事件机制
  8. Java 并发编程:Synchronized 及其实现原理
  9. 2021-08-20 python安装及作图
  10. DSB2017第一名代码尝试运行(记录自用)(五)
  11. LeetCode344. Reverse String
  12. switch语句训练
  13. 通用权限管理系统组件 (GPM - General Permissions Manager) 中实现系统参数配置保存,附源码...
  14. 【高级编程技术作业】第六周
  15. 安装FileFormatConverters,出现错误“无法使用此产品的安装源。请确认安装源存在,并且您可以访问它”
  16. ios 图片逆时针旋转_iOS 图片旋转方法实例代码
  17. win10系统Jmeter下载安装详解
  18. 一种用于压力传感器的温度控制系统设计
  19. 全球票房73亿的《海王》,是怎么炼成的!
  20. vue-cli中出现这个错误[WDS] Disconnected!解决!!!

热门文章

  1. 车企进军手机市场,意在智能汽车
  2. 推荐系统笔记(八):推荐系统中的长尾效应
  3. Android中跳转到系统设置界面
  4. Windows系统监控
  5. 使用N2N软件远程管理DLAP221设备
  6. 网站性能优化--实例分析篇
  7. hmm 流程图_算法:HMM模型+维特比算法详解
  8. python实现GCD算法
  9. SAP项目上的疑难杂症-(制品区分)如何处理?
  10. isbn号码 (java实现)