在微服务架构里,服务的粒度被进一步细分,各个业务服务能够被独立的设计、开发、测试、部署和管理。这时,各个独立部署单元能够用不一样的开发测试团队维护,可使用不一样的编程语言和技术平台进行设计,这就要求必须使用一种语言和平台无关的服务协议做为各个单元间的通信方式。java
换句话说就是网关为全部的请求提供了统一的入口,方便咱们对服务请求和响应作统一管理。正则表达式
API 网关是一个处于应用程序或服务(提供 REST API 接口服务)以前的系统,用来管理受权、访问控制和流量限制等,这样 REST API 接口服务就被 API 网关保护起来,对全部的调用者透明。算法
Spring Cloud Gateway是Spring官方基于Spring 5.0,Spring Boot 2.0和Project Reactor等技术开发的网关,Spring Cloud Gateway旨在为微服务架构提供一种简单而有效的统一的API路由管理方式。Spring Cloud Gateway做为Spring Cloud生态系中的网关,目标是替代ZUUL,其不只提供统一的路由方式,而且基于Filter链的方式提供了网关基本的功能,例如:安全,监控/埋点,和限流等。spring
客户端向Spring Cloud网关发出请求。若是网关处理程序映射肯定请求与路由匹配,则将其发送到网关Web处理程序。该处理程序运行经过特定于请求的过滤器链发送请求。过滤器由虚线分隔的缘由是,过滤器能够在发送代理请求以前或以后执行逻辑。执行全部“前置”过滤器逻辑,而后发出代理请求。发出代理请求后,将执行“后”过滤器逻辑。编程
路由和过滤器是gateway中很是重要的两个概念,gateway自己提供了很是丰富的路由规则和多种过滤器来适配咱们的需求。gateway提供了11种路由规则,分别是:安全
后置路由谓词工厂cookie
该谓词匹配在当前日期时间以后发生的请求。参数名为 After架构
前置路由谓词工厂app
该谓词匹配当前日期时间以前发生的请求。参数名为 Before编程语言
时间段路由谓词工厂
该谓词匹配在datetime1以后和datetime2以前发生的请求。参数名为 Between
cookie路由谓词工厂
该谓词匹配具备给定名称的cookie,而且值匹配正则表达式。参数名为 Cookie
标头路由谓词工厂
该谓词与具备给定名称的标头匹配,而且值与正则表达式匹配。参数名为 Header
主机路由谓词工厂
该谓词是指由路由进行匹配,匹配多个路由时用,隔开。参数名为 Host
方法路由谓词工厂
该参数是一个或多个要匹配的HTTP方法。参数名为 Method
路径路由谓词工厂
该谓词是指在请求路径上加一个前缀,以此来匹配。参数名为 Path
查询路由谓词工厂
RemoteAddr路由谓词工厂
其中,咱们比较经常使用的就是路径路由谓词工厂,配合StripPrefix GatewayFilter工厂,实现咱们的路由匹配转发。
路径路由谓词工厂配置以下:
spring: cloud: gateway: discovery: locator: enabled: true # 开启从注册中心动态建立路由的功能,利用微服务名称进行路由 routes: # 路由id,建议配合服务名 - id: demo_route #匹配路由名 uri: lb://demo-provider predicates: # 断言,路径相匹配的进行路由 - Path=/demo/**
配置的含义就是,若是请求路径中是/demo/**,则转发到demo-provider服务。
在spring cloud gateway 2.2.2.RELEASE版本中,已经默认实现了30种过滤器。
序号 | 过滤器工厂 | 做用 | 参数 |
---|---|---|---|
1 | AddRequestHeader | 为原始请求添加Header | Header的名称及值 |
2 | AddRequestParameter | 为原始请求添加请求参数 | 参数名称及值 |
3 | AddResponseHeader | 为原始响应添加Header | Header的名称及值 |
4 | DedupeResponseHeader | 剔除响应头中重复的值 | 须要去重的Header名称及去重策略 |
5 | Hystrix | 为路由引入Hystrix的断路器保护 | HystrixCommand的名称 |
6 | CircuitBreaker | 为路由引入Resilience4J断路器保护 | CircuitBreaker的名称 |
7 | FallbackHeaders | 为fallbackUri的请求头中添加具体的异常信息 | Header的名称 |
MapRequestHeader | 更新原始请求中的Header | Header的值 | |
9 | PrefixPath | 为原始请求头添加前缀 | 前缀路径 |
10 | PreserveHostHeader | 为请求添加preserverHostHeader=true的属性,路由过滤器会检查该属性以决定是否要发送原始的host | 无 |
11 | RequestRateLimiter | 用于对请求限流,限流算法为令牌桶 | keyResolver、rateLimiter、statusCode、denyEmptyKey、emptyKeyStatus |
12 | RedirectTo | 将原始请求重定向到指定的url | http状态码及重定向的url |
13 | RemoveHopByHopHeadersFilter | 为原始请求删除IETF组织规定的一系列Header | 默认就会启用,能够经过配置指定仅删除哪些Header |
14 | RemoveRequestHeader | 为原始请求删除某个Header | Header名称 |
15 | RemoveResponseHeader | 为原始响应删除某个Header | Header名称 |
16 | RewritePath | 重写原始的请求路径 | 原始路径正则表达式以及重写后路径的正则表达式 |
RewriteLocationResponseHeader | 重写响应头的Location 的值 |
||
18 | RewriteResponseHeader | 重写原始响应中的某个Header | Header名称,值的正则表达式,重写后的值 |
19 | SaveSession | 在转发请求以前,强制执行WebSession::save 操做 |
无 |
20 | SecureHeaders | 为原始响应添加一系列起安全做用的响应头 | 无,支持修改这些安全响应头的值 |
21 | SetPath | 修改原始的请求路径 | 修改后的值 |
22 | SetRequestHeader | 修改原始请求中的某个Header的值 | Header名称,修改后的值 |
23 | SetResponseHeader | 修改原始响应中某个Header的值 | Header名称,修改后的值 |
24 | SetStatus | 修改原始响应的状态码 | HTTP 状态码,能够是数字,也能够是字符串 |
25 | StripPrefix | 用于截断原始请求的路径 | 使用数字表示要截断的路径的数量 |
26 | Retry | 针对不一样的响应进行重试 | retries、statuses、methods、series |
27 | RequestSize | 设置容许接收最大请求包的大小。若是请求包大小超过设置的值,则返回 413 Payload Too Large 设置容许接收最大请求包的大小。若是请求包大小超过设置的值,则返回 413 Payload Too Large |
请求包大小,单位为字节,默认值为5M |
28 | ModifyRequestBody | 在转发请求以前修改原始请求体内容 | 修改后的请求体内容 |
29 | ModifyResponseBody | 修改原始响应体的内容 | 修改后的响应体内容 |
30 | Default | 为全部路由添加过滤器 | 过滤器工厂名称及值 |
这里比较经常使用的如第25种,配置以下:
spring: cloud: gateway: discovery: locator: enabled: true # 开启从注册中心动态建立路由的功能,利用微服务名称进行路由 routes: # 路由id,建议配合服务名 - id: demo_route #匹配路由名 uri: lb://demo-provider predicates: # 断言,路径相匹配的进行路由 - Path=/demo/** filters: - StripPrefix=1
通常状况下咱们配合path路由使用,这里的意思是假如,咱们的demo-provider服务种有一个/test的接口,实际上咱们的请求路径通过网关时应该时/demo/test,这样就能把这个路由分发到demo-provider服务中,可是分发过去的路由是/demo/test,和咱们实际的/test接口不同。这时候咱们用StripPrefix=1,来截取掉一级路由,这样转发过去的路由就是/test了。
除了上面提供的30种过滤器外,咱们还能够实现自定义的过滤器。
gatewayFilter接口是为了实现请求过滤,ordered接口是为了给过滤器设定优先级,值越大级别越低。
想要实现一个自定义的过滤器,无非就是两个步骤:1.实现过滤器,2.将过滤器添加到具体路由上。
public class TokenGatewayFilter implements GatewayFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { System.out.println("这里处理自身逻辑"); return chain.filter(exchange); } @Override public int getOrder() { return 0; } } @Configuration class RouteConfiguration{ @Bean public RouteLocator routeLocator(RouteLocatorBuilder builder){ return builder.routes().route( r-> r.path("/demo/**") .uri("lb://demo-provider ") .filter(new TokenGatewayFilter()) .id("demo_route ")) .build(); } }
@Component public class TokenCheckGatewayFilterFactory extends AbstractGatewayFilterFactory<TokenCheckGatewayFilterFactory.Config> { public TokenCheckGatewayFilterFactory() { super(Config.class); } @Override public List<String> shortcutFieldOrder() { return Arrays.asList("enabled"); } @Override public GatewayFilter apply(Config config) { return (exchange, chain) -> { system.out.println("这里处理自身逻辑") return chain.filter(exchange); }; } public static class Config { // 控制是否开启认证 private boolean enabled = true; public Config() {} public boolean isEnabled() { return enabled; } public void setEnabled(boolean enabled) { this.enabled = enabled; } } }
这里咱们能够直接在application.yml中为须要过滤的路由添加这个过滤器。
spring: cloud: gateway: routes: - id: demo_route # 路由id,建议配合服务名 uri: lb://demo-provider #匹配路由名 predicates: - Path=/demo/** # 断言,路径相匹配的进行路由 filters: - TokenCheck=true
须要注意的是,这个地方自定义的过滤器名称必须是XXGatewayFilterFactory,而且配置文件中配置过滤器时名字必须时这个XX。
固然,咱们也能够为每一个路由都添加这个过滤器,能够直接这样写配置,而不用在每一个路由上都去写。
spring: cloud: gateway: default-filters: - TokenCheck=true
这个GlobalFilter从名字中就能够看出,是一个全局过滤器,也就是说实现这个接口后,全部的请求都会被过滤,咱们就不须要在去找往某个路由中加过滤器了。
@Component public class TokenGlobalFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { System.out.println("这里处理自身逻辑"); return chain.filter(exchange); } @Override public int getOrder() { return 0; } }
以上就是实现自定义网关过滤器的三种方式了。实际开发中根据需求来实现合适的过滤器就能够了。