网站建设公司发展理念,计算机培训机构,seo网络排名优化技巧,菏泽建设局网站Gateway网关
1、网关的位置与作用
官网#xff1a;Spring Cloud Gateway
Geteway是Zuul的替代#xff0c;
Zuul#xff1a;路由和过滤Zuul最终还是会注册到Eureka Zuul网关采用同步阻塞模式不符合要求。 Spring Cloud Gateway基于Webflux#xff0c;比较完美地支持异步…Gateway网关
1、网关的位置与作用
官网Spring Cloud Gateway
Geteway是Zuul的替代
Zuul路由和过滤Zuul最终还是会注册到Eureka Zuul网关采用同步阻塞模式不符合要求。 Spring Cloud Gateway基于Webflux比较完美地支持异步非阻塞编程很多功能实现起来比较方便。 一、相同点 1、底层都是servlet 2、两者均是web网关处理的是http请求 二、不同点 1、内部实现 gateway对比zuul多依赖了spring-webflux在spring的支持下功能更强大内部实现了限流、负载均衡等扩展性也更强但同时也限制了仅适合于Spring Cloud套件 zuul则可以扩展至其他微服务框架中其内部没有实现限流、负载均衡等。2、是否支持异步 zuul仅支持同步 gateway支持异步。理论上gateway则更适合于提高系统吞吐量但不一定能有更好的性能最终性能还需要通过严密的压测来决定3、框架设计的角度 gateway具有更好的扩展性并且其已经发布了2.0.0的RELESE版本稳定性也是非常好的4、性能 WebFlux 模块的名称是 spring-webflux名称中的 Flux 来源于 Reactor 中的类 Flux。Spring webflux 有一个全新的非堵塞的函数式 Reactive Web 框架可以用来构建异步的、非堵塞的、事件驱动的服务在伸缩性方面表现非常好。使用非阻塞API。 Websockets得到支持并且由于它与Spring紧密集成所以将会是一个更好的 开发 体验。 Zuul 1.x是一个基于阻塞io的API Gateway。Zuul已经发布了Zuul 2.x基于Netty也是非阻塞的支持长连接但Spring Cloud暂时还没有整合计划。 三、总结 总的来说在微服务架构如果使用了Spring Cloud生态的基础组件则Spring Cloud Gateway相比而言更加具备优势单从流式编程支持异步上就足以让开发者选择它了。 对于小型微服务架构或是复杂架构不仅包括微服务应用还有其他非Spring Cloud服务节点zuul也是一个不错的选择。 Gateway是一个web项目本质也是微服务可当做过滤器使用也是微服务的入口。 Gateway旨在提供一种简单而有效的方式来对API进行路由以及提供一些强大的过滤器功能例如熔断、限流、重试等 使用要求 基于Spring5SpringBoot2 SpringCloud Gatway是基于WebFlux框架实现的而WebFlux框架底层则使用了高性能的Reactor模式通讯框架Netty Spring Cloud Gateway 使用的Webflux中的reactor-netty响应式编程组件底层使用了Netty通讯框架 统一的路由方式且基于Filter链 网关的位置 nginx做负载均衡。nginx没法写业务 nginx去找网关。 网关的作用负载均衡、过滤请求、验证令牌(统一鉴权)、 全局熔断 2、GateWay工作原理
网关原理:经过各个过滤器的过滤之后,将满足指定断言规则的请求路由到指定位置 1.客户端向Spring Cloud Gateway发出请求。然后在Gateway Handler Mapping中找到与请求匹配的路由
将其发送到Gateway Web Handler.2.Handler再通过指定的过滤器链来将请求发送给我们实际的服务执行业务逻辑然后返回。 上图中过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前pre或之后(post)执行业务逻辑。 Filter在pre类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等在post类型的过滤器中可以做响应内容、响应头的修改日志的输出流量控制等有着非常重要的作用 3、动态路由通过服务名实现
路由是构建网关的基本模块路由是一个动作它由4个属性ID目标URI一系列的断言和过滤器组成如果断言为true则匹配该路由 创建新的工程cloud-gateway-gateway9527又是那无聊至极的3步 1、引入依赖 !--新增gateway不需要引入web和actuator模块--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-gateway/artifactId/dependency 2、配置文件 server:port: 9527
spring:application:name: cloud-gatewayeureka:instance:hostname: cloud-gateway-serviceclient:register-with-eureka: truefetch-registry: trueservice-url:defaultZone: http://localhost:7001/eureka 3、主启动 package com.atguigu.springcloud;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;SpringBootApplication
EnableEurekaClient
public class GateWayMain9527 {public static void main(String[] args) {SpringApplication.run( GateWayMain9527.class,args);}
} 网关做路由映射就在配置文件中
server:port: 9527spring:application:name: cloud-gatewaycloud:gateway:routes:- id: payment_routh #路由的ID没有固定规则但要求唯一建议配合服务名uri: http://localhost:8001 #匹配后提供服务的路由地址predicates:- Path/payment/get/** #断言,路径相匹配的进行路由- id: payment_routh2uri: http://localhost:8001predicates:- Path/payment/lb/** #断言,路径相匹配的进行路由eureka:instance:hostname: cloud-gateway-serviceclient:register-with-eureka: truefetch-registry: trueservice-url:defaultZone: http://localhost:7001/eureka
按道理说网关后面应该跟的是消费端现在咱不那么麻烦直接让网关路由到提供端8001。 启动测试 当然你要是直接访问8001也是好使的老师所说的隐藏我也不觉得安全啊照样能访问 动态路由
默认情况下Gateway会根据注册中心的服务列表以注册中心上微服务名为路径创建动态路由进行转发从而实现动态路由的功能 需要注意的是uri的协议为lb表示启用Gateway的负载均衡功能
spring:application:name: cloud-gatewaycloud:gateway:discovery:locator:enabled: true #开启从注册中心动态创建路由的功能利用微服务名进行路由routes:- id: payment_routh #路由的ID没有固定规则但要求唯一建议配合服务名uri: lb://CLOUD-PAYMENT-SERVICEpredicates:- Path/payment/get/** #断言,路径相匹配的进行路由 使用网关访问 第一次 第二次 4、断言Predicate的使用
如果请求与断言规则相匹配则进行路由
Spring Cloud Gateway包括许多内置的Route Predicate工厂。所有这些Predicate都与HTTP请求的不同属性匹配。多个Route Predicate工厂可以进行组合 Predicate就是为了实现一组匹配规则让请求过来找到对应的Route进行处理
spring:application:name: cloud-gatewaycloud:gateway:discovery:locator:enabled: true #开启从注册中心动态创建路由的功能利用微服务名进行路由routes:- id: payment_routh #路由的ID没有固定规则但要求唯一建议配合服务名uri: lb://CLOUD-PAYMENT-SERVICEpredicates:- Path/payment/get/** #断言,路径相匹配的进行路由#- After2020-03-08T10:59:34.10208:00[Asia/Shanghai] 没到时间进行测试会报错#- Cookieusername,xiaoyumao #并且Cookie是usernamexiaoyumao才能访问#- HeaderX-Request-Id, \d #请求头中要有X-Request-Id属性并且值为整数的正则表达式#- Host**.atguigu.com#- MethodGET#- Queryusername, \d #要有参数名称并且是正整数才能路由 5、gateway如何实现限流?
1. Spring Cloud Gateway使用令牌桶算法实现限流。
2. Spring Cloud Gateway默认使用redis的Ratelimter限流算法来实现。所以我们要使用首先需要引入redis的依赖。
3.使用过程中我们主要配置 令牌桶填充的速率令牌桶的容量指定限流的Key。
4.限流的Key,可以根据用户来限流 、IP限流、接口限流等等。 令牌桶算法(Token Bucket) 随着时间流逝系统会按恒定1/QPS时间间隔(如果QPS100,则间隔是10ms)往桶里加入Token如果桶已经满了就不再加了.新请求来临时会各自拿走一个Token,如果没有Token可拿了就阻塞或者拒绝服务 令牌桶算法”在能够限制数据的平均传输速率外还允许某种程度的突发传输。在令牌桶算法”中只要令牌桶中存在令牌那么就允许突发地传输数据直到达到用户配置的门限所以它适合于具有突发特性的流量。 以redis限流IP为例 1,引入依赖 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis-reactive/artifactId
/dependency 2,IP限流的keyResolver Bean
public KeyResolver ipKeyResolver() {
return exchange - Mono. just(exchange. getRequest(). getRemoteAddress(). getHostName());
} 3,配置文件 filters :
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
key-resolver: #{ipKeyResolver} flter名称必须是RequestRateLimiter redis-rate-limiter.replenishRafe :允许用户每秒处理多少个请求 redis-rate-limiter.burstCapacity :令牌桶的容量,允许在-秒钟内完成的最大请求数 key-resolver :使用SpEL按名称引用bean 漏桶(Leaky Bucket)算法 水(请求)先进入到漏桶内,桶以一定的速度出水(接口的响应速率),当水流入速度过大会直接溢出(访问频率超过接口响应速率),然后就拒绝请求,可以看出漏桶算法能强行限制数据的传输速率 Filter的使用
1、内置路由过滤器 断言predicates满足指定的要求就开始工作 路由Route满足断言的条件就路由到这个地方 过滤器Filter到达指定地方前后由所有过滤器一起工作 使用过滤器可以在请求被路由前或者之后对请求进行修改 SpringCloud Gateway内置了多种路由过滤器他们都由GatewayFilter的工厂类来产生。 内置过滤器都是动态为请求添加一些行为 在路由配置中加入过滤器这个演示的路由过滤器会给请求加一个请求头 当然是可以同时存在的断言是判断请求对不对过滤器是动态添加请求头 我们在8001服务的controller中获取并打印一下 String header request.getHeader(X-Request-red);
System.out.println(header header); 2、自定义全局过滤器
自定义全局过滤器 implements GlobalFilter, Ordered
Component
Slf4j
public class MyLogGateWayFilter implements GlobalFilter, Ordered {Overridepublic MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain) {log.info(*********come in MyLogGateWayFilter: new Date());String uname exchange.getRequest().getQueryParams().getFirst(username);if(StringUtils.isEmpty(uname)){log.info(*****用户名为Null 非法用户,(┬┬));exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);return exchange.getResponse().setComplete();}return chain.filter(exchange);}Overridepublic int getOrder() {return 0; //对多个过滤器排序}
} 此时再次访问相同的请求 http://localhost:9527/payment/get/35 当你加一个请求参数username访问的结果就又不一样了 此时不管是自定义的过滤器还是内置的过滤器都是会走的只是在俩个不同的控制台一个在9527一个在8001。。。我当时还纠结了好久怎么只有其中一个过滤器生效呢服了