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

青石路發表於2024-07-01

開心一刻

暗戀公司的一個女同事,聊了快一年了,一直沒勇氣表白

上個月突然找我借 5000 塊錢,我直接轉給她了

我:這錢幹嘛用的?

她:給男朋友買個手機

我強顏歡笑說:你真貼心

幾天後我收到一個快遞,開啟一看是部手機!!!

我壓抑著內心的激動,放下手頭的工作,立馬微信上問她怎麼回事

她說:手機她男朋友不喜歡,商家也不給退,就當還我錢了……

殺人誅心

需求描述

一天,領導找到我,巴拉巴拉一頓溝通,需求很清晰,我就不細說了(因為跟本文關係不大),總結下就是

有兩個服務:任務分發中心、任務執行器
分發中心負責任務拆分,然後將拆分後的任務下發給執行器,執行器執行任務
任務分發中心和任務執行器都要支援水平擴節點

我說:技術實現沒什麼難點,引入註冊中心就行

但領導緊接著就說:考慮到客戶硬體資源的侷限性以及部署的複雜性,不能單獨部署註冊中心

當時我就懵了,心裡想的是

既要馬兒跑,又要馬兒不吃草,咋不讓我上天?

工作要緊

我接著說道:任務分發中心兼職註冊中心,任務執行器能夠自動註冊到分發中心?

領導:對,你總結的言簡意賅,就是要實現這樣的效果

領導又補充道:你可以簡單點實現,不用像 Nacos 那樣複雜,服務支援水平擴充套件,能夠監控任務執行器狀態就行

相信大家都明白需求了,總結成一句話

拿著賣白菜的錢,要幹賣白粉的事!

需求實現

主流的註冊中心,像ZookeeperNacosetcd、Consul 以及 Eureka,都需要單獨部署;如果能單獨部署,那實現就簡單了,可現在要求是不能單獨部署,但又要有註冊中心的基本功能

寶寶心裡苦

說白了,就是要自實現一個簡易版的註冊中心,雖說是簡易版,但基本功能還是要有吧

  1. 服務發現
    註冊中心儲存和管理所有可用服務的地址資訊,其他服務可以透過查詢註冊中心發現所需的服務
  2. 服務註冊
    服務提供者可以將自己的地址資訊註冊到註冊中心,以便其他服務發現和呼叫
  3. 健康檢查
    註冊中心定期對註冊的服務進行健康檢查,以確保服務的可用性
    某個服務出現故障或不可用,註冊中心能夠將其從可用服務列表中移除,防止其他服務呼叫失敗
  4. 支援水平擴充
    註冊中心肯定要支援水平擴充來保障其高可用
    註冊中心節點之間要能正常通訊,節點之間的可用服務列表能夠及時同步,並且要保證一致

這些基本功能實現起來簡不簡單?也許你們覺的簡單,可我覺的並不簡單

但事已至此,已無退路,只能硬著頭皮上了

分發中心整合 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 搭建是不是沒區別?

肯定沒區別呀,我就是按平時的搭建流程來的,具體區別還要往下看

分發中心整合 Eureka Client

為了更好的體現 任務分發中心 整合 Eureka Client,我們簡化業務實現

任務執行器 就提供一個介面給 任務分發中心 呼叫

任務執行器介面_exec

任務分發中心 也提供一個介面給其他服務(例如 排程中心)呼叫

分發中心介面

重點來了,任務分發中心如何將拆分後的任務分發到任務執行器?

細化來講,分 3 點
1.任務分發中心能不能拿到任務執行器服務列表
2.能拿到的話,如何拿
3.拿到之後如何負載均衡的下發任務

第 1 點毋庸置疑,肯定能拿到,任務分發中心作為 Eureka Server,儲存了任務執行器的服務例項列表

第 2 、3點,我們可以將 任務分發中心 又當做 Eureka Client 試試,試試有不要錢

  1. 引入依賴
    Eureka Server 包含了Eureka Client ,不需要額外引入Eureka Client
    但需要引入 open-feign

    <dependency>
    	<groupId>org.springframework.cloud</groupId>
    	<artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    
  2. 開啟 Eureka Clientopen-feign

    @SpringBootApplication
    @EnableEurekaServer
    @EnableEurekaClient
    @EnableFeignClients
    public class TaskDispatcherApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(TaskDispatcherApplication.class, args);
        }
    }
    
  3. 實現 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-dispatchertask-executor ,然後呼叫介面

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

你會發現 500

500

看下日誌,關鍵資訊如下

Load balancer does not contain an instance for the service TASK-EXECUTOR

負載均衡器不包含 TASK-EXECUTOR 服務例項,這是因為我們有個配置關閉了

fetch-registry-false

導致 Eureka Client 未拉取其他服務,那麼 Load balancer 自然就獲取不到 TASK-EXECUTOR 例項了

我們將其開啟(設定成 true),然後啟動task-dispatchertask-executor,然後呼叫介面

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

結果 success,日誌輸出如下

  1. 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
    
  2. 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 是單例項,我們再啟動一個例項,來看看負載均衡效果

負載均衡

至此,需求是不是實現了

愣著幹啥,鼓掌

總結

  1. 註冊中心推薦單獨部署,不要摻雜業務程式碼
  2. Eureka Server 也可以做 Eureka Client,雖說不推薦,但有時候能止渴
  3. 要敢於嘗試,不試怎麼知道不行?

相關文章