《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 http://www.iocoder.cn/Soul/install/ 「芋道源码」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注微信公众号:【芋道源码】有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

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 服务,适合测试环境。如下图所示:

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 文档 —— 数据库设计》

③ 启动完成后,我们可以通过日志看到 Soul Admin 启动在 9095 端口。使用浏览器,访问 http://127.0.0.1:9095/ 地址,进入登录页。

Soul Admin - 登录页

默认内置管理员账号「admin/123456」。输入账号密码,进入首页。

Soul Admin - 首页

胖友可以自己随便点点,简单了解下有哪些功能。

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」菜单,看到选择器规则。如下图所示:

插件列表 -> Dubbo

点击选择器 /user-api 的「编辑」按钮,查看该选择器的具体信息。如下图所示:

插件列表 -> Dubbo -> 选择器

点击规则 /user-api/user/get 的「编辑」按钮,查看该规则的具体信息。如下图所示:

插件列表 -> Dubbo -> 规则

④ 使用 Postman 模拟请求 http://127.0.0.1:9195/user-api/user/get 地址,调用 UserServiceImpl#getUser(Integer id) 方法。如下图所示:

Postman 模拟

  • 使用 Request MethodPOST
  • 请求内容类型为 application/json
  • 因为 UserServiceImpl#getUser(Integer id) 方法是非 Bean 参数类型,所以直接在 Request Body 输入具体值即可。

⑤ 使用 Postman 模拟请求 http://127.0.0.1:9195/user-api/user/create 地址,调用 UserServiceImpl#createUser(UserCreateDTO createDTO) 方法。如下图所示:

Postman 模拟

  • 使用 Request MethodPOST
  • 请求内容类型为 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」菜单,看到选择器规则。如下图所示:

插件列表 -> Divide

点击选择器 /sb-demo-api 的「编辑」按钮,查看该选择器的具体信息。如下图所示:

插件列表 -> Divide -> 选择器

点击规则 /sb-demo-api/user/get 的「编辑」按钮,查看该规则的具体信息。如下图所示:

插件列表 -> Divide -> 规则

④ 使用 Postman 模拟请求 http://127.0.0.1:9195/sb-demo-api/user/get?id=1 地址,转发到 GET /user/get 接口上。如下图所示:

Postman 模拟

  • 使用 Request MethodGET
  • 请求参数,直接带在 URL 后面。

⑤ 使用 Postman 模拟请求 http://127.0.0.1:9195/sb-demo-api/user/create 地址,转发到 POST /user/create 接口上。如下图所示:

Postman 模拟

  • 使用 Request MethodPOST
  • 请求内容类型为 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 仓库中,下载最新的源码。如下图所示:

soul 源码

② 修改 application.yml 配置文件,添加 spring.cloud.nacos.discovery.server-addr 配置项为 Nacos 注册中心的地址。如下图所示:

`application.yml` 配置文件

③ 修改 pom.xml 文件,引入 spring-cloud-starter-alibaba-nacos-discovery 依赖,集成 Nacos 作为 Spring Cloud 的注册中心。如下图所示:

`pom.xml` 文件

友情提示:如果想要 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」菜单,看到选择器规则。如下图所示:

插件列表 -> springcloud

点击选择器 /sc-user-service-api 的「编辑」按钮,查看该选择器的具体信息。如下图所示:

插件列表 -> springcloud -> 选择器

点击规则 /sc-user-service-api/user/get 的「编辑」按钮,查看该规则的具体信息。如下图所示:

插件列表 -> Divide -> 规则

④ 使用 Postman 模拟请求 http://127.0.0.1:9195/sc-user-service-api/user/get?id=1 地址,转发到 GET /user/get 接口上。如下图所示:

Postman 模拟

  • 使用 Request MethodGET
  • 请求参数,直接带在 URL 后面。

⑤ 使用 Postman 模拟请求 http://127.0.0.1:9195/sb-demo-api/user/create 地址,转发到 POST /user/create 接口上。如下图所示:

Postman 模拟

  • 使用 Request MethodPOST
  • 请求内容类型为 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」菜单,进行限流规则的配置。如下图所示:

插件列表 -> rate_limiter

② 点击「添加选择器」按钮,添加一个选择器。如下图所示:

插件列表 -> 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) 方法,最终被限流。如下图所示:

Postman 模拟

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」菜单,进行熔断器规则的配置。如下图所示:

插件列表 -> hystrix

② 点击「添加选择器」按钮,添加一个选择器。如下图所示:

插件列表 -> 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) 方法,最终被熔断。如下图所示:

Postman 模拟

此时,我们在 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

666. 彩蛋

至此,我们已经完成了 Soul 网关的学习,后续胖友可以阅读《Soul 文档》,了解本文暂时并未写到的内容。

例如插件相关:

例如功能相关:

  • 自定义 filter:自定义 Filter,可以拓展安全认证等等功能。
  • 文件上传下载:提供的文件上传和下载功能。

    友情提示:建议文件上传不要经过 API 网关,而是先上传到文件服务器,然后提交 URL 到 API 网关。

  • 自定义 host 与 ip:考虑到 API 网关的前面都有 Nginx,所以需要拓展保证解析到正确的用户 IP。

  • 自定义返回结果:每个公司的统一返回格式可能有差异,最好自己拓展下。
文章目录
  1. 1. 1. 概述
  2. 2. 2. 单机部署
    1. 2.1. 2.1 MySQL 安装
    2. 2.2. 2.2 Soul Admin 安装
    3. 2.3. 2.3 Soul Bootstrap 安装
    4. 2.4. 2.4 下一步
  3. 3. 3. 接入 Dubbo 应用
    1. 3.1. 3.1 设置 dubbo 插件
    2. 3.2. 3.2 搭建 Dubbo 示例项目
      1. 3.2.1. 3.2.1 引入依赖
      2. 3.2.2. 3.2.2 配置文件
      3. 3.2.3. 3.2.3 UserServiceImpl
    3. 3.3. 3.3 简单测试
  4. 4. 4. 接入 Spring Boot 应用
    1. 4.1. 4.1 设置 divide 插件
    2. 4.2. 4.2 安装 Zookeeper
    3. 4.3. 4.3 搭建 Spring Boot 示例项目
      1. 4.3.1. 4.3.1 引入依赖
      2. 4.3.2. 4.3.2 配置文件
      3. 4.3.3. 4.3.3 UserController
    4. 4.4. 4.4 简单测试
  5. 5. 5. 接入 Spring Cloud 应用
    1. 5.1. 5.1 设置 springcloud 插件
    2. 5.2. 5.2 安装 Nacos
    3. 5.3. 5.3 修改 Soul Bootstrap 接入 Nacos
    4. 5.4. 5.4 搭建 Spring Cloud 示例项目
      1. 5.4.1. 5.4.1 引入依赖
      2. 5.4.2. 5.4.2 配置文件
      3. 5.4.3. 5.4.3 UserController
    5. 5.5. 5.5 简单测试
  6. 6. 6. rateLimiter 插件
    1. 6.1. 6.1 安装 Redis
    2. 6.2. 6.2 设置 rateLimiter 插件
    3. 6.3. 6.3 设置 rateLimiter 限流规则
    4. 6.4. 6.4 简单测试
  7. 7. 7. hystrix 插件
    1. 7.1. 7.1 设置 hystrix 插件
    2. 7.2. 7.2 设置 rateLimiter 限流规则
    3. 7.3. 7.3 简单测试
  8. 8. 666. 彩蛋