1. 概述
Soul 是基于 WebFlux 实现的响应式的 API 网关,具有异步、高性能、跨语言等特点。
作者:我希望能够有一样东西像灵魂一样,保护您的微服务。在参考了 Kong、Spring Cloud Gateway 等优秀的网关后,站在巨人的肩膀上,Soul 由此诞生!
作者是艿艿的大表弟,胖友信么?!
目前 Soul 功能列表如下:
-
支持各种语言,无缝集成到 Dubbo、Spring Cloud、Spring Boot 中。
Soul 是极其少支持 Dubbo 的 API 网关,通过 Dubbo 泛化调用 实现。
-
丰富的插件支持,鉴权,限流,熔断,防火墙等等。
- 网关多种规则动态配置,支持各种策略配置。
- 插件热插拔,易扩展。
- 支持集群部署,支持 A/B Test。
整体架构如下图所示:
是不是看着就贼酷炫,实际一脸懵逼。不要慌~我们先来搭建 Soul 网关。
2. 单机部署
本小节,我们来单机部署一个 Soul 服务,适合测试环境。如下图所示:
2.1 MySQL 安装
目前最好安装 5.X 版本,一开始用 8.X 存在报错的情况。
安装完成后,创建 soul
数据库。
2.2 Soul Admin 安装
Soul Admin 控制台,负责维护网关的元数据、配置等等,并提供给 Soul Bootstrap 网关服务读取。
友情提示:后续推荐胖友阅读如下两篇文章,搞懂 Soul Admin 和 Soul Bootstrap 的同步的原理:
① 从 https://yu199195.github.io/jar/soul-admin.jar 下载启动 jar 包。
# 创建目录
$ mkdir -p /Users/yunai/Soul
$ cd /Users/yunai/Soul
# 下载
$ wget https://yu199195.github.io/jar/soul-admin.jar
② 通过 java -jar soul-admin.jar
命令启动 Soul Admin 控制台。完整命令如下:
$ java -jar soul-admin.jar --spring.datasource.url="jdbc:mysql://s1.iocoder.cn:3306/soul?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=CONVERT_TO_NULL&failOverReadOnly=false&autoReconnect=true&useSSL=false" --spring.datasource.username='root' --spring.datasource.password='3WLiVUBEwTbvAfsh'
--spring.datasource.url
配置项,修改成胖友的数据库地址。--spring.datasource.username
配置项,修改成胖友的数据库账号。--spring.datasource.password
配置项,修改成胖友的数据库密码。
Soul Admin 会自动创建数据库,以及表结构,并初始化默认数据。如下图所示:
友情提示:具体的数据库设计,后续可以看看《Soul 文档 —— 数据库设计》。
③ 启动完成后,我们可以通过日志看到 Soul Admin 启动在 9095 端口。使用浏览器,访问 http://127.0.0.1:9095/ 地址,进入登录页。
默认内置管理员账号「admin/123456」。输入账号密码,进入首页。
胖友可以自己随便点点,简单了解下有哪些功能。
2.3 Soul Bootstrap 安装
Soul Bootstrap 网关服务,负责启动网关,并转发请求到后端服务。
① 从 https://yu199195.github.io/jar/soul-bootstrap.jar 下载启动 jar 包。
$ wget https://yu199195.github.io/jar/soul-bootstrap.jar
② 直接通过 java -jar soul-bootstrap.jar
命令启动 Soul Bootstrap 网关服务。完整命令如下:
$ java -jar soul-bootstrap.jar --soul.sync.websocket.url="ws://localhost:9095/websocket"
--spring.datasource.url
配置项,修改成胖友的 Soul Admin 地址。
同时,我们在 Soul Admin 的日志输出如下日志,说明 Soul Bootstrap 成功连接上。
2020-05-22 20:32:48.005 INFO 48891 --- [0.0-9095-exec-1] o.d.s.a.l.websocket.WebsocketCollector : websocket on open successful....
③ 启动完成后,我们可以通过日志看到 Soul Bootstrap 启动在 9195 端口。使用浏览器,访问 http://127.0.0.1:9195/ 地址,返回如下结果,说明启动成功。
{
"code": -100,
"message": "您的参数错误,请检查相关文档!",
"data": null
}
2.4 下一步
至此,我们已经完成了 Soul 服务的单机部署,是不是挺简单的。下面,胖友可以根据自己的需要,阅读如下小节:
3. 接入 Dubbo 应用
示例代码对应仓库:
lab-60-soul-dubbo-demo-user-service
本小节,我们参考《Soul 文档 —— Dubbo 用户接入》文章,接入 Soul 服务网关。整个示例架构如下图所示:
下面,我们来开始正式接入 Dubbo 应用。
3.1 设置 dubbo 插件
先需要设置 dubbo 插件 的注册中心,因为 Soul Bootstrap 服务网关需要从注册中心获取到 Dubbo 服务的实例列表。
① 使用浏览器,访问 http://127.0.0.1:9095/#/system/plugin 地址,进入「系统管理 -> 插件管理」菜单,可以看到 dubbo 插件。如下图所示:
② 点击 dubbo 插件的「编辑」按钮,设置注册中心的配置。如下图所示:
- 因为我们将使用 Nacos 作为 Dubbo 服务的注册中心,所以这里设置为
{"register":"nacos://localhost:8848"}
。 - 如果胖友使用 Zookeeper 作为 Dubbo 服务的注册中心,所以这里设置为
{"register":"zookeeper://localhost:2181"}
。
友情提示:注册中心的地址,记得要填写正确哈~
③ 因为 Soul Bootstrap 和 Soul Admin 暂时不支持插件修改的自动加载,所以我们此时需要手动重启下。
3.2 搭建 Dubbo 示例项目
先快速搭建一个 Dubbo 示例项目,暂未接入 Soul 网关。如下图所示:
友情提示:如果胖友对 Dubbo + Nacos 不了解的胖友,可以阅读《芋道 Spring Boot Dubbo 入门》文章。
下面,我们来将它改造接入 Soul 网关。
3.2.1 引入依赖
修改 pom.xml
文件,引入 soul-client-apache-dubbo
依赖,它是 Soul 对 Apache Dubbo 2.7.X 的集成支持。
<!-- 引入 Soul 针对 Dubbo 的集成的依赖 -->
<dependency>
<groupId>org.dromara</groupId>
<artifactId>soul-client-apache-dubbo</artifactId>
<version>2.1.2-RELEASE</version>
</dependency>
友情提示:如果胖友使用 Alibaba Dubbo 2.6.X 的话,引入
soul-client-alibaba-dubbo
依赖。
3.2.2 配置文件
修改 application.yaml
配置文件,添加 Soul 配置项如下:
soul:
# Soul 针对 Dubbo 的配置项,对应 DubboConfig 配置类
dubbo:
admin-url: http://127.0.0.1:9095 # Soul Admin 地址
context-path: /user-api # 设置在 Soul 网关的路由前缀,例如说 /order、/product 等等。
# 后续,网关会根据该 context-path 来进行路由
app-name: user-service # 应用名。未配置情况下,默认使用 Dubbo 的应用名
soul.dubbo
配置项,Soul 对 Dubbo 的配置项,对应 DubboConfig 配置类。具体每个配置项的作用,胖友自己看配置项后的注释。
3.2.3 UserServiceImpl
需要在 Dubbo Service 实现类的方法上,添加 @SoulClient
注解,用于设置每个 Dubbo 方法对应的请求路径。这里,我们修改 UserServiceImpl 类,添加该注解。代码如下:
@org.apache.dubbo.config.annotation.Service(version = "1.0.0")
public class UserServiceImpl implements UserService {
private Logger logger = LoggerFactory.getLogger(getClass());
@Override
@SoulClient(path = "/user/get", desc = "获得用户详细")
public String getUser(Integer id) {
return "User:" + id;
}
@Override
@SoulClient(path = "/user/create", desc = "创建用户")
public Integer createUser(UserCreateDTO createDTO) {
logger.info("[createUser][username({}) password({})]", createDTO.getNickname(), createDTO.getGender());
return 1;
}
}
@SoulClient
注解一共有三个属性:
path
:映射的 HTTP 接口的请求路径。desc
:接口的描述,便于知道其用途。enable
:是否开启,默认为true
开启。
后续,在 Dubbo 服务启动时,Soul Client 会自动解析 @SoulClient
注解的 Dubbo 方法,写入方法的元数据到 Soul Admin 控制台,最终通知到 Soul Bootstrap 服务网关上。
3.3 简单测试
① 执行 UserServiceApplication 启动 Dubbo 服务。在 IDEA 控制台可以看到如下日志,看到写入 Dubbo 方法的元数据到 Soul Admin 控制台。
2020-05-23 01:27:56.682 INFO 54370 --- [pool-2-thread-1] .d.s.c.d.s.DubboServiceBeanPostProcessor : dubbo client register success :{} {"appName":"user-service","path":"/user-api/user/get","pathDesc":"获得用户详细","rpcType":"dubbo","serviceName":"cn.iocoder.springboot.lab60.userservice.api.UserService","methodName":"getUser","parameterTypes":"java.lang.Integer","rpcExt":"{\"version\":\"1.0.0\"}","enabled":true}
2020-05-23 01:27:56.944 INFO 54370 --- [pool-2-thread-1] .d.s.c.d.s.DubboServiceBeanPostProcessor : dubbo client register success :{} {"appName":"user-service","path":"/user-api/user/create","pathDesc":"创建用户","rpcType":"dubbo","serviceName":"cn.iocoder.springboot.lab60.userservice.api.UserService","methodName":"createUser","parameterTypes":"cn.iocoder.springboot.lab60.userservice.api.dto.UserCreateDTO","rpcExt":"{\"version\":\"1.0.0\"}","enabled":true}
② 使用浏览器,访问 http://127.0.0.1:9095/#/system/metadata 地址,进入「系统管理 -> 元数据」菜单,可以看到上述注册的元数据。如下图所示:
③ 使用浏览器,访问 http://127.0.0.1:9095/#/plug/dubbo 地址,进入「插件列表 -> Dubbo」菜单,看到选择器和规则。如下图所示:
点击选择器 /user-api
的「编辑」按钮,查看该选择器的具体信息。如下图所示:
点击规则 /user-api/user/get
的「编辑」按钮,查看该规则的具体信息。如下图所示:
④ 使用 Postman 模拟请求 http://127.0.0.1:9195/user-api/user/get 地址,调用 UserServiceImpl#getUser(Integer id)
方法。如下图所示:
- 使用 Request Method 为
POST
。 - 请求内容类型为
application/json
。 - 因为
UserServiceImpl#getUser(Integer id)
方法是非 Bean 参数类型,所以直接在 Request Body 输入具体值即可。
⑤ 使用 Postman 模拟请求 http://127.0.0.1:9195/user-api/user/create 地址,调用 UserServiceImpl#createUser(UserCreateDTO createDTO)
方法。如下图所示:
- 使用 Request Method 为
POST
。 - 请求内容类型为
application/json
。 - 因为
UserServiceImpl#createUser(UserCreateDTO createDTO)
方法是 Bean 参数类型,所以直接在 Request Body 输入 JSON 数据格式。
至此,我们已经完成了 Soul 网关接入 Dubbo 应用,并进行相应的而测试。
友情提示:实际上,我们也可以参考《Soul 文档 —— dubbo 插件》,手动在 Soul Admin 控制台配置 Dubbo 接口方法的元数据,以及进行 dubbo 插件的选择器和规则的设置,实现 Soul Bootstrap 服务网关转发请求到 Dubbo 服务,无需在 Dubbo 项目中引入
soul-client-apache-dubbo
依赖。也就是说,引入
soul-client-apache-dubbo
依赖的目的,是为了实现自动化,毕竟手工配置比较麻烦,并且容易出错。
4. 接入 Spring Boot 应用
示例代码对应仓库:
lab-60-soul-spring-boot-demo
本小节,我们参考《Soul 文档 —— http 用户接入》文章,接入 Soul 服务网关。整个示例架构如下图所示:
下面,我们来开始正式接入 Spring Boot 应用。
4.1 设置 divide 插件
需要设置 divide 插件 为开启。该插件实现 HTTP 正向代理的功能,所有 HTTP 类型的请求你,都由它进行负载均衡的调用。
使用浏览器,访问 http://127.0.0.1:9095/#/system/plugin 地址,进入「系统管理 -> 插件管理」菜单,可以看到 divide 插件。如下图所示:
默认情况下,divide 插件已经是开启状态,所以无需开启。
4.2 安装 Zookeeper
因为 Soul 网关需要知道后端 Spring Boot 应用的 host + port 地址,所以 Soul Client 实现使用 Zookeeper 作为注册中心,让 Spring Boot 应用注册到其上,从而使得 Soul 网关能够知道具体转发的地址。
① 参考《Zookeeper 极简入门》文章,先来搭建一个 Zookeeper 服务。
② 重启 Soul Admin 控制台,设置 --soul.http.zookeeper-url
配置项为 Zookeeper 地址。完整命令如下:
java -jar soul-admin.jar --spring.datasource.url="jdbc:mysql://s1.iocoder.cn:3306/soul?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=CONVERT_TO_NULL&failOverReadOnly=false&autoReconnect=true&useSSL=false" --spring.datasource.username='root' --spring.datasource.password='3WLiVUBEwTbvAfsh' --soul.http.register=true --soul.http.zookeeper-url=127.0.0.1:2181
4.3 搭建 Spring Boot 示例项目
先快速搭建一个 Spring Boot 示例项目,暂未接入 Soul 网关。如下图所示:
4.3.1 引入依赖
修改 pom.xml
文件,引入 soul-client-springmvc
依赖,它是 Soul 对 SpringMVC 的集成支持。
<!-- 引入 Soul 针对 SpringMVC 的集成的依赖 -->
<dependency>
<groupId>org.dromara</groupId>
<artifactId>soul-client-springmvc</artifactId>
<version>2.1.2-RELEASE</version>
</dependency>
4.3.2 配置文件
修改 application.yaml
配置文件,添加 Soul 配置项如下:
soul:
# Soul 针对 SpringMVC 的配置项,对应 SoulHttpConfig 配置类
http:
admin-url: http://127.0.0.1:9095 # Soul Admin 地址
context-path: /sb-demo-api # 设置在 Soul 网关的路由前缀,例如说 /order、/product 等等。
# 后续,网关会根据该 context-path 来进行路由
app-name: sb-demo-service # 应用名。未配置情况下,默认使用 `spring.application.name` 配置项
zookeeper-url: 127.0.0.1:2181 # 使用 Zookeeper 作为注册中心的地址
soul.http
配置项,Soul 对 SpringMVC 的配置项,对应 SoulHttpConfig 配置类。具体每个配置项的作用,胖友自己看配置项后的注释。
4.3.3 UserController
需要在 Controller 的 HTTP API 方法上,添加 @SoulClient
注解,用于设置每个 API 方法对应的请求路径。这里,我们修改 UserController 类,添加该注解。代码如下:
@RestController
@RequestMapping("/user")
public class UserController {
private Logger logger = LoggerFactory.getLogger(getClass());
@GetMapping("/get")
@SoulClient(path = "/user/get", desc = "获得用户详细")
public String getUser(@RequestParam("id") Integer id) {
return "DEMO:" + id;
}
@PostMapping("/create")
@SoulClient(path = "/user/create", desc = "创建用户")
public Integer createUser(@RequestBody UserCreateDTO createDTO) {
logger.info("[createUser][username({}) password({})]", createDTO.getNickname(), createDTO.getGender());
return 1;
}
}
@SoulClient
注解一共有三个属性:
path
:映射的 HTTP 接口的请求路径。desc
:接口的描述,便于知道其用途。enable
:是否开启,默认为true
开启。
后续,在 Spring Boot 应用启动时,Soul Client 会自动解析 @SoulClient
注解的 API 方法,写入方法的元数据到 Soul Admin 控制台,最终通知到 Soul Bootstrap 服务网关上。
4.4 简单测试
① 执行 DemoApplication 启动 Spring Boot 应用。在 IDEA 控制台可以看到如下日志,看到写入 HTTP API 方法的元数据到 Soul Admin 控制台。
// 注册到 Zookeeper
2020-05-23 10:50:39.587 INFO 62682 --- [ main] o.d.s.c.s.s.ApplicationStartListener : soul-http-client服务注册成功,context-path:/sb-demo-api, ip:port:10.171.1.115:8080
// 写入元数据
2020-05-23 10:50:39.911 INFO 62682 --- [pool-1-thread-1] o.d.s.c.s.s.SoulClientBeanPostProcessor : springMvc client register success :{} {"appName":"sb-demo-service","path":"/sb-demo-api/user/get","pathDesc":"获得用户详细","rpcType":"http","serviceName":"UserController","methodName":"getUser","parameterTypes":"java.lang.Integer","rpcExt":"","enabled":true}
2020-05-23 10:50:40.212 INFO 62682 --- [pool-1-thread-1] o.d.s.c.s.s.SoulClientBeanPostProcessor : springMvc client register success :{} {"appName":"sb-demo-service","path":"/sb-demo-api/user/create","pathDesc":"创建用户","rpcType":"http","serviceName":"UserController","methodName":"createUser","parameterTypes":"cn.iocoder.springboot.lab60.dto.UserCreateDTO","rpcExt":"","enabled":true}
② 使用浏览器,访问 http://127.0.0.1:9095/#/system/metadata 地址,进入「系统管理 -> 元数据」菜单,可以看到上述注册的元数据。如下图所示:
③ 使用浏览器,访问 http://127.0.0.1:9095/#/plug/divide 地址,进入「插件列表 -> Divide」菜单,看到选择器和规则。如下图所示:
点击选择器 /sb-demo-api
的「编辑」按钮,查看该选择器的具体信息。如下图所示:
点击规则 /sb-demo-api/user/get
的「编辑」按钮,查看该规则的具体信息。如下图所示:
④ 使用 Postman 模拟请求 http://127.0.0.1:9195/sb-demo-api/user/get?id=1 地址,转发到 GET /user/get
接口上。如下图所示:
- 使用 Request Method 为
GET
。 - 请求参数,直接带在 URL 后面。
⑤ 使用 Postman 模拟请求 http://127.0.0.1:9195/sb-demo-api/user/create 地址,转发到 POST /user/create
接口上。如下图所示:
- 使用 Request Method 为
POST
。 - 请求内容类型为
application/json
。 - 因为
POST /user/create
使用 JSON 接参,所以直接在 Request Body 输入 JSON 数据格式。
至此,我们已经完成了 Soul 网关接入 Spring Boot 应用,并进行相应的而测试。
友情提示:实际上,我们也可以参考《Soul 文档 —— divide 插件》,手动在 Soul Admin 控制台配置 API 接口方法的元数据,以及进行 divide 插件的选择器和规则的设置,实现 Soul Bootstrap 服务网关转发请求到 Spring Boot 应用,无需在 Spring Boot 应用中引入
soul-client-springmvc
依赖。也就是说,引入
soul-client-springmvc
依赖的目的,是为了实现自动化,毕竟手工配置比较麻烦,并且容易出错。当然,这样也就无法使用 Zookeeper 作为注册中心,需要在 Soul Admin 中手动维护应用的实例列表,会比较麻烦~
5. 接入 Spring Cloud 应用
示例代码对应仓库:
lab-60-soul-spring-cloud-demo
本小节,我们参考《Soul 文档 —— springcloud 用户接入》文章,接入 Soul 服务网关。整个示例架构如下图所示:
下面,我们来开始正式接入 Spring Cloud 应用。
5.1 设置 springcloud 插件
需要设置 springcloud 插件 为开启。该插件实现从 Spring Cloud 注册中心获取服务的示例列表,后续使用 Ribbon 实现负载均衡的调用。
使用浏览器,访问 http://127.0.0.1:9095/#/system/plugin 地址,进入「系统管理 -> 插件管理」菜单,可以看到 springcloud 插件。如下图所示:
默认情况下,springcloud 插件已经是开启状态,所以无需开启。
5.2 安装 Nacos
我们使用 Nacos 作为 Spring Cloud 应用的注册中心,所有胖友可以参照《Nacos 极简入门》文章,搭建一个 Nacos 注册中心。
友情提示:如果想要 Eureka 作为 Spring Cloud 应用注册中心的胖友,可以参照《芋道 Spring Cloud Netflix 注册中心 Eureka 入门》文章,搭建一个 Eureka 注册中心。
5.3 修改 Soul Bootstrap 接入 Nacos
因为 Soul Bootstrap 需要从注册中心获取 Spring Cloud 应用的实例列表,所以需要集成 Spring Cloud 注册中心。目前,默认情况下 Soul Bootstrap 网关服务提供的 soul-bootstrap.jar
包,并未引入相关依赖,所以我们需要自己修改源码,并进行打包。
① 使用 IDEA 从 https://gitee.com/shuaiqiyu/soul 仓库中,下载最新的源码。如下图所示:
② 修改 application.yml
配置文件,添加 spring.cloud.nacos.discovery.server-addr
配置项为 Nacos 注册中心的地址。如下图所示:
③ 修改 pom.xml
文件,引入 spring-cloud-starter-alibaba-nacos-discovery
依赖,集成 Nacos 作为 Spring Cloud 的注册中心。如下图所示:
友情提示:如果想要 Eureka 作为 Spring Cloud 应用注册中心的胖友,也是修改配置文件,和引入依赖。
④ 关闭 soul-bootstrap.jar
启动的服务网关,在 IDEA 中执行 SoulBootstrapApplication 启动服务网关。美滋滋~
友情提示:启动时,会报
Connection refused: localhost/127.0.0.1:6379
错误,这是 Soul 限流功能需要使用到 Redis,可以暂时忽略。
5.4 搭建 Spring Cloud 示例项目
先快速搭建一个 Spring Cloud 示例项目,暂未接入 Soul 网关。如下图所示:
5.4.1 引入依赖
修改 pom.xml
文件,引入 soul-client-springcloud
依赖,它是 Soul 对 Spring Cloud 的集成支持。
<!-- 引入 Soul 针对 Spring Cloud 的集成的依赖 -->
<dependency>
<groupId>org.dromara</groupId>
<artifactId>soul-client-springcloud</artifactId>
<version>2.1.2-RELEASE</version>
</dependency>
5.4.2 配置文件
修改 application.yaml
配置文件,添加 Soul 配置项如下:
soul:
# Soul 针对 SpringMVC 的配置项,对应 SoulSpringCloudConfig 配置类
springcloud:
admin-url: http://127.0.0.1:9095 # Soul Admin 地址
context-path: /sc-user-service-api # 设置在 Soul 网关的路由前缀,例如说 /order、/product 等等。
# 后续,网关会根据该 context-path 来进行路由
app-name: sc-user-service # 应用名。未配置情况下,默认使用 `spring.application.name` 配置项
soul.springcloud
配置项,Soul 对 Spring Cloud 的配置项,对应 SoulSpringCloudConfig 配置类。具体每个配置项的作用,胖友自己看配置项后的注释。
5.4.3 UserController
需要在 Controller 的 HTTP API 方法上,添加 @SoulClient
注解,用于设置每个 API 方法对应的请求路径。这里,我们修改 UserController 类,添加该注解。代码如下:
@RestController
@RequestMapping("/user")
public class UserController {
private Logger logger = LoggerFactory.getLogger(getClass());
@GetMapping("/get")
@SoulClient(path = "/user/get", desc = "获得用户详细")
public String getUser(@RequestParam("id") Integer id) {
return "DEMO:" + id;
}
@PostMapping("/create")
@SoulClient(path = "/user/create", desc = "创建用户")
public Integer createUser(@RequestBody UserCreateDTO createDTO) {
logger.info("[createUser][username({}) password({})]", createDTO.getNickname(), createDTO.getGender());
return 1;
}
}
@SoulClient
注解一共有三个属性:
path
:映射的 HTTP 接口的请求路径。desc
:接口的描述,便于知道其用途。enable
:是否开启,默认为true
开启。
后续,在 Spring Cloud 应用启动时,Soul Client 会自动解析 @SoulClient
注解的 API 方法,写入方法的元数据到 Soul Admin 控制台,最终通知到 Soul Bootstrap 服务网关上。
5.5 简单测试
① 执行 DemoApplication 启动 Spring Boot 应用。在 IDEA 控制台可以看到如下日志,看到写入 HTTP API 方法的元数据到 Soul Admin 控制台。
2020-05-23 17:00:26.711 INFO 67422 --- [pool-1-thread-1] s.SoulSpringCloudClientBeanPostProcessor : springCloud client register success :{} {"appName":"sc-user-service","path":"/sc-user-service-api/user/get","pathDesc":"获得用户详细","rpcType":"springCloud","serviceName":"UserController","methodName":"getUser","parameterTypes":"java.lang.Integer","rpcExt":"","enabled":true}
2020-05-23 17:00:27.110 INFO 67422 --- [pool-1-thread-1] s.SoulSpringCloudClientBeanPostProcessor : springCloud client register success :{} {"appName":"sc-user-service","path":"/sc-user-service-api/user/create","pathDesc":"创建用户","rpcType":"springCloud","serviceName":"UserController","methodName":"createUser","parameterTypes":"cn.iocoder.springcloud.lab60.dto.UserCreateDTO","rpcExt":"","enabled":true}
② 使用浏览器,访问 http://127.0.0.1:9095/#/system/metadata 地址,进入「系统管理 -> 元数据」菜单,可以看到上述注册的元数据。如下图所示:
③ 使用浏览器,访问 http://127.0.0.1:9095/#/plug/divide 地址,进入「插件列表 -> Divide」菜单,看到选择器和规则。如下图所示:
点击选择器 /sc-user-service-api
的「编辑」按钮,查看该选择器的具体信息。如下图所示:
点击规则 /sc-user-service-api/user/get
的「编辑」按钮,查看该规则的具体信息。如下图所示:
④ 使用 Postman 模拟请求 http://127.0.0.1:9195/sc-user-service-api/user/get?id=1 地址,转发到 GET /user/get
接口上。如下图所示:
- 使用 Request Method 为
GET
。 - 请求参数,直接带在 URL 后面。
⑤ 使用 Postman 模拟请求 http://127.0.0.1:9195/sb-demo-api/user/create 地址,转发到 POST /user/create
接口上。如下图所示:
- 使用 Request Method 为
POST
。 - 请求内容类型为
application/json
。 - 因为
POST /user/create
使用 JSON 接参,所以直接在 Request Body 输入 JSON 数据格式。
至此,我们已经完成了 Soul 网关接入 Spring Cloud 应用,并进行相应的而测试。
友情提示:实际上,我们也可以参考《Soul 文档 —— springcloud 插件》,手动在 Soul Admin 控制台配置 API 接口方法的元数据,以及进行 springcloud 插件的选择器和规则的设置,实现 Soul Bootstrap 服务网关转发请求到 Spring Cloud 应用,无需在 Spring Cloud 应用中引入
soul-client-springcloud
依赖。也就是说,引入
soul-client-springcloud
依赖的目的,是为了实现自动化,毕竟手工配置比较麻烦,并且容易出错。
6. rateLimiter 插件
本小节,我们参考《Soul 文档 —— rateLimiter 插件》文章,使用 rateLimiter 插件,实现 Soul 网关的限流功能。该插件是基于令牌桶算法 + Redis 存储计数,实现分布式限流。整体设计如下图:
下面,我们在「3. 接入 Dubbo 应用」小节的基础上,对 user-api/user/get
实现限流的功能。
6.1 安装 Redis
相信大家都会,艿艿就不瞎哔哔了。嘿嘿~
6.2 设置 rateLimiter 插件
先需要设置 rateLimiter 插件 的 Redis 配置,目前支持单机、哨兵、集群模式。
① 使用浏览器,访问 http://127.0.0.1:9095/#/system/plugin 地址,进入「系统管理 -> 插件管理」菜单,可以看到 rateLimiter 插件。如下图所示:
② 点击 rateLimiter 插件的「编辑」按钮,设置 Redis 的配置,并设置该插件为开启。如下图所示:
友情提示:Redis 的地址,记得要填写正确哈~
③ 因为 Soul Bootstrap 和 Soul Admin 暂时不支持插件修改的自动加载,所以我们此时需要手动重启下。
6.3 设置 rateLimiter 限流规则
① 使用浏览器,访问 http://127.0.0.1:9095/#/plug/rate_limiter 地址,进入「插件列表 -> rate_limiter」菜单,进行限流规则的配置。如下图所示:
② 点击「添加选择器」按钮,添加一个选择器。如下图所示:
③ 点击「添加规则」按钮,给该选择器添加一个规则。如下图所示:
- 对请求地址
/user-api/user/get
进行限流,对应 UserService 的#getUser(Integer id)
方法。 - 速率:是你允许用户每秒执行多少请求,而丢弃任何请求。这是令牌桶的填充速率。
- 容量:是允许用户在一秒钟内执行的最大请求数。这是令牌桶可以保存的令牌数。
友情提示:可能胖友对 Soul 定义的选择器与规则的概念有点不了解,可以看看《Soul 文档 —— 选择器规则详解》文章。
6.4 简单测试
执行 UserServiceApplication 启动 Dubbo 服务。
快速且多次使用 Postman 模拟请求 http://127.0.0.1:9195/user-api/user/get 地址,调用 UserServiceImpl#getUser(Integer id)
方法,最终被限流。如下图所示:
7. hystrix 插件
本小节,我们参考《Soul 文档 —— hystrix 插件》文章,使用 hystrix 插件,使用 Hystrix 框架,实现 Soul 网关的熔断器功能。
友情提示:对 Hystrix 不了解的胖友,可以后续阅读《芋道 Spring Boot 服务容错 Hystrix 入门》文章进行学习。
下面,我们在「3. 接入 Dubbo 应用」小节的基础上,对 user-api/user/get
实现熔断器的功能。
7.1 设置 hystrix 插件
需要设置 hystrix 插件 为开启。
使用浏览器,访问 http://127.0.0.1:9095/#/system/plugin 地址,进入「系统管理 -> 插件管理」菜单,可以看到 hystrix 插件。如下图所示:
默认情况下,hystrix 插件已经是开启状态,所以无需开启。
7.2 设置 rateLimiter 限流规则
① 使用浏览器,访问 http://127.0.0.1:9095/#/plug/hystrix 地址,进入「插件列表 -> hystrix」菜单,进行熔断器规则的配置。如下图所示:
② 点击「添加选择器」按钮,添加一个选择器。如下图所示:
③ 点击「添加规则」按钮,给该选择器添加一个规则。如下图所示:
- 对请求地址
/user-api/user/get
进行熔断保护,对应 UserService 的#getUser(Integer id)
方法。
友情提示:可能胖友对 Soul 定义的选择器与规则的概念有点不了解,可以看看《Soul 文档 —— 选择器规则详解》文章。
7.3 简单测试
不要执行 UserServiceApplication 启动 Dubbo 服务,模拟其故障。
快速且多次使用 Postman 模拟请求 http://127.0.0.1:9195/user-api/user/get 地址,调用 UserServiceImpl#getUser(Integer id)
方法,最终被熔断。如下图所示:
此时,我们在 Soul Bootstrap 网关的日志可以看到,Hystrix 熔断器已经打开。日志内容如下:
2020-05-23 20:52:28.786 ERROR 69264 --- [work-threads-20] o.d.s.web.plugin.hystrix.HystrixPlugin : hystrix execute have circuitBreaker is Open! groupKey:user-service,commandKey:cn.iocoder.springboot.lab60.userservice.api.UserService
至此,我们已经完成了 Soul 网关的学习,后续胖友可以阅读《Soul 文档》,了解本文暂时并未写到的内容。
例如插件相关:
- monitor 插件:实现监控数据的收集,后续可以使用 Grafana 实现监控仪表盘。
- waf 插件:实现黑名单功能,禁止恶意 IP 的访问。
- sign 插件:实现请求签名功能,保证接口的安全性。
- rewrite 插件:对请求 URI 进行重写。
- websocket 插件:实现对 Websocket 进行代理转发。
- 自定义插件:自己实现插件,进一步拓展自己的插件。
例如功能相关:
- 自定义 filter:自定义 Filter,可以拓展安全认证等等功能。
-
文件上传下载:提供的文件上传和下载功能。
友情提示:建议文件上传不要经过 API 网关,而是先上传到文件服务器,然后提交 URL 到 API 网关。
-
自定义 host 与 ip:考虑到 API 网关的前面都有 Nginx,所以需要拓展保证解析到正确的用户 IP。
- 自定义返回结果:每个公司的统一返回格式可能有差异,最好自己拓展下。