不單獨部署註冊中心,又要具備註冊中心的功能,我能上天!

青石路發表於2024-07-08

開心一刻

昨天看到一條廣告:全國比醜大賽,一等獎 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 負載均衡策略

    輪詢和隨機,預設是輪詢;如果需要其他的複雜均衡策略,則需要自定義

相關文章