荐 SpringCloud(5)--服务网关(GateWay)
系列链接:
- GitHub:源码
- SpringCloud(1)–入门、版本、环境搭建
- SpringCloud(2)–服务注册与发现(Eureka、Zookeeper、Consul)
- SpringCloud(3)–服务调用(Ribbon、OpenFeign)
- SpringCloud(4)–服务降级(Hystrix、降级、熔断、监控)
- SpringCloud(5)–服务网关(GateWay)
- …
服务网关
基本架构如下:
GateWay
Gateway 是在 Spring 生态系统之上构建的 API 网关服务,基于 Spring 5、Spring Boot 2 和 Project Reactor 等技术。它提供了一种简单且有效的方式来对 API 进行路由,并提供了一些强大的过滤器功能(熔断、限流、重试等)。
Gateway 的底层是基于 WebFlux 框架实现的,而webFlux底层使用netty通信(NIO)。
GateWay的特性:
- 基于 Spring 5、Spring Boot 2 和 Project Reactor 进行构建
- 动态路由,能够匹配任何请求属性
- 可以对路由指定和边写 Predicate(断言)和 Filter(过滤器)
- 集成 Hystrix 的断路器功能
- 集成 Spring Cloud 服务发现功能
- 请求限流功能、支持路径重写
GateWay与zuul的区别:
- Zuul 1.x 是一个基于 Servlet 2.5 的阻塞架构,性能较差。而 2.x 版本基于 Netty 非阻塞并支持长连接,但与 Spring Cloud 目前还没整合。
- Gateway 使用非阻塞 API,支持 WebSocket 且与 Spring 紧密集成。
相关概念
-
路由: 路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,就是根据某些规则,将请求发送到指定服务上。
-
断言: 断言用于匹配 HTTP 请求中的所有内容(请求头/请求参数),如果请求与断言相匹配则进行路由。
-
过滤: 实现的过滤器可以在请求被路由前或者之后,对请求进行修改。
工作原理
客户端向 Gateway 发出请求,然后在 Gateway Handler Mapping 中找到与请求匹配的路由,将其发送到 Gateway Handler。Handler 再通过指定的过滤器链,然后将请求发送到实际的服务执行业务逻辑,最后返回。
过滤器链之间用虚线分开,是因为在发送请求之前或之后执行一些其他的业务逻辑:
- 之前:参数校验、权限校验、流量监控、日志输出、协议转换等。
- 之后:相应内容与响应头的修改、日志输出、流量监控等。
GateWay的使用
-
新建名称为 cloud-gateway-gateway9527 的Module
-
pom文件
<!--gateway--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>
-
配置文件
server: port: 9527 spring: application: name: cloud-gateway eureka: instance: hostname: cloud-gateway-service client: register-with-eureka: true fetch-registry: true service-url: defaultZone: http://eureka7001.com:7001/eureka
-
主启动类
@SpringBootApplication @EnableEurekaClient public class GateWayMain9527 { public static void main(String[] args){ SpringApplication.run(GateWayMain9527.class,args); } }
-
针对pay模块,设置路由,修改GateWay模块(9527)的配置文件
spring: application: name: cloud-gateway cloud: gateway: routes: - id: payment_routh # 路由的 ID,没有固定规则但要求唯一 uri: http://localhost:8001 # 匹配后蹄冻服务的路由地址 predicates: - Path=/payment/get/** # 断言,路径相匹配的进行路由 - id: payment_routh2 # 路由的 ID,没有固定规则但要求唯一 uri: http://localhost:8001 # 匹配后蹄冻服务的路由地址 predicates: - Path=/payment/lb/** # 断言,路径相匹配的进行路由
-
开始测试,启动7001、8001、9527
注:如果启动GateWay报错可能是GateWay模块引入了web和监控的starter依赖,需要移除
访问http://localhost:9527/payment/get/31
-
GateWay的网关配置,除了支持配置文件,还支持硬编码方式,使用硬编码配置GateWay:
-
创建配置类
@Configuration public class GateWayConfig { @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder){ RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes(); routes.route("path_route_moke",r->r.path("/guonei") .uri("http://news.baidu.com/")); return routes.build(); } }
-
然后重启服务即可
-
动态路由
上面的配置虽然首先了网关,但是是在配置文件中写死了要路由的地址。我们可以修改为,从注册中心获取某组微服务的地址,然后根据微服务名字进行路由。
-
修改GateWay模块的配置文件
spring: application: name: cloud-gateway cloud: gateway: discovery: locator: enabled: true # 开启从注册中心动态创建路由的功能,利用微服务名进行路由 routes: - id: payment_routh # 路由的 ID,没有固定规则但要求唯一 # uri: http://localhost:8001 # 匹配后蹄冻服务的路由地址 uri: lb://cloud-payment-service predicates: - Path=/payment/get/** # 断言,路径相匹配的进行路由 - id: payment_routh2 # 路由的 ID,没有固定规则但要求唯一 # uri: http://localhost:8001 # 匹配后蹄冻服务的路由地址 uri: lb://cloud-payment-service predicates: - Path=/payment/lb/** # 断言,路径相匹配的进行路由
-
然后就可以启动7001,8001,8002,9527服务
Pridicate断言
我们之前在配置文件中配置了断言:
predicates:
- Path=/payment/get/** # 断言,路径相匹配的进行路由
Gateway 包括许多内置的 Route Predicate 工厂,所有这些 Predicate 都与 HTTP 请求的不同属性匹配,且多个 Route Oredicate 工厂可以进行组合。之前我们配置的Path,就是由其中一种工厂创建的。断言还有以下的类型:
-
After:可以指定,只有在指定时间后,才可以路由到指定微服务,zai 指定的时间之前访问,都会报404。
-
before:与after类似,他说在指定时间之前的才可以访问
-
between:需要指定两个时间,在他们之间的时间才可以访问
-
cookie:只有包含某些指定cookie(key,value),的请求才可以路由
-
Header:只有包含指定请求头的请求,才可以路由
-
Host:只有指定主机的才可以访问
-
Method:只有指定请求才可以路由,比如get请求…
-
Path:只有访问指定路径,才进行路由,我们已经用过了
-
Query:必须带有请求参数才可以访问
Filter过滤器
Gateway 内置了多种路由过滤器,由 GatewayFilter 的工厂类生成,过滤器的类型可以在官网查看。
生命周期:在请求进入路由之前,和处理请求完成,再次到达路由之前
种类:
-
GatewayFilter:单一的过滤器
-
GlobalFilter:全局过滤器
自定义过滤器
-
实现两个接口GlobalFilter和Ordered
@Component @Slf4j public class MyLogGateWayFilter implements GlobalFilter,Ordered{ @Override public Mono<Void> filter(ServerWebExchange serverWebExchange, GatewayFilterChain gatewayFilterChain) { log.info("****come in MyLogGateWayFilter:"+new Date()); String uname = serverWebExchange.getRequest().getQueryParams().getFirst("uname"); if(uname == null){ log.info("****用户名为空,非法用户"); serverWebExchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE); return serverWebExchange.getResponse().setComplete(); } return gatewayFilterChain.filter(serverWebExchange); } @Override public int getOrder() { return 0; } }
-
然后启动服务
-
请求带unam参数
-
请求不带参数
-
本文地址:https://blog.csdn.net/MOKEXFDGH/article/details/107344407
上一篇: springAOP中的代理模式
下一篇: 2020-Android-面试总结(1)
推荐阅读
-
跟我学SpringCloud | 第十篇:服务网关Zuul高级篇
-
SpringCloud-使用路由网关的服务过滤功能-拦截登录前是否有token为例
-
荐 Spark快速入门系列(5) | Spark环境搭建—standalone(2) 配置历史日志服务器
-
Springcloud GateWay网关配置过程图解
-
Spring Cloud Gateway 服务网关快速实现解析
-
荐 Day04_springcloud_feign&hysrix&Gateway
-
荐 SpringCloud(5)--服务网关(GateWay)
-
Spring Cloud gateway 网关服务 一
-
springcloud(5)springcloud-Config 配置中心 服务端
-
荐 SpringCloud(3)--服务调用(Ribbon、OpenFeign)