开心一刻

昨天看到一条广告:全国比丑大赛,一等奖 2 万奖金

我高高兴兴骑着自行车去了场地,结果被保安拦着不让进

我心里窃喜:莫非我长得不丑,不符合参赛条件?

我说道:为什么不让我进

保安:这是业余人员间的比赛,职业选手不能参加

敢情不是不丑,而是太丑!

书接上回

上篇
不单独部署注册中心,又要具备注册中心的功能,咋不让我上天?

说道
任务分发中心
既集成了
Eureka Server
,还集成了
Eureka Client
,实现了对
任务执行器
的负责均衡,已经很完美的实现了需求

有两个服务:任务分发中心、任务执行器
分发中心负责任务拆分,然后将拆分后的任务下发给执行器,执行器执行任务
任务分发中心和任务执行器都要支持水平扩节点

当我向领导反馈我的实现时,得到了我想要的肯定

但又给我引申了需求,他说

  1. 任务分发中心只调用一个服务:任务执行器,引入
    open-feign
    感觉没什么必要
  2. Eureka Server
    肯定是存储了
    任务执行器
    的实例,是不是可以不开启
    @EnableEurekaClient
    (言外之意就是任务分发中心不要做
    Eureka Client

虽然我心中一万只草泥马奔腾而过,十分不愿意去修改,但理性告诉我他是对的,是可以继续简化(人家能当领导确实是有两把刷子的!)

我们分析下,如果我们拿到了
任务执行器
列表,那么我们就可以根据负载均衡策略选择其中某个实例进行任务分发,所以重点是如何获取
任务执行器
列表

获取服务实例列表

如何获取
任务执行器
列表,大家就不要想着
@EnableEurekaClient
了,因为引申需求的第 2 点就限制了不能用
EurekaClient
,那怎么办?

我就不绕圈子了,我们需要用到一个
holder

EurekaServerContextHolder
,借此我们就能拿到
任务执行器
实例列表,例如:

EurekaServerContextHolder

拿到实例列表后,该做什么了?

是不是负载均衡选择其中某个实例?

负载均衡

拿到实例列表后,我们可以自实现负载均衡策略,但是不推荐,这就跟我为什么不自实现
注册中心
是一个道理,选择现成的、成熟的负载均衡器更具性价比

不是自实现不起,而是现成更具性价比!

这次就不选择
Ribbon
了,因为我们选择的
Spring Cloud 2021.0.8
默认包含的负载均衡器是
spring-cloud-balancer

spring-cloud-loadbalancer

服务实例列表已经获取到了,负载均衡器也有了,接下来做什么?

那就是将实例列表注册给负载均衡器,如下所示

ServiceInstanceListSupplier

接下来是不是就只差任务分发了?

任务分发

我们要明确,我们的
task-executor
提供的是一个
HTTP
接口,所以我们接下来要考虑的是如何去请求这个接口

至于是请求哪个
task-executor
实例,就交给负载均衡器了

发送
HTTP
请求的方式不要太多,而
Spring

RestTemplate
就是其中之一,为了不额外引用第三方
HTTP
工具,也为了适配负载均衡器,推荐就是用
RestTemplate

RestTemplate

至此,就只差临门一脚了,那就是通过
RestTemplate
进行任务分发

任务分发

启动
task-dispatcher

task-executor
,然后调用接口

http://192.168.2.10:8080/dispatcher/job/dispatch?jobId=689

结果
success
,日志输出如下

  1. task-dispatcher

    2024-07-05 22:53:52.606|INFO|http-nio-8080-exec-9|30|com.qsl.task.web.JobController          :收到作业[jobId=689]执行请求
    2024-07-05 22:53:52.606|INFO|http-nio-8080-exec-9|31|com.qsl.task.web.JobController          :作业[jobId=689]拆分任务中...
    2024-07-05 22:53:52.606|INFO|http-nio-8080-exec-9|33|com.qsl.task.web.JobController          :作业[jobId=689]拆分完成,得到作业列表[[123, 666, 888, 999]]
    2024-07-05 22:53:52.611|INFO|http-nio-8080-exec-9|39|com.qsl.task.web.JobController          :任务[123]执行结果:success
    2024-07-05 22:53:52.614|INFO|http-nio-8080-exec-9|39|com.qsl.task.web.JobController          :任务[666]执行结果:success
    2024-07-05 22:53:52.617|INFO|http-nio-8080-exec-9|39|com.qsl.task.web.JobController          :任务[888]执行结果:success
    2024-07-05 22:53:52.619|INFO|http-nio-8080-exec-9|39|com.qsl.task.web.JobController          :任务[999]执行结果:success
    
  2. task-executor

    2024-07-05 22:53:52.609|INFO|http-nio-8081-exec-3|17|com.qsl.task.web.TaskController         :收到任务[taskId=123]执行请求
    2024-07-05 22:53:52.609|INFO|http-nio-8081-exec-3|18|com.qsl.task.web.TaskController         :任务[taskId=123]执行中...
    2024-07-05 22:53:52.610|INFO|http-nio-8081-exec-3|19|com.qsl.task.web.TaskController         :任务[taskId=123]执行完成
    2024-07-05 22:53:52.612|INFO|http-nio-8081-exec-2|17|com.qsl.task.web.TaskController         :收到任务[taskId=666]执行请求
    2024-07-05 22:53:52.613|INFO|http-nio-8081-exec-2|18|com.qsl.task.web.TaskController         :任务[taskId=666]执行中...
    2024-07-05 22:53:52.613|INFO|http-nio-8081-exec-2|19|com.qsl.task.web.TaskController         :任务[taskId=666]执行完成
    2024-07-05 22:53:52.615|INFO|http-nio-8081-exec-4|17|com.qsl.task.web.TaskController         :收到任务[taskId=888]执行请求
    2024-07-05 22:53:52.616|INFO|http-nio-8081-exec-4|18|com.qsl.task.web.TaskController         :任务[taskId=888]执行中...
    2024-07-05 22:53:52.616|INFO|http-nio-8081-exec-4|19|com.qsl.task.web.TaskController         :任务[taskId=888]执行完成
    2024-07-05 22:53:52.618|INFO|http-nio-8081-exec-1|17|com.qsl.task.web.TaskController         :收到任务[taskId=999]执行请求
    2024-07-05 22:53:52.618|INFO|http-nio-8081-exec-1|18|com.qsl.task.web.TaskController         :任务[taskId=999]执行中...
    2024-07-05 22:53:52.618|INFO|http-nio-8081-exec-1|19|com.qsl.task.web.TaskController         :任务[taskId=999]执行完成
    

目前
task-executor
是单实例,我们再启动一个实例,来看看负载均衡效果

  1. task-executor 8081

    2024-07-05 22:59:01.311|INFO|http-nio-8081-exec-6|17|com.qsl.task.web.TaskController         :收到任务[taskId=123]执行请求
    2024-07-05 22:59:01.312|INFO|http-nio-8081-exec-6|18|com.qsl.task.web.TaskController         :任务[taskId=123]执行中...
    2024-07-05 22:59:01.312|INFO|http-nio-8081-exec-6|19|com.qsl.task.web.TaskController         :任务[taskId=123]执行完成
    2024-07-05 22:59:01.391|INFO|http-nio-8081-exec-7|17|com.qsl.task.web.TaskController         :收到任务[taskId=888]执行请求
    2024-07-05 22:59:01.391|INFO|http-nio-8081-exec-7|18|com.qsl.task.web.TaskController         :任务[taskId=888]执行中...
    2024-07-05 22:59:01.391|INFO|http-nio-8081-exec-7|19|com.qsl.task.web.TaskController         :任务[taskId=888]执行完成
    
  2. task-executor 8090

    2024-07-05 22:59:01.379|INFO|http-nio-8090-exec-2|17|com.qsl.task.web.TaskController         :收到任务[taskId=666]执行请求
    2024-07-05 22:59:01.380|INFO|http-nio-8090-exec-2|18|com.qsl.task.web.TaskController         :任务[taskId=666]执行中...
    2024-07-05 22:59:01.380|INFO|http-nio-8090-exec-2|19|com.qsl.task.web.TaskController         :任务[taskId=666]执行完成
    2024-07-05 22:59:01.394|INFO|http-nio-8090-exec-1|17|com.qsl.task.web.TaskController         :收到任务[taskId=999]执行请求
    2024-07-05 22:59:01.394|INFO|http-nio-8090-exec-1|18|com.qsl.task.web.TaskController         :任务[taskId=999]执行中...
    2024-07-05 22:59:01.394|INFO|http-nio-8090-exec-1|19|com.qsl.task.web.TaskController         :任务[taskId=999]执行完成
    

至此,引申需求是不是完美实现了?

装逼

但有一点需要注意,既然
task-dispatcher
不再作为
Eureka Client
, 有个配置最好关闭

fetch-registry

完整代码:integrate-eureka2

https://gitee.com/youzhibing/qsl-project/tree/master/integrate-eureka2

总结

  1. 有存储功能的容器(如
    Eureka Server

    Spring
    )一般都会提供
    holder
    (钩子)来获取容器中的实例

  2. 尽量选同体系内的组件(比如都用
    Spring
    自带的组件),不会存在兼容性问题

  3. spring-cloud-balancer
    目前支持两种负载均衡策略


    spring-cloud-balancer 负载均衡策略

    轮询和随机,默认是轮询;如果需要其他的复杂均衡策略,则需要自定义

标签: none

添加新评论