前言
作为Netflix Zuul的替代者,Spring Cloud Gateway是一款非常实用的微服务网关,在Spring Cloud微服务架构体系中发挥非常大的作用。本文对Spring Cloud Gateway常见使用场景进行了梳理,希望对微服务开发人员提供一些帮助。
微服务网关SpringCloudGateway
1.概述
Spring cloud gateway是spring官方基于Spring 5.0、Spring Boot2.0和Project Reactor等技术开发的网关,Spring Cloud Gateway旨在为微服务架构提供简单、有效和统一的API路由管理方式,Spring Cloud Gateway作为Spring Cloud生态系统中的网关,目标是替代Netflix Zuul,其不仅提供统一的路由方式,并且还基于Filer链的方式提供了网关基本的功能,例如:安全、监控/埋点、限流等。
2.核心概念
网关提供API全托管服务,丰富的API管理功能,辅助企业管理大规模的API,以降低管理成本和安全风险,包括协议适配、协议转发、安全策略、防刷、流量、监控日志等贡呢。一般来说网关对外暴露的URL或者接口信息,我们统称为路由信息。如果研发过网关中间件或者使用过Zuul的人,会知道网关的核心是Filter以及Filter Chain(Filter责任链)。Sprig Cloud Gateway也具有路由和Filter的概念。下面介绍一下Spring Cloud Gateway中几个重要的概念。
路由。路由是网关最基础的部分,路由信息有一个ID、一个目的URL、一组断言和一组Filter组成。如果断言路由为真,则说明请求的URL和配置匹配
断言。Java8中的断言函数。Spring Cloud Gateway中的断言函数输入类型是Spring5.0框架中的ServerWebExchange。Spring Cloud Gateway中的断言函数允许开发者去定义匹配来自于http request中的任何信息,比如请求头和参数等。
过滤器。一个标准的Spring webFilter。Spring cloud gateway中的filter分为两种类型的Filter,分别是Gateway Filter和Global Filter。过滤器Filter将会对请求和响应进行修改处理
Spring cloudGateway发出请求。然后再由Gateway Handler Mapping中找到与请求相匹配的路由,将其发送到Gateway web handler。Handler再通过指定的过滤器链将请求发送到我们实际的服务执行业务逻辑,然后返回。
快速入门
以Spring Boot框架开发为例,启动一个Gateway服务模块(以Consul作为注册中心),一个后端服务模块。client端请求经gateway服务把请求路由到后端服务。
前提条件:
- Consul:版本1.5.0。
- Spring bot:版本2.1.5。
- Spring cloud:版本Greenwich.SR1。
- Redis:版本5.0.5。
1.微服务开发
这里以使用Spring Boot框架开发微服务为例,启动一个服务并注册到Consul。
引入依赖:
org.springframework.cloudspring-cloud-starter-consul-discovery
注册服务到Consul,配置文件配置如下:
spring:application:name: service-consumercloud:consul: host: 127.0.0.1 port: 8500 discovery: service-name: service-consumer
如下定义RestController,发布HTTP接口。
@RestController@RequestMapping("/user")public class UserController {@Resourceprivate UserService userService;@GetMapping(value = "/info")public User info() { return userService.info();}
}
注:此为服务端配置,经Gateway把请求路由转发到该服务上。
2.网关配置
创建一个Gateway服务,引入以下依赖:
org.springframework.cloudspring-cloud-starter-gatewayorg.springframework.cloudspring-cloud-starter-consul-discovery
启动类配置如下:
@SpringBootApplication@EnableDiscoveryClientpublic class GatewayApplication {public static void main(String[] args) { SpringApplication.run(GatewayApplication.class, args);}
}
Spring Cloud Gateway对client端请求起到路由功能,主要配置如下:
server:port: 8098spring:application:name: service-gatewaycloud:gateway: discovery: locator: enabled: true lower-case-service-id: true consul: host: 127.0.0.1 #注册gateway网关到consul port: 8500 discovery: service-name: service-gateway
此时使用http://localhost:8089/service-consumer/user/info访问服务,网关即可对服务进行路由转发,把请求转发到具体后端服务上。此时,url中使用的url前缀service-consumer,是后端服务在Consul注册的服务名称转为小写字母以后的字符串。
最佳实践
01 Gateway网关配置
本文第二部分开发规范中定义了网关进行路由转发的配置,除了上述配置方式还可以使用下面的方式进行配置:
gateway: discovery: locator: enabled: true lower-case-service-id: true routes: - id: service_consumer uri: lb://service-consumer predicates: - Path= /consumer/** filters: - StripPrefix=1
在上面的配置中,配置了一个Path的predicat,将以/consumer/**开头的请求都会转发到uri为lb://service-consumer的地址上,lb://service-consumer(注册中心中服务的名称)即service-consumer服务的负载均衡地址,并用StripPrefix的filter 在转发之前将/consumer去掉。同时将spring.cloud.gateway.discovery.locator.enabled改为false,如果不改的话,之前的http://localhost:8081/service-consumer/user/info这样的请求地址也能正常访问,因为这时为每个服务创建了2个router。
本文第二部分和本节一共讲述了两种配置方式,两种配置都可以实现请求路由转发的功能。参数spring.cloud.gateway.discovery.locator.enabled为true,表明Gateway开启服务注册和发现的功能,并且Spring Cloud Gateway自动根据服务发现为每一个服务创建了一个router,这个router将以服务名开头的请求路径转发到对应的服务。spring.cloud.gateway.discovery.locator.lowerCaseServiceId是将请求路径上的服务名配置为小写(因为服务注册的时候,向注册中心注册时将服务名转成大写的了)。
gateway: discovery: locator: enabled: true lower-case-service-id: true
02 Gateway跨域访问
Spring Cloud Gateway还针对跨域访问做了设计,可以使用以下配置解决跨域访问问题:
spring:cloud:gateway: globalcors: corsConfigurations: '[/**]': allowedOrigins: "https://docs.spring.io" allowedMethods: - GET allowHeaders: - Content-Type
在上面的示例中,允许来自https://docs.spring.io的get请求进行访问,并且表明服务器允许请求头中携带字段Content-Type。
03 Gateway 过滤器
Spring Cloud Gateway的filter生命周期不像Zuul那么丰富,它只有两个:“pre”和“post”:
pre:这种过滤器在请求被路由之前调用。可以利用这个过滤器实现身份验证、在集群中选择请求的微服务、记录调试的信息。
post:这种过滤器在路由到服务器之后执行。这种过滤器可用来为响应添加HTTP Header、统计信息和指标、响应从微服务发送给客户端等。
Spring Cloud gateway的filter分为两种:GatewayFilter和Globalfilter。GlobalFilter会应用到所有的路由上,而Gatewayfilter将应用到单个路由或者一个分组的路由上。
利用Gatewayfilter可以修改请求的http的请求或者是响应,或者根据请求或者响应做一些特殊的限制。更多时候可以利用Gatewayfilter做一些具体的路由配置。
下面的配置是AddRequestParameter Gatewayfilter的相关配置。
spring:application:name: service-gatewaycloud:gateway: discovery: locator: enabled: true routes: - id: parameter_route uri: http://localhost:8504/user/info filters: - AddRequestParameter=foo, bar predicates: - Method=GET
上述配置中指定了转发的地址,设置所有的GET方法都会自动添加foo=bar,当请求符合上述路由条件时,即可在后端服务上接收到Gateway网关添加的参数。
另外再介绍一种比较常用的filter,即StripPrefix gateway filter。
配置如下:
spring:cloud:gateway: routes: - id: stripprefixfilter uri: lb://service-consumer predicates: - Path=/consumer/** filters: - StripPrefix=1
当client端使用http://localhost:8098/consumer/user/info路径进行请求时,如果根据上述进行配置Gateway会将请求转换为http://localhost:8098/service-consumer/user/info。以此作为前端请求的最终目的地。
04 Gateway请求匹配
Gateway网关可以根据不同的方式进行匹配进而把请求分发到不同的后端服务上。
通过header进行匹配,把请求分发到不同的服务上,配置如下:
spring:cloud:gateway: routes: - id: header_route uri: http://baidu.com predicates: - Header=X-Request-Id, d+
通过curl测试:curl http://localhost:8080 -H "X-Request-Id:666666