
目录一. 为什么需要网关二. 网关最流行的两种技术实现与分析三. gateway 快速入门四. 断言工厂五. 过滤器5.1 路由过滤器GatewayFilter5.2 全局过滤器GlobalFilter5.3 过滤器链执行顺序六. 网关的cors跨域配置其它微服务组件文章合集有需要的小伙伴可跳转观看SpringCloud——Eureka 微服务注册中心组件使用教程SpringCloudAlibaba——Nacos 微服务注册配置功能组件使用教程SpringCloud——OpenFeign 微服务远程调用组件使用教程SpringCloud——gateway 微服务网关组件使用教程SpringCloud——Ribbon 微服务负载均衡原理解析一. 为什么需要网关一个微服务项目正常来说应该是任何人都可以来访问的但如果有恶意攻击会对我们的业务造成一定的损失。因此在实际业务中当一个请求来了之后我们应该先对他进行校验看看他要浏览什么然后将这个请求转到对应的服务模块中去。这是不是和我们之前学习的过滤器与拦截器有些相似其实也可以这么理解。那么对引出了我们网关的功能(1)身份认证与权限校验我们肯定是不能允许所有的请求都到达我们的服务器的要先进行认证校验只有符合的我才放行。(2)服务路由负载均衡他可以结合我们之前所学的Ribbon当有多个请求到达服务器请求同一个功能时我们都可以在通过一个功能的不同模块中挑一个去响应达到一个负载均衡。(3)请求限流这个很好理解当有大量的请求都想要访问我们的服务器时是不允许所有的请求都进入的假设微服务只允许2000个请求现在来了10000个肯定是不能让所有的请求都进入的不然服务器就炸了所以它有请求限流的效果。二. 网关最流行的两种技术实现与分析在当下网关有两种比较流行的实现方式分别是 zuul 和 gateway。Zuul是基于Servlet的实现属于阻塞式编程。Gateway则是基于Spring5中提供的WebFlux实现属于响应式编程吞吐能力更强具有更好的性能。本篇文章我们就聊 GateWay三. gateway 快速入门想要搭建网关功能有以下步骤(1) 创建新的moudle模块引入SpringCloudGateway依赖和nacos服务发现依赖如下!--nacos服务注册发现依赖-- dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId /dependency !--网关gateway依赖-- dependency groupIdorg.springframework.cloud/groupId artifactIdspring-cloud-starter-gateway/artifactId /dependency这里gateway依赖好理解引入nacos服务注册发现依赖是因为刚操我i们也说了创建新的模块所以这个gateway自然也是我们微服务的一部分所以要引入nacos服务发现依赖。(2) 配置路由规则要写在gateway模块中的yml文件中写入规则如下server: port: 10010 logging: level: cn.itcast: debug pattern: dateformat: MM-dd HH:mm:ss:SSS spring: application: name: gateway cloud: nacos: server-addr: nacos:8848 # nacos地址 gateway: routes: - id: user-service # 路由标示必须唯一 uri: lb://userservice # 路由的目标地址 predicates: # 路由断言判断请求是否符合规则 - Path/user/** # 路径断言判断路径是否是以/user开头如果是则符合 - id: order-service uri: lb://orderservice predicates: - Path/order/**这里我来解释几个重要的配置server 配置自身的端口号spring.application.name 配置该为服务模块的名称cloud.nacos.server-addr 配置nacos地址方便后续被nacos发现gateway.routes就是路由这里可以配置多个我写了user-service和order-service后续你有几个微服务就可以写几个使用- id表示一个数组有多个参数- id 为路由标识必须唯一我们可以使用微服务模块的名称uri这里建议写服务名称lb: 表示负载均衡predicates 表示路径断言可以配置多个只要请求路径匹配其中的一个就可以放行。完成上述两步之后我们就可以启动gateway模块了四. 断言工厂上述我们在yml文件中写的所有断言规则都是字符串这些字符串到最后都会被Predicate Factory(断言工厂)读取并处理转变成路由规则去做判断。这里我们主要来说predicates这个属性其实它的属性有很多如下图这里的说明和示例也很清晰就不展示了但其中最常用的还是Path。五. 过滤器5.1 路由过滤器GatewayFilter上面我们说到了网关可以对我们的请求进行身份认证与权限校验然后发送到对应的微服务。但其实在发送之前通常还是需要进一步进行加工操作的。经过层层过滤器最终到达我们的微服务当然响应返回的时候也是一样的道理。我么就可以在过滤器中设置一些参数对我们的请求进行加工如下图Spring官网给我们提供了很多很多中不同的过滤器这里我就简单列举几个我来展示一下它们的用法过滤器也是分为局部路由生效和全局路由生效的局部路由生效可以将过滤器配置设置在yml文件中路由id的下一级如下所示然后在对应的Controller方法中添加请求头参数RequestHeadervalue指定获取的值required false表示可获取可不获取有就加上没有就不加。GetMapping(/{id}) public User queryById(PathVariable(id) Long id, RequestHeader(value Truth, required false) String truth){ System.out.println(truth: truth); return userService.queryById(id); }这里过滤器可以设置多个所以采用数组的方式。全局路由生效可以将过滤器设置到与routes(网关路由配置同一级),它会对所有的路由生效采用默认过滤器如下获取请求头的方式和刚才一样设置RequestHeader即可。5.2 全局过滤器GlobalFilter全局过滤器的作用和刚才的路由过滤器作用非常一样。区别在于GatewayFilter通过配置实现处理逻辑是固定的。而GlobalFilter的逻辑是需要自己代码实现更加灵活。全局过滤器GlbalFilter的实现方式时实现GlobalFilter接口。需要实现的接口如下这里我就简单写一个案例定义一个全局过滤器拦截并判断用户身份判断请求参数中是否满足以下条件1参数中是否有anthorization2authorization中的参数是否为admin如果同时满足则放行不满足则拦截代码如下Component public class AuthorizeFilter implements GlobalFilter, Ordered { Override public MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain) { // 1.获取请求参数 ServerHttpRequest request exchange.getRequest(); MultiValueMapString, String params request.getQueryParams(); // 2.获取参数中的 authorization 参数 String auth params.getFirst(authorization); // 3.判断参数值是否等于 admin if (admin.equals(auth)) { // 4.是放行 return chain.filter(exchange); } // 5.否拦截 // 5.1.设置状态码 exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); // 5.2.拦截请求 return exchange.getResponse().setComplete(); } Override public int getOrder() { return -1; } }5.3 过滤器链执行顺序请求在进入路由后会遇到三类过滤器当前路由过滤器DefalutFilterGlobalFilter。上述三类过滤器会合并到一个过滤器链中排好序依次执行。那么他们有是按照什么样的顺序去执行的呢有以下四种规则(1) 每个过滤器必须指定一个int类型的order值order越小优先级越高执行顺序越靠前。(2) GlobalFilter通过实现Ordered接口或者添加Order注解来指定Order值由我们自己指定。在5. (2) 中我采用了实现接口的方式。(3) 路由过滤器和DefalutFilter有Spring指定默认是按照声明顺序从1递增。(4) 当过滤器的Order值一样时会按照defalutFilter 路由过滤器 GlobalFilter 执行顺序去执行。六. 网关的cors跨域配置域名不一致就是跨域主要包括域名不同例如www.taobao.com和www.taobao.org一级域名不同www.haust.teacher和www.jd.com二级域名也不同。域名相同端口不同例如localhost:8080与localhost:8081端口不同。那么话说回来跨域一定会有问题吗其实也不是就像我们的localhost;8080和localhost8081都是微服务中userservice模块的端口它们互相访问并不会有问题。所以这里要明白一点跨域问题是 “浏览器禁止请求的发起者与服务端发生跨域ajax请求请求被浏览器拦截的问题”。网关解决跨域问题的解决方案即使CORS这里底层逻辑已经帮我们实现好了我们只需要做简单的配置即可。配置完成之后我们重启项目输入localhost:8090/user/1也可以查询到id为1的用户信息。