概述
前面的一些列文章介绍了soul网关的核心流程以及数据同步这两大最重要的功能逻辑。鉴于后续希望为soul贡献1个插件,所以接下来再学习学习soul中其它核心插件的写法,今天先看看divide插件
Divide plugin使用
divide-plugin是和spring-clould-plugin同类型的接入类插件,可以让任意http服务都接入到soul中,并让请求正确路由到下游服务。使用divide时首先需要在soul网关中必须引入soul-spring-boot-starter-plugin-divide
项目。而对于下游服务有3种接入方式,第一种,对于spring-boot
项目需要做以下步骤
项目以引入
soul-spring-boot-starter-client-springmvc
包配置文件中增加如下内容
1
2
3
4
5
6
7
8
9
10
11
12soul:
http:
adminUrl: http://localhost:9095
port: 你本项目的启动端口
contextPath: /http
appName: http
full: false
# adminUrl: 为你启动的soul-admin 项目的ip + 端口,注意要加http://
# port: 你本项目的启动端口
# contextPath: 为你的这个mvc项目在soul网关的路由前缀,这个你应该懂意思把? 比如/order ,/product 等等,网关会根据你的这个前缀来进行路由.
# appName:你的应用名称,不配置的话,会默认取 `spring.application.name` 的值
# full: 设置true 代表代理你的整个服务,false表示代理你其中某几个controller在你的
controller
的接口上加上@SoulSpringMvcClient
注解。
第二种对于spring-mvc
项目需要做以下步骤
项目以引入
soul-client-springmvc
包spring的xml文件增加如下配置
1
2
3
4
5
6
7
8
9
10
11<bean id ="springMvcClientBeanPostProcessor" class = "org.dromara.soul.client.springmvc.init.SpringMvcClientBeanPostProcessor">
<constructor-arg ref="soulSpringMvcConfig"/>
</bean>
<bean id="soulSpringMvcConfig" class="org.dromara.soul.client.springmvc.config.SoulSpringMvcConfig">
<property name="adminUrl" value="http://localhost:9095"/>
<property name="port" value="你的端口"/>
<property name="contextPath" value="/你的contextPath"/>
<property name="appName" value="你的名字"/>
<property name="full" value="false"/>
</bean>在你的
controller
的接口上加上@SoulSpringMvcClient
注解。
spring-boot
或spring-mvc
项目完成以上2步在项目启动时admin就会自动感知到服务的启动并在metadata中保存该服务可以提供的接口。第三种如果你是非常非常常规的web服务没有用spring框架,或者你是spring项目但是你不想因为soul而改变你的代码,那么就需要手动配置,让soul知道有新的下游服务接入。这样的话如何配置呢?很简单,直接配置divide插件的选择器selector和规则rule。
soul-plugin-divide
下面我们看看引入soul网关的divide插件是如何实现的。还是从实现了AbstractSoulPlugin
的DividePlugin开始
1 | public class DividePlugin extends AbstractSoulPlugin { |
整体来说divide插件的实现逻辑和之前我们介绍的spring-cloud-plugin核心逻辑相同,都是构造实际请求了url放在请求上下文中。不同的是spring-cloud插件是借助注册中心如eureka拿到合适的1个下游服务。而divide是从内存UpstreamCacheManager
中拿到的所有服务,然后根据插件配置执行自己实现的负责均衡算法选择出合适的1个下游服务。可配的3种负载策略大概的含义如下:
- HASH,根据请求者IP取1个下游服务,如果下游服务不变相同IP请求的永远是同一个服务
- Random,每次请求都从所有下游服务中随机选一个
- RoundRobin,所有服务轮询被请求
UpstreamCacheManager
刚才我们提到插件是从UpstreamCacheManager中根据selectorId选择出全部可用下游服务的。那么为什么UpstreamCacheManager会知道所有的下游服务呢?它是如何验证下游服务是否可用呢?我们来具体看下。
1 | public final class UpstreamCacheManager { |
通过代码可以看出在所有的soul网关中都会运行这样一个upstream的cache,关注divide插件的selector变化,如果有更新就同步更新jvm内存中的配置(UPSTREAM_MAP,UPSTREAM_MAP_TEMP)。同时还运行的有探活程序周期性验证selector配置的下游服务是否存活,但是不会验证接口级别,只会验证IP端口是否通。
总结
divide插件可以让任何http服务都在无侵入的情况下接入到soul,soul也支持对他们进行探活。从逻辑上讲每个网关会探每个selector配置的所有的下游服务的存活情况,因为selector可以配到接口级别,如果1类用户服务有3个实例,10个接口并且配置了10个selector,soul网关启动了5个,那么30秒内关于探活用户服务的请求在网络中就有5*10*3=150个,每个网关都会发10*3=30个。同时这个UpstreamCacheManager
在下游服务是websocket服务时也会用到。