经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Spring Boot » 查看文章
不单独部署注册中心,又要具备注册中心的功能,我能上天!
来源:cnblogs  作者:青石路  时间:2024/7/8 9:54:39  对本文有异议

开心一刻

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

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

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

我说道:为什么不让我进

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

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

书接上回

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

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

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

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

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

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

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

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

获取服务实例列表

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

我就不绕圈子了,我们需要用到一个 holderEurekaServerContextHolder,借此我们就能拿到 任务执行器 实例列表,例如:

EurekaServerContextHolder

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

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

负载均衡

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

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

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

spring-cloud-loadbalancer

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

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

ServiceInstanceListSupplier

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

任务分发

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

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

发送 HTTP 请求的方式不要太多,而 SpringRestTemplate 就是其中之一,为了不额外引用第三方 HTTP 工具,也为了适配负载均衡器,推荐就是用 RestTemplate

RestTemplate

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

任务分发

启动 task-dispatchertask-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 ServerSpring)一般都会提供 holder(钩子)来获取容器中的实例

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

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

    spring-cloud-balancer 负载均衡策略

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

原文链接:https://www.cnblogs.com/youzhibing/p/18286882

 友情链接:直通硅谷  点职佳