关于服务网关Gateway-Spring Cloud Gateway
前置知识
WebFlux:点击-Spring WebFlux 是一个异步非阻塞式 IO 模型,通过少量的容器线程就可以支撑大量的并发访问。底层使用的是 Netty 容器,这点也和传统的 SpringMVC 不一样,SpringMVC 是基于 Servlet 的。
概述
Gateway 是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能Reactor模式通信框架Netty。由于基于异步非阻塞模型上开发的,性能比较高。
Gateway 的目标 提供统一路由方式 且基于Filter链的方式 提供了网关基本的功能,安全、监控/指标、限流等。
Gateway 相当于所有服务的门户,将客户端请求与服务端应用相分离,客户端请求通过 Gateway 后由定义的路由和 Predicate(
断言)和 Filter
(过滤器)进行转发,路由代表需要转发请求的地址,断言相当于请求这些地址时所满足的条件,只有同时符合路由和断言才给予转发。
功能
- 反向代理;
- 鉴权;
- 流量控制;
- 熔断;
- 日志监控。
特性
- 动态路由:能够匹配任何请求属性;
- 可以对路由指定
Predicate
(断言)和Filter
(过滤器); - 集成
Hystrix
的断路器功能; - 集成
Spring Cloud
的服务发现功能; - 易于编写
Predicate
和Filter
; - 请求限流功能;
- 支持路径重写。
图示描述
核心概念
Router(路由):是构建网关的基本模块,由ID和目标URI和一系列的断言和过滤器组成,如果断言为true则匹配该路由。
Predicate(断言):可以匹配Http请求中的所有内容,如果请求与断言相匹配则进行路由。
- After:在某时间之后才能访问;
- Before:在某时间之前才能访问;
- Between:在某时间之间才能访问;
- Cookie:验证Cookie中保存的信息
- Header:检查Header中是否包含了响应的属性
- Method:请求类型;
- Path:即指定当前网关的路径与实际路径的映射。
- Query:判断QueryPrameters列表是否存在指定值;
Filter(过滤):使用过滤器,可以在路由被请求前或者请求后对请求进行修改。
描述:根据web请求和匹配条件,定位到真正的服务节点。并在这个转发过程的前后,进行一些精细化控制。即根据predicate的匹配条件,通过过滤器,再加上uri来实现具体的路由。
GatewayFilter
:针对某个请求的过滤器;GlobalFitler
:全局过滤器。
自定义全局过滤器:继承implements GlobalFilter, Ordered
接口。
工作流程
- 客户端向Spring Cloud Gateway发出请求;
- 然后再Gateway Handler Mapping中找到与请求相匹配的路由;
- 将其发送到Gateway Web Handler;
- Handler再通过指定的过滤器链来将请求发送到实际业务执行逻辑中,返回。
- 请求前过滤器(pre):参数校验、权限校验、流量监控、日志输出、协议转换。
- 请求后过滤器(post):响应内容和响应头修改,日志输出,流量监控等。
一、鉴权实现
在所有的客户端请求在经过gateway时,都会被拦截下来,并进行统一的权限判断处理,校验权限信息,如果不通过会返回指定结果,当然也可以在代码中定义指定的路径不受权限的控制。
通过实现GlobalFilter和Ordered这两个接口中的filter(进行全局过滤)和getOrder(指定过滤器的优先级)方法
其中,FilterChain维护了一个链表,链表中存放着配置对象的链条,每次用户调用 一次chain.doFilter(request, response),链表就去取下一个配置对象,再通过配置对象 得到下一个filter,然后调用该filter,接着在filter里写的逻辑就被执行了。
package com.wudimanong.gateway.filter; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import org.springframework.http.HttpStatus; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; /** * @author jiangqiao * @说明:全局过滤器,进行统一的URL过滤及权限认证 */ @Configuration public class AuthSignatureGlobalFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { String requestPath = exchange.getRequest().getPath().value(); //判断接口情况地址如果为内部服务定义,则拦截 if (requestPath.contains("internal")) { exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete(); } //应用accessToken有效性(这里只是简单判空,可以根据实际业务场景进行扩展) String accessToken = exchange.getRequest().getHeaders().getFirst("access_token"); if (accessToken == null) { exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete(); } //正常进行返回 return chain.filter(exchange); } @Override public int getOrder() { return -1; } }
二、路由实现
gateway根据路由与断言去转发请求到指定的服务,gateway服务中的配置文件中配置
spring: cloud: gateway: #开启网关服务注册发现机制 discovery: locator: enabled: true #路由配置(网关基本构建模版,由id、目标uri、一组predicates及一组filters构成) routes: - id: sso-resourceserver #lb代表从注册中心获取服务,格式为lb://$(注册服务的名字) uri: lb://sso-resourceserver predicates: #通过路径进行匹配 - Path=/resources/** filters:
#StripPrefix 能够帮我们去调用户请求中的虚拟路径 - StripPrefix=1
三.跨域实现
概念:指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制。
• 同源策略:是指协议,域名,端口都要相同,其中有一个不同都会产生跨域;
解决跨域方法:
解决跨域 -(一)使用nginx部署为同一域
解决跨域 -(二)配置当次请求允许跨域•1、添加响应头•Access-Control-Allow-Origin:支持哪些来源的请求跨域•Access-Control-Allow-Methods:支持哪些方法跨域•Access-Control-Allow-Credentials:跨域请求默认不包含cookie,设置为true可以包含cookie•Access-Control-Expose-Headers:跨域请求暴露的字段•CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。•Access-Control-Max-Age:表明该响应的有效时间为多少秒。在有效时间内,浏览器无须为同一请求再次发起预检请求。请注意,浏览器自身维护了一个最大有效时间,如果该首部字段的值超过了最大有效时间,将不会生效
spring: cloud: gateway: globalcors: cors-configurations: '[/**]': # 匹配所有请求 allowedOrigins: "*" #跨域处理 允许所有的域 allowedMethods: # 支持的方法 - GET - POST - PUT - DELETE