微服务架构 | 服务网关 - [Gateway]
@
§1 官网与简介
Zuul
Gateway
This project provides a library for building an API Gateway on top of Spring WebFlux. Spring Cloud Gateway aims to provide a simple, yet effective way to route to APIs and provide cross cutting concerns to them such as: security, monitoring/metrics, and resiliency.
特性:
- Built on Spring Framework 5, Project Reactor and Spring Boot 2.0
- Able to match routes on any request attribute
- Predicates and filters are specific to routes
- Circuit Breaker integration
- Spring Cloud DiscoveryClient integration
- Easy to write Predicates and Filters
- Request Rate Limiting
- Path Rewriting
对比:
- 由 Springcloud 团队打造,天然亲和 Springcloud 生态,更新和社区更友好
- 底层使用 webflux(相比web mvc 非阻塞) 的 reactor-netty 响应式编程组件,zuul 底层是基于 servlet 的阻塞式 I/O,高并发上有优势
- 整合 Spring5 / project reactor / springboot / websocket 等
网关在微服务架构中的位置
组成、工作流程和作用:
网关由路由、断言、过滤器构成:
- 断言:起比较作用,可以比较请求的所有部分,比较后匹配的由路由处理
- 路由:由 ID 、url、断言、过滤器组成,最终由它决定请求交给哪个服务接口处理
- 过滤:由 spring gateway filter 实例实现,可以在请求前后进行一些操作,比如请求重写
通过上述组件可以实现:
- 反向代理
- 鉴权
- 流量控制
- 熔断
- 日志监控
- 重写
§2 简单使用(路由)
依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
注意,网关的使用需要 排除 下面两个依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
配置
YML 方式
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: payment_routh #payment_route #路由的唯一id
uri: http://localhost:8001 #服务的路由地址
predicates:
- Path=/payment/get/** # 服务下接口的地址
#多个路由如下配置
- id: payment_routh2 #payment_route
uri: lb://cloud-payment-service #配置 spring.cloud.gateway.discovery.locator.enabled = true后,可以使用服务名作为服务地址
predicates:
- Path=/payment/lb/**
Configuration 方式
@Configuration
public class GatewayRoutelocatorConfig {
@Bean
RouteLocator routeLocator(RouteLocatorBuilder builder){
RouteLocatorBuilder.Builder routes = builder.routes();
routes.route("n",
r->r.path("/").uri("http://www.gamersky.com/"));
return routes.build();
}
}
§3 常用断言
由 RoutePredicateFactory 实现
§3.1 path
Path 路由断言工厂接收一个参数,根据 Path 定义好的规则来判断访问的 URI 是否匹配。
spring:
cloud:
gateway:
routes:
- id: host_route
uri: http://c.biancheng.net
predicates:
- Path=/blog/detail/{segment}
如果请求路径为 /blog/detail/xxx,则此路由将匹配。也可以使用正则,例如 /blog/detail/** 来匹配 /blog/detail/ 开头的多级 URI。
path 断言匹配成功后会将断言部分拼接上 uri 作为实际请求路径
即,若断言为 /a,那实际路径一定是 http://....../a
示例
http://localhost:9527/blog/detail/36185 -->
http://c.biancheng.net/blog/detail/36185
§3.2 query
Query 路由断言工厂接收两个参数
- 一个必需的参数,用于匹配请求中的 query 字段
- 一个可选的正则表达式,用于匹配请求中的 query 字段的值
spring:
cloud:
gateway:
routes:
- id: query_route
uri: http://c.biancheng.net
predicates:
- Query=foo, ba.
示例
http://localhost:2001/?foo=baz
§3.3 method
Method 路由断言工厂接收一个参数,匹配的是 http 的 method
spring:
cloud:
gateway:
routes:
- id: method_route
uri: http://baidu.com
predicates:
- Method=GET
§3.4 header
Header 路由断言工厂接收两个参数
- 一个必需的参数,用于匹配请求中的请求头名称
- 一个可选的正则表达式,用于匹配请求中的请求头的值
spring:
cloud:
gateway:
routes:
- id: header_route
uri: http://example.org
predicates:
- Header=X-Request-Id, \d+
§3.5 cookie
cookie 路由断言工厂接收两个参数
- 一个必需的参数,用于匹配请求中的 cookie 名
- 一个可选的正则表达式,用于匹配请求中的 cookie 的值
spring:
cloud:
gateway:
routes:
- id: query_route
uri: http://c.biancheng.net
predicates:
- Cookie=chocolate, ch.p
§3.6 时间
时间匹配规定路由路由规则生效的时间范围,有三种模式
- Before
- After
- Between
时间格式要求为带有时区的时间戳,对应 ZoneDateTime
spring:
cloud:
gateway:
routes:
- id: query_route
uri: http://c.biancheng.net
predicates:
- Between=2022-01-20T17:42:47.789-07:00[Asia/Shanghai],2023-01-20T17:42:47.789-07:00[Asia/Shanghai]
§4 过滤器
由 GatewayFilterFactroies 实现,原理和 servlet 的 filter 类似。
filter 分为两类
- gateway filter
- global filter
§4.1 预设过滤器(TODO)
§4.2 自定义过滤器(TODO)
加入类扫描,实现默认接口
- GlobalFilter 全局过滤接口
- Order 用于指定优先级
注意 Gateway 的 filter 可以实现拦截器的功能
@Component
@Slf4j
public class TestGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("<<<TestGlobalFilter>>> start");
String name = exchange.getRequest().getQueryParams().getFirst("name");
if(StringUtils.isEmpty(name)){
log.info("<<<TestGlobalFilter>>> no-name");
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
本文部分内容来自 Spring Cloud Gateway的常用路由断言工厂
传送门:
微服务架构 | 组件目录