2.3 Gateway网关服务
一、网关作用介绍
网关功能:
身份认证和权限校验
服务路由、负载均衡
请求限流
SpringCloud中实现网关的两个组件
gateway:基于Spring5中提供的WebFlux,属于响应式编程,具备更好的性能
zuul(已停止维护):Zuul是基于Servlet的实现,属于阻塞式编程
二、快速入门
搭建网关服务
坐标依赖:
<!-- Gateway组件依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!-- Nacos发现依赖 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!-- 需要引入负载均衡依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency>备注:SpringBoot2.4以及以上版本需要手动导入负载均衡依赖,否则报错!!!!
编写配置文件以及nacos地址
server: port: 10010 spring: application: name: gateway cloud: nacos: server-addr: 49.233.26.144:60000 # nacos地址 gateway: # 网关配置 routes: # 网关路由配置 - id: user-service # 路由标识,自定义,只要唯一即可 # uri: http://127.0.0.1:8081 # 路由的目标地址 http就是一个固定地址,不建议使用 uri: lb://user-service # 路由目标地址 lb是负载均衡,后面跟随服务名称 强烈推荐 predicates: # 路由断言,也就是判断请求是否符合路由规则的条件 - Path=/user/** # 这格式按照路径匹配,只要是以/user/开头的就符合要求,路径断言
三、路由断言工厂
网关路由可以配置的内容包括:
路由id:路由唯一标识
uri:路由目的地,支持lb和http两种
predicates:路由断言,判断请求是否符合要求,符合要求才会转发到路由目的
filters:路由过滤器,处理请求或响应
路由断言工厂(Route Predicate Factory)
我们在配置文件中写的断言规则只是字符串,这些字符串会被Predicate Factory读取并处理,转变为路由判断的条件
例如
Path=/user/**是按照路径匹配的,这个规则是由org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory类来处理的像这样的断言工厂不还有10多个
Spring提供了11种基本的断言工厂
名称说明示例After
是某个时间点后的请求
- After=2037-01-20T17:42:47.789-07:00[America/Denver]
Before
是某个时间点之前的请求
- Before=2031-04-13T15:14:47.433+08:00[Asia/Shanghai]
Between
是某两个时间点之间的请求
- Between=2037-01-20T17:42:47.789-07:00[America/Denver],2037-03-20T17:42:47.789-07:00[America/Denver]
Cookie
请求必须包含某些cookie
- Cookie=chocolate,ch.p
Header
请求种必须包含某些Header
- Header=X-Request-Id,\d+
Host
请求必须是访问某个Host(域名)
- Host=**.lonelysnow.cn
Method
请求方式必须是指定方式
- Method=GET, POST
Path
请求路径必须符合指定规则
- Path=/red/{segment},/blue/**
Query
请求参数必须包含指定参数
- Query=name,Jack
RemoteAddr
请求者的ip必须是指定范围
- RemoteAddr=192.168.1.1/24
Weight
权重处理
备注:如果有使用的,可以直接官方查看文档,表格中的示例也是使用方式
四、路由过滤器配置——GatewayFilter
GatewayFilter是网关中提供的一种过滤器,可以对进入网关的请求和微服务返回的相应做处理
Spring提供了31中过滤工厂,例如:
名称说明AddRequestHeader
给当前请求添加一个请求头
RemoveRequestHeader
移除请求中的一个请求头
AddResponseHeader
给响应结果中添加一个响应头
RemoveResponseHeader
移除响应结果中的一个响应头
RequestRateLimiter
限制请求的流量
……
……
备注:其他详细的可以到官网上查看
给服务添加过滤器配置:
spring: cloud: gateway: routes: # 网关路由配置 - id: user-service # 路由id,自定义,只要唯一即可 # uri: http://127.0.0.1:8081 # 路由的目标地址 http就是一个固定地址,不建议使用 uri: lb://user-server # 路由目标地址 lb是负载均衡,后面跟随服务名称 强烈推荐 predicates: # 路由断言,也就是判断请求是否符合路由规则的条件 - Path=/user/** # 这格式按照路径匹配,只要是以/user/开头的就符合要求 filters: # 只给userService加请求头 - AddRequestHeader=Truth,addHeader OK # 添加一个请求头内容 - id: order uri: lb://order-service predicates: - Path=/order/**配置全局默认过滤器(所有请求均生效)
spring: gateway: routes: # 网关路由配置 - id: user-service # 路由id,自定义,只要唯一即可 # uri: http://127.0.0.1:8081 # 路由的目标地址 http就是一个固定地址,不建议使用 uri: lb://user-server # 路由目标地址 lb是负载均衡,后面跟随服务名称 强烈推荐 predicates: # 路由断言,也就是判断请求是否符合路由规则的条件 - Path=/user/** # 这格式按照路径匹配,只要是以/user/开头的就符合要求 # filters: # 只给userService加请求头 # - AddRequestHeader=Truth,addHeader OK # 添加一个请求头内容 - id: order uri: lb://order-service predicates: - Path=/order/** default-filters: # 配置全局默认过滤器 - AddRequestHeader=Truth,addHeader OK
五、全局过滤器——GlobalFilter
全局过滤器的作用也是处理一切进入网管的请求和微服务响应,与GatewayFilter的作用一样,类似default-filters
区别在于GatewayFilter通过配置定义,处理逻辑是固定的,而GlobalFilter的逻辑需要自己写代码实现
定义方法:实现GlobalFilter接口
// 接口介绍 public interface GlobalFilter { /** * 处理当前请求,有必要的话通过{@link GatewayFilterChain}将请求交给下一个过滤器处理 * * @param exchange 请求上下文,这里可以获取Request、Response等信息 * @param chain 用来把请求委托给下一个过滤器 * @return {@code Mono<void>} 返回标识当前过滤器业务结束 */ Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain); }案例:定义全局过滤器,拦截请求,判断请求的参数是否满足以下条件
参数中是否有authorization,
authorization参数值是否为admin
同时满足上面两个条件,放行,否则拦截
// 交给Spring管理 @Component // 过滤器执行顺序 //@Order(-1) public class AuthorFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // 获取请求参数 ServerHttpRequest request = exchange.getRequest(); MultiValueMap<String, String> params = request.getQueryParams(); // 获取参数中的authorization String auth = params.getFirst("authorization"); // 判断值是否为admin;是,放行;否,拦截 if ("admin".equals(auth)) { // 放行 return chain.filter(exchange); } // 设置状态码,不然直接结束没有相应 exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); // 拦截,直接结束 return exchange.getResponse().setComplete(); } @Override public int getOrder() { return -1; } }备注:过滤器一定要定义顺序,可以使用注解直接定义,也可以实现接口
六、过滤器执行顺序
请求进入网关会碰到三类过滤器:当前路由的过滤器、DefaultFilter、GlobalFilter
请求路由后,会将当前路由过滤器和DefaultFilter、GlobalFilter,合并到一个过滤器链中(集合中),排序后依次执行每个过滤器
每一个过滤器都必须指定一个int类型的order值,,order值越小,优先级越高,执行顺序越靠前
GlobalFilter通过实现Ordered接口,或者添加@Order注解来指定order值,由我们自己指定
路由过滤器和defaultFilter的order由Spring指定,默认是按照声明顺序,从1递增
当过滤器的order值相同时,会按照 deaultFilter > 路由过滤器 > GlobalFilter的顺序执行
七、CORS跨域配置
跨域:域名不一致就是跨域,主要包括:
域名不同:包括二级域名不同
域名相同,端口不同
跨域问题:浏览器禁止请求的发起者与服务器端发生跨域Ajax请求,请求被浏览器拦截的问题
解决方案:CORS
Gateway配置跨域请求
spring: cloud: gateway: globalcors: add-to-simple-url-handler-mapping: true # 解决options请求被拦截的问题 cors-configurations: '[/**]': allowedOrigins: # 允许那些网站的跨域请求 - "http://localhost:8090" - "http://域名" allowedMethods: # 允许的跨域Ajax请求方式 - "GET" - "POST" - "DELETE" - "PUT" - "OPTIONS" allowedHeaders: "*" # 允许在请求中携带头信息 allowCredentials: true # 是否允许携带Cookie maxAge: 36000 # 这次跨域检测的有效期
最后更新于
这有帮助吗?