開心一刻
暗戀公司的一個女同事,聊了快一年了,一直沒勇氣表白
上個月突然找我借 5000 塊錢,我直接轉給她了
我:這錢幹嘛用的?
她:給男朋友買個手機
我強顏歡笑說:你真貼心
幾天後我收到一個快遞,開啟一看是部手機!!!
我壓抑著內心的激動,放下手頭的工作,立馬微信上問她怎麼回事
她說:手機她男朋友不喜歡,商家也不給退,就當還我錢了……
需求描述
一天,領導找到我,巴拉巴拉一頓溝通,需求很清晰,我就不細說了(因為跟本文關係不大),總結下就是
有兩個服務:任務分發中心、任務執行器
分發中心負責任務拆分,然後將拆分後的任務下發給執行器,執行器執行任務
任務分發中心和任務執行器都要支援水平擴節點
我說:技術實現沒什麼難點,引入註冊中心就行
但領導緊接著就說:考慮到客戶硬體資源的侷限性以及部署的複雜性,不能單獨部署註冊中心
當時我就懵了,心裡想的是
既要馬兒跑,又要馬兒不吃草,咋不讓我上天?
我接著說道:任務分發中心兼職註冊中心,任務執行器能夠自動註冊到分發中心?
領導:對,你總結的言簡意賅,就是要實現這樣的效果
領導又補充道:你可以簡單點實現,不用像 Nacos
那樣複雜,服務支援水平擴充套件,能夠監控任務執行器狀態就行
相信大家都明白需求了,總結成一句話
拿著賣白菜的錢,要幹賣白粉的事!
需求實現
主流的註冊中心,像Zookeeper
、Nacos
、etcd、
、Consul
以及 Eureka
,都需要單獨部署;如果能單獨部署,那實現就簡單了,可現在要求是不能單獨部署,但又要有註冊中心的基本功能
說白了,就是要自實現一個簡易版的註冊中心,雖說是簡易版,但基本功能還是要有吧
- 服務發現
註冊中心儲存和管理所有可用服務的地址資訊,其他服務可以透過查詢註冊中心發現所需的服務- 服務註冊
服務提供者可以將自己的地址資訊註冊到註冊中心,以便其他服務發現和呼叫- 健康檢查
註冊中心定期對註冊的服務進行健康檢查,以確保服務的可用性
某個服務出現故障或不可用,註冊中心能夠將其從可用服務列表中移除,防止其他服務呼叫失敗- 支援水平擴充
註冊中心肯定要支援水平擴充來保障其高可用
註冊中心節點之間要能正常通訊,節點之間的可用服務列表能夠及時同步,並且要保證一致
這些基本功能實現起來簡不簡單?也許你們覺的簡單,可我覺的並不簡單
但事已至此,已無退路,只能硬著頭皮上了
分發中心整合 Eureka Server
幾個主流的註冊中心,我對 Eureka
比較熟悉,感覺其實現還算比較簡單,參考它來實現註冊中心應該可行
一頭扎進去看原始碼,一天下來收效甚微,發現並非想象中的那麼簡單,正當我準備放棄時,腦中閃過一個念頭
任務分發中心可不可以整合 Eureka Server?
Eureka Server
是註冊中心,這個我們都知道,但我們忽略了一個點,它還是一個普通 Web 服務,只是我們平時不用它來處理業務請求,僅僅是把它當做一個註冊中心
從定位來講,Eureka Server
確實只應該做註冊中心該做的事,不應該關聯到業務,尤其是服務多時,Eureka Server
維護壓力大,更不應該關聯業務
但有時候也需要特殊情況特殊處理,比如我目前的需求,註冊中心維護的服務就一個 任務執行器
,任務執行器的節點也不會很多,頂天 10 個,也就是 Eureka Servr
維護服務的壓力會很小,同時業務處理也很簡單:任務拆分,然後分發
這麼分析下來,任務分發中心整合 Eureka Server
是可行的,說幹就幹!
Eureka server
搭建不要太簡單,你們肯定都會
https://gitee.com/youzhibing/qsl-project/tree/master/integrate-eureka
搭建過程就不演示了,偷懶的小夥伴可以直接用我提供的程式碼
此時的程式碼結構如下(未包含業務程式碼)
搭建完成後啟動服務,Eureka
監控如下
至此,Eureka
整合完成
你們發現沒,前面的 Eureka
搭建跟我們平時的 Eureka
搭建是不是沒區別?
肯定沒區別呀,我就是按平時的搭建流程來的,具體區別還要往下看
分發中心整合 Eureka Client
為了更好的體現 任務分發中心
整合 Eureka Client
,我們簡化業務實現
任務執行器
就提供一個介面給 任務分發中心
呼叫
任務分發中心
也提供一個介面給其他服務(例如 排程中心
)呼叫
重點來了,任務分發中心如何將拆分後的任務分發到任務執行器?
細化來講,分 3 點
1.任務分發中心能不能拿到任務執行器服務列表
2.能拿到的話,如何拿
3.拿到之後如何負載均衡的下發任務
第 1 點毋庸置疑,肯定能拿到,任務分發中心作為 Eureka Server
,儲存了任務執行器的服務例項列表
第 2 、3點,我們可以將 任務分發中心
又當做 Eureka Client
試試,試試有不要錢
-
引入依賴
Eureka Server
包含了Eureka Client
,不需要額外引入Eureka Client
但需要引入open-feign
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
-
開啟
Eureka Client
和open-feign
@SpringBootApplication @EnableEurekaServer @EnableEurekaClient @EnableFeignClients public class TaskDispatcherApplication { public static void main(String[] args) { SpringApplication.run(TaskDispatcherApplication.class, args); } }
-
實現
TaskExecutorService
,完成對任務執行器
負載均衡呼叫@FeignClient("TASK-EXECUTOR") public interface TaskExecutorService { @GetMapping("task/exec") String exec(@RequestParam("taskId") Long taskId); }
@GetMapping("dispatch") public String dispatch(Long jobId) { LOGGER.info("收到作業[jobId={}]執行請求", jobId); LOGGER.info("作業[jobId={}]拆分任務中...", jobId); List<Long> taskIds = Arrays.asList(123L, 666L, 888L, 999L); LOGGER.info("作業[jobId={}]拆分完成,得到作業列表[{}]", jobId, taskIds); for (Long taskId : taskIds) { String execResult = taskExecutorService.exec(taskId); LOGGER.info("任務[{}]執行結果:{}", taskId, execResult); } return "success"; }
啟動 task-dispatcher
、task-executor
,然後呼叫介面
http://192.168.2.10:8080/dispatcher/job/dispatch?jobId=689
你會發現 500
了
看下日誌,關鍵資訊如下
Load balancer does not contain an instance for the service TASK-EXECUTOR
負載均衡器不包含 TASK-EXECUTOR
服務例項,這是因為我們有個配置關閉了
導致 Eureka Client
未拉取其他服務,那麼 Load balancer
自然就獲取不到 TASK-EXECUTOR
例項了
我們將其開啟(設定成 true
),然後啟動task-dispatcher
、task-executor
,然後呼叫介面
http://192.168.2.10:8080/dispatcher/job/dispatch?jobId=689
結果 success
,日誌輸出如下
-
task-dispatcher
2024-06-30 10:51:51.653|INFO|http-nio-8080-exec-3|25|com.qsl.task.web.JobController :收到作業[jobId=689]執行請求 2024-06-30 10:51:51.653|INFO|http-nio-8080-exec-3|26|com.qsl.task.web.JobController :作業[jobId=689]拆分任務中... 2024-06-30 10:51:51.653|INFO|http-nio-8080-exec-3|28|com.qsl.task.web.JobController :作業[jobId=689]拆分完成,得到作業列表[[123, 666, 888, 999]] 2024-06-30 10:51:51.657|INFO|http-nio-8080-exec-3|31|com.qsl.task.web.JobController :任務[123]執行結果:success 2024-06-30 10:51:51.660|INFO|http-nio-8080-exec-3|31|com.qsl.task.web.JobController :任務[666]執行結果:success 2024-06-30 10:51:51.663|INFO|http-nio-8080-exec-3|31|com.qsl.task.web.JobController :任務[888]執行結果:success 2024-06-30 10:51:51.665|INFO|http-nio-8080-exec-3|31|com.qsl.task.web.JobController :任務[999]執行結果:success
-
task-executor
2024-06-30 10:51:51.656|INFO|http-nio-8081-exec-6|17|com.qsl.task.web.TaskController :收到任務[taskId=123]執行請求 2024-06-30 10:51:51.656|INFO|http-nio-8081-exec-6|18|com.qsl.task.web.TaskController :任務[taskId=123]執行中... 2024-06-30 10:51:51.656|INFO|http-nio-8081-exec-6|19|com.qsl.task.web.TaskController :任務[taskId=123]執行完成 2024-06-30 10:51:51.659|INFO|http-nio-8081-exec-9|17|com.qsl.task.web.TaskController :收到任務[taskId=666]執行請求 2024-06-30 10:51:51.659|INFO|http-nio-8081-exec-9|18|com.qsl.task.web.TaskController :任務[taskId=666]執行中... 2024-06-30 10:51:51.659|INFO|http-nio-8081-exec-9|19|com.qsl.task.web.TaskController :任務[taskId=666]執行完成 2024-06-30 10:51:51.662|INFO|http-nio-8081-exec-8|17|com.qsl.task.web.TaskController :收到任務[taskId=888]執行請求 2024-06-30 10:51:51.662|INFO|http-nio-8081-exec-8|18|com.qsl.task.web.TaskController :任務[taskId=888]執行中... 2024-06-30 10:51:51.662|INFO|http-nio-8081-exec-8|19|com.qsl.task.web.TaskController :任務[taskId=888]執行完成 2024-06-30 10:51:51.664|INFO|http-nio-8081-exec-7|17|com.qsl.task.web.TaskController :收到任務[taskId=999]執行請求 2024-06-30 10:51:51.664|INFO|http-nio-8081-exec-7|18|com.qsl.task.web.TaskController :任務[taskId=999]執行中... 2024-06-30 10:51:51.664|INFO|http-nio-8081-exec-7|19|com.qsl.task.web.TaskController :任務[taskId=999]執行完成
目前 task-executor
是單例項,我們再啟動一個例項,來看看負載均衡效果
至此,需求是不是實現了
總結
- 註冊中心推薦單獨部署,不要摻雜業務程式碼
Eureka Server
也可以做Eureka Client
,雖說不推薦,但有時候能止渴- 要敢於嘗試,不試怎麼知道不行?