Spring Cloud 之服务网关 Gateway (一)
Spring Cloud 之服务网关 Gateway
概述
Spring Cloud Gateway 是Spring官方基于 Spring 5.0, Spring Boot 2.0 和 Project Reactor 等技术开发的网关,Spring Cloud Gateway 旨在为微服务架构提供一种简单而有效的统一的API路由管理方式. Spring Cloud Gateway作为Spring Cloud生态系中的网关. 目标是替代 Netflix ZUUL, 其不仅提供统一的路由方式, 并且基于 Filter 链的方式提供了网关基本的功能, 例如: 安全, 监控/埋点, 和限流等
与 zuul 的区别
spring-cloud-gateway 是 spring-cloud 的一个子项目. 而 zuul 则是 netflix 公司的项目, 只是 spring 将 zuul 集成在 spring-cloud 中使用而已. 因为 zuul2.0 连续跳票和 zuul1 的性能表现不是很理想. 所以催生了 spring 团队开发了 Gateway 项目. 简单来说, gateway 是spring-cloud的亲儿子, zuul 别人家的孩子. 所以总整体性能和与spring cloud 兼容程度来说, gateway 优于 zuul
简单案例实现一个网关(Java 代码)
聚合模块说明
- 版本说明 Spring Boot : 2.0.9.RELEASE Spring Cloud: Finchley.RELEASE
- 项目整体结构采用 maven 多 Module 结构 模块端口说明Demo父项目Eureka15002注册中心Gateway15000网关Comment15003应用服务
- 项目树 一个注册中心 一个网关 一个应用服务 |_ demo |_ eureka |_ gateway |_ comment |_ pom.xml
编写 Eureka 服务
参考: Spring Cloud 之 Eureka 服务注册与发现
编写 Gateway 网关服务
- 编写 pom 文件 在 gateway 里引入 Spring Retry 的 jar 包 <dependencies> <!-- 健康监控 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- Spring Cloud Gateway 依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies>
- application.yml 文件配置 spring: application: name: gateway cloud: gateway: discovery: locator: enabled: true # 开启基于服务发现的路由规则 lower-case-service-id: true # 开启小写的 serviceId 进行基于服务路由的转发 routes: # 路由集群内其他服务,url 需要用 [lb://]+[serviceId](lb:loadbalance) - id: comment-server uri: lb://comment-server predicates: - Path=/comment-server loadbalancer: retry: enabled: true # 内部已默认开启负载均衡 eureka: client: service-url: defaultZone: http://localhost:15002/eureka/ # 指定注册中心地址, 以便使用服务发现功能 instance: lease-renewal-interval-in-seconds: 5 lease-expiration-duration-in-seconds: 15 perfer-in-address: true server: port: 15000 management: endpoints: health: enabled: true gateway: enabled: true web: exposure: include: "*" # 暴露所有端点, 默认是 info, health logging: level: org.springframework.cloud.gateway: debug
- 启动类 @SpringBootApplication public class GatewayApplication { public static void main(String[] args) { SpringApplication.run(GatewayApplication.class, args); } }
网关启动后, 由于开启了健康检查, 可以通过访问: http://localhost:15000/actuator/gateway/routes 查看路由 配置信息
编写应用程序服务 comment-server
- 编写 pom 文件 <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
- 编写工程的配置文件, eureka: client: serverUrl: defaultZone: http://localhost:15002/eureka/ instance: lease-renewal-interval-in-seconds: 5 lease-expiration-duration-in-seconds: 15 perfer-in-address: true server: port: 15003 spring: application: name: comment-server
- 编写控制器 @RestController @RequestMapping("/comments") @Slf4j public class CommentController { @GetMapping("/{id}") public String getJokes(@PathVariable("id") String id) { log.debug("Get comments"); return id; } }
发送请求测试效果
注册中心(eureka), 网关服务(gateway) 和应用服务(comment-server)依次启动后, 访问 http://localhost:15000/comment-server/comments/123 返回 123, 说明通过访问网关的 15000 接口, 成功路由到 应用服务并返回结果.
路由转发配置
Path 路由断言工厂
Path 路由断言工厂根据请求的路径进行路由匹配. 值得注意的是, 如果路由集群内其他服务,url 需要用 [lb://]+serviceId
routes:
# 路由集群内其他服务,url 需要用 [lb://]+[serviceId](lb:loadbalance)
- id: path_route
uri: lb://comment-server
predicates:
- Path=/comment-server
访问 http://localhost:15000/comment-server/comments/123 返回 123, 说明通过访问网关的 15000 接口, 成功路由到 应用服务并返回结果.
Host 路由断言工厂
Host 路由断言工厂根据配置的 Host,对请求中的 Host 进行断言处理(配置主机名的时候, 如果gateway是80端口, 则可以省略. 如果是别的端口号, 需要在断言后面加上对应的端口阿红 eg: Host=****.csdn.****:15000)
routes:
# Host 路由断言工厂
- id: host_route
uri: https://blog.csdn.net/zjhcxdj/category_9771365.html
predicates:
- Host=**.csdn.**:15000 # 请求域名中携带 csdn,则转发
本地hosts文件配置:
127.0.0.1 vip.csdn.com
访问: http://vip.csdn.com:15000/ 跳转到 https://blog.csdn.net/zjhcxdj/category_9771365.html
Query 路由断言工厂
Query 路由断言工厂会从请求中获取请求的参数及其参数值, 然后与 Query断言路由中的配置进行匹配
routes:
- id: query_route
uri: https://blog.csdn.net/zjhcxdj/article/details/106992956
predicates:
- Query=username,zzz # 请求参数含有username,且值为zzz
访问: http://localhost:15000/?username=zzz 跳转到 https://blog.csdn.net/zjhcxdj/article/details/106992956
Header 路由断言工厂
Header 路由断言工厂类似 Query 路由断言方式, 只不过是从请求的 header 里取一个参数及参数值. 用于根据配置的路由 header 信息进行断言匹配路由
routes:
- id: header_route
uri: https://blog.csdn.net/zjhcxdj/article/details/105631321
predicates:
- Header=request, d+ # 如果请求头含有request,且为数字,则转发
通过 postman 访问 http://localhost:15000 并在 header 里设置 request:121231, 则会返回 https://blog.csdn.net/zjhcxdj/article/details/105631321 的页面内容
Cookie 路由断言工厂
Cookie 路由断言工厂类似 Query 路由断言方式, 只不过是从请求的 Cookie 里取一个参数及参数值. 用于根据配置的路由 header 信息进行断言匹配路由
routes:
- id: cookie_route
uri: https://blog.csdn.net/zjhcxdj/article/details/105631321
predicates:
- Cookie=name, zzzgd # 如果携带cookie,参数名为name,值为zzzgd,则转发
Gateway 工作原理
客户端向 Gateway 发起请求, 请求首先会被 HttpWebHandlerAdapter 进行提取组装成网关的上下文, 然后网关的上下文会传递到 DispatcherHandler . DispatcherHandler 是所有请求的分发处理器, 主要负责请求对应的处理器. 比如将请求分发到对应的 RoutePredicateHandlerMapping (路由断言处理映射器). 路由断言处理映射器主要用于路由的查找, 以及找到路由后返回对应的 FilteringWebHandler. FilteringWebHandler 主要负责组装 Filter 链表并调用 Filter 执行一系列的 Filter 处理, 然后把请求转到后端对应的代理服务器, 处理完毕后, 将请求返回给客户端. 如果所示:
(在 Filter 链中, 通过虚线分割 Filter 的原因是, Filter 可以在转发请求之前处理或者接受到被代理的服务返回结果之后处理. 所有的 Pre 类型的 Filter 执行完毕后, 才会转发到被代理的的服务处理. 被代理的服务把所有的请求处理完毕后, 才会执行 Post 类型的服务器)
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- httpclient使用HTTP代理实践
- 使用Python利用微信企业号发送报警信息
- C# Task.Delay() 和 Thread.Sleep() 区别
- Csharp实例:武汉智能安检闸机数据接收和解析
- [周末往期回顾]Oracle基本参数(LOG_ARCHIVE_DEST_n)
- [周末往期回顾]Oracle基本参数(SGA_TARGET)
- C#如何释放已经加载的图片
- 笔记本内置摄像头视频播放和存储
- [Data Guard全解析]5.Data Guard及ADG日常运维操作
- [Oracle 数据库日常操作] 表空间的日常运维命令
- Java 反射 -超详细讲解(附源码)
- [Data Guard全解析]6.物理备库的Switchover
- com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException异常解决方法
- [Oracle数据库日常操作] Redo Log的相关操作
- [周末往期回顾] 使用requests和fiddler模拟登陆51cto并获取下载币