球友好,这一节我们来更细粒度地聊一聊微服务网关 Gateway。
在面试系列中,我们已经讲过一些关于 Gateway 的基础知识,以及一些 Gateway 在 PmHub 中的实操。这一节, 我们将进行更深入地学习,来帮你打通任督二脉:
- Gateway 工作流程机理
- 网关如何做路由映射
- 如何动态获取服务 URI
- 自定义断言
- 自定义过滤器
- PmHub 中的高级实践
书读百遍不如跟着我实操一遍,涉及到代码的地方,希望你可以拿起高贵的笔记本和我一起敲击哦。
概述
这部分和面试系列稍微会有一些交叉,但会有一些意想不到的惊喜。
由于苍何最近在公司整的大数据及 K8s 应用,还发现了一种更高性能的网关,它的名字叫 APISIX,你可能没听过他,但工作中有可能用到哦,这里我们来看看他和 SpringCloud Gateway 有啥区别:
对比维度 | Spring Cloud Gateway | APISIX |
---|---|---|
项目定位 | 基于 Spring Cloud 的微服务网关解决方案,专为 Java 生态设计。 | 一个高性能的开源 API 网关,面向多语言生态和高并发场景。 |
技术栈 | 基于 Java 和 Spring Reactor。 | 基于 Nginx 和 OpenResty,采用 Lua 语言扩展插件体系。 |
性能 | 性能较高,但受限于 JVM 性能瓶颈。 | 高性能,轻量级,基于 Nginx 的高并发优势。 |
生态支持 | 强大的 Spring 生态系统,集成 Spring Cloud 全家桶。 | 支持多语言客户端,广泛适配云原生生态,如 Kubernetes。 |
扩展性 | 支持自定义 Filter 和 Predicate,但需掌握 Java 编程。 | 提供丰富的 Lua 插件,可动态加载,支持实时扩展。 |
动态性 | 配置较为静态,需重启应用加载新配置。 | 支持动态配置,无需重启,配置变更实时生效。 |
管理方式 | 依赖代码配置(通过 Java 配置类或 yml 文件)。 | 提供友好的 Dashboard 界面,支持 REST API 和 CLI 管理。 |
插件体系 | 插件功能有限,主要通过 Filter 实现。 | 插件丰富,涵盖鉴权、限流、日志监控、数据转换等功能。 |
服务发现 | 原生支持 Spring Cloud 服务发现机制(Eureka、Consul 等)。 | 支持多种服务发现方式,包括 Nacos、Eureka、Consul 等。 |
协议支持 | HTTP 和 WebSocket。 | 支持 HTTP、HTTPS、gRPC、WebSocket、TCP 等多种协议。 |
社区支持 | 依赖 Spring 官方社区,更新周期较长。 | Apache 基金会项目,社区活跃,更新频率较高。 |
适用场景 | 适用于 Java 微服务体系,特别是基于 Spring Cloud 的项目。 | 适用于多语言、多协议的高并发场景,如跨语言服务集成场景。 |
学习成本 | 对熟悉 Spring 生态的开发者成本较低。 | 需要了解 Nginx 和 Lua,较高的学习曲线。 |
性能瓶颈 | JVM 和线程模型可能成为高并发场景的瓶颈。 | 更接近于原生 Nginx 性能,适合大规模高并发流量处理。 |
典型用户 | Java 开发团队,特别是 Spring Cloud 使用者。 | 面向对性能和多语言支持要求较高的团队,如互联网公司。 |
由于我们的项目属于大数据平台,故不像 PmHub 这样单纯的美好,涉及到的开发语言也不只有 Java,还包括云原生和 k8s 等,所以 APISIX 更适合。但 APISIX 不是我们今天的主角,就不过多展示。
三大法宝
如果你有认真看面试系列的话,就应该清楚,说起 SpringCloud Gateway,就不得不提三大法宝,来,跟我一起回忆一遍吧。
法宝之一:路由
给你举个例子,我们在浏览器输入一串地址,就能跳转到对应的网站,这一串地址包含了域名,网站 URI 等信息。对于微服务系统而言,虽然只有一个页面,但不同的地方会有不同的 URL,比如说:
/a/**:跳转到 A 服务,
/b/**:跳转到 B 服务,
/c/**:跳转到 C 服务
那在微服务系统中,就可以通过网关来实现,而这,用个牛逼点的名词来解释就是:路由。
啥是路由呢?
路由是由一组信息组合而成的,包含 ID、目标 URI、一组断言和一组过滤器,断言路由如果是真的,那请求的 URI 就是配置的路径,也就是请求了/a/**
,就会跳转到路由配置的服务上来。
不大明白?哈哈,没关系,我们看看 PmHub 中是怎么做的。
spring:
cloud:
gateway:
discovery:
locator:
lowerCaseServiceId: true
enabled: true
routes:
# 认证中心
- id: pmhub-auth
uri: lb://pmhub-auth
predicates:
- Path=/auth/**
filters:
# 验证码处理
- CacheRequestFilter
# - ValidateCodeFilter
- StripPrefix=1
# 代码生成
- id: pmhub-gen
uri: lb://pmhub-gen
predicates:
- Path=/gen/**
filters:
- StripPrefix=0
比如你访问 /auth/**
,那根据配置,predicates 断言为真,会跳转到 uri 对应的服务 id,也就是会跳转到 pmhub-auth 这个微服务。
是不是一下子就理解啦?
在路由配置中,有一个 predicates 配置,这个有人说是路由规则,其实就是我们下面要说的法宝二:断言。
法宝之二:断言
断言可以理解为匹配规则,比如在 PmHub 中配置的「 - Path=/auth/**
」,就代表所有符合这个路径规则的请求都会被转发到对应的服务上。参考面试系列:✅PmHub Gateway全局过滤器统计接口调用耗时(👍必看)
法宝之三:过滤
在路由配置中,你会看到有 filters 这个配置,这个其实就是过滤器的配置。
网关中的过滤器,有点类似 SpringMVC 里面的拦截器 Interceptor,以及 Servlet 过滤器,其中「pre」 和「post」分别会在请求被执行栈调用前和被执行后调用,用来修改请求和响应信息。
参考面试系列:✅PmHub Gateway全局过滤器统计接口调用耗时(👍必看)
SpringCloud Gateway 工作流
知其然,而后知其所以然,方可修炼成佛,哈哈,了解工作流后,你就可以和面试官吹逼。
我们先来祭出一张官网截图:
这是官网截图附带描述:
我让 ChatGPT 翻译一下:
客户端向 Spring Cloud Gateway 发出请求。如果 Gateway Handler Mapping 确定某个请求匹配一个路由 (Route),则该请求会被发送到 Gateway Web Handler。此处理器通过特定于该请求的过滤器链来运行请求。过滤器被分为虚线前后两部分的原因是,过滤器可以在代理请求发送之前或之后执行逻辑。所有 "pre" 过滤器逻辑会先被执行,然后代理请求会被发送。代理请求完成后,会执行 "post" 过滤器逻辑。
苍何用人话来描述一下这个过程:
首先啊,客户端向 Spring Cloud Gateway 发出请求。然后在 Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到 Gateway Web Handler。Handler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。
过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(Pre)或之后(Post)执行业务逻辑。
在“pre”类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等;
在“post”类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等有着非常重要的作用。
其实你会发现,核心逻辑就是:路由转发+断言判断+执行过滤器链
PmHub 中集成 SpringCloud Gateway
在 PmHub 中,将 SpringCloud Gateway 作为一个单独的微服务提供了,这也是解耦的关键,通常,我们的网关服务会单独部署,而且由于网关作为核心组件,会集群部署,至少 2 个节点吧。
那么但凡是单独的微服务,那就离不开五部曲:
- 1、建 module
- 2、改 pom
- 3、写 YML
- 4、修改主启动类
- 5、编写业务类
首先新建一个模块 module,pmhub-gateway:
然后再 pom 中引入依赖:
<!-- SpringCloud Gateway -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
然后写 YML:
# Tomcat
server:
port: 6880
# Spring
spring:
application:
# 应用名称
name: pmhub-gateway
profiles:
# 环境配置
active: dev
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8848
username: nacos
password: nacos
config:
# 配置中心地址
server-addr: 127.0.0.1:8848
username: nacos
password: nacos
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
sentinel:
# 取消控制台懒加载
eager: true
transport:
# 配置控制台服务地址
dashboard: 127.0.0.1:8080
# 默认 8719 端口,假如被占用
真诚点赞 诚不我欺
热门评论
1 条评论
回复