【遠程調用框架】如何實現一個簡單的RPC框架(五)優化三:軟負載中心設計與實現

【如何實現一個簡單的RPC框架】系列文章:web

【遠程調用框架】如何實現一個簡單的RPC框架(一)想法與設計 
【遠程調用框架】如何實現一個簡單的RPC框架(二)實現與使用 
【遠程調用框架】如何實現一個簡單的RPC框架(三)優化一:利用動態代理改變用戶服務調用方式 
【遠程調用框架】如何實現一個簡單的RPC框架(四)優化二:改變底層通訊框架 
【遠程調用框架】如何實現一個簡單的RPC框架(五)優化三:軟負載中心設計與實現 
第一個優化以及第二個優化修改後的工程代碼可下載資源 如何實現一個簡單的RPC框架緩存

 

 

1.前言

在博客【遠程調用框架】如何實現一個簡單的RPC框架(一)想法與設計中咱們介紹了「服務註冊查找中心」,負責服務信息的管理即服務的註冊以及查找,在目前爲止的實現中,咱們採用web應用的方式,以http協議接口的方式爲服務發佈者以及調用者提供使用接口。服務發佈者在發佈服務的同時須要將服務的信息註冊到「服務註冊查找中心」,供服務調用者進行查詢。可是這種方式,有一個很大的弊端就是:沒法正確及時感知服務的上線與下線,並及時將服務信息的更改推送到服務調用端。 
所以這裏咱們將「服務註冊查找中心」改形成一個「軟負載中心」來代替「服務註冊查找中心」的職責。軟負載中心主要負責服務地址等信息的聚合與管理,同時能正確進行服務上下線的感知並推送給服務的訂閱者。 
本博客內容部分摘自《大型網站系統與Java中間件實踐》數據結構

2.主要功能與結構

2.1 軟負載中心的主要功能

2.1.1 聚合地址信息

不管是服務框架中須要用到的服務提供者地址,仍是消息中間件系統中的消息中間件應用的地址,都須要由軟負載中心去聚合地址列表,造成一個可供服務調用者及消息的發送者、接收者直接使用的列表。框架

2.1.2 生命週期感知

軟負載中心須要能對服務的上下線自動感知,而且根據這個變化去更新服務地址數據,想成新的地址列表後,把數據傳給須要數據的調用者活着消息的發送者接收者。socket

2.2 軟負載中心的結構

軟負載中心包括兩部分(1)軟負載中心的服務端;(2)軟負載中心的客戶端ide

2.2.1 服務端

服務端主要負責:性能

  • (1)感知提供服務的機器是否在線。與服務發佈者保持長鏈接,感知服務存活狀態,並即便更新服務地址信息;
  • (2)聚合提供者的機器信息。對地址信息進行管理;
  • (3)而且負責把數據傳給使用數據的應用。當某一個服務的地址信息有變化時,及時將信息推送給該服務的訂閱者

2.2.2 客戶端

客戶端承載了兩個角色,優化

  • (1)做爲服務提供者,客戶端負責與軟負載中心創建長鏈接,把服務提供者提供服務的具體信息主動傳給服務端,而且隨着提供服務的變化去更新數據;
  • (2)做爲服務使用者,客戶端負責與軟負載中心創建長鏈接,向服務端告知本身所須要使用的數據並負責接收服務端的推送,更新數據,還要進行本地的數據緩存,經過本地的數據緩存,使得每次去請求服務獲取列表都是一個本地操做,從而提高效率和性能。

3.設計

3.1 軟負載中心維護的三類重要數據

軟負載中心須要管理服務地址等信息供服務調用者查詢使用,同時須要保存服務的訂閱關係信息,在服務地址信息發生變化時,將最新結果推送給訂閱該服務的相關客戶端用戶,同時也要維護軟負載中心與服務發佈端/調用端的鏈接。所以,軟負載中心內部有三部分重要的數據:網站

3.1.1 聚合數據

就是聚合後的地址信息列表。spa

3.1.2 訂閱關係

在軟負載中心,須要數據的應用(服務使用者等)把本身須要的數據信息高速軟負載中心,這就是一個訂閱關係,訂閱的粒度和聚合數據的粒度是一致的。當聚合數據有變化時,也是經過訂閱關係的數據找到須要通知的數據訂閱者,而後去進行數據更新的通知。 
3.1.3 鏈接數據 
是指鏈接到軟負載中心的節點和軟負載中心已經創建的鏈接的管理。採用的是長鏈接的方式,當訂閱的數據產生變化時,經過訂閱關係找到須要通知的使用者id,在鏈接數據這裏就能找到對應的鏈接,而後進行數據的發送,完成對應用的數據更新。

3.2 軟負載中心工做模式

這裏寫圖片描述
- (1)服務發佈者須要進行服務註冊時,主動與軟負載中心創建socket長鏈接,發送服務註冊信息DO,同時經過發送心跳包保持與軟負載中心的長鏈接; 
- (2)軟負載中心在收到服務發佈者發送的心跳包後更新該服務地址的最後更新時間,以此來判斷服務是否存活,實時更新服務的地址列表; 
- (3)服務調用者在進行服務調用時會查詢本地緩存獲取服務的地址列表,而調用者也會與軟負載中心創建長鏈接,實時更新本地緩存; 
- (4)全部聚合數據有變的狀況下,都要根據訂閱關係,即時講服務的最新信息推送給該服務的訂閱者

3.3 軟負載中心設計

3.3.1 通訊數據結構設計

  • (1)客戶端向服務端發送的請求數據包DO 
    數據包DO表明服務發佈端以及服務調用端與軟負載中心服務端長鏈接中傳遞的數據包數據結構。長鏈接中客戶端向服務端傳送的數據主要包含四種類型,服務發佈者發送的註冊服務信息以及爲了保持長鏈接發送的心跳數據、服務調用端發送的服務地址查詢信息以及爲了保持長鏈接發送的心跳數據。數據結構以下圖所示: 
    這裏寫圖片描述
  • (2)服務端向客戶端發送的響應數據包DO 
    服務端接收到客戶端的請求進行相應的處理後,響應給客戶端的數據結構包括:對於心跳包的響應、服務地址查詢結果、服務註冊結果。數據結構以下圖所示: 
    這裏寫圖片描述

3.3.2 服務端維護三種數據結構設計

  • (1)聚合數據:Map類型數據結構,key爲服務惟一標識,value爲ServiceInfoDO數據類型;
  • (2)訂閱關係:Map類型數據結構,key爲服務惟一標識,value爲訂閱該服務的鏈接惟一標識列表;
  • (3)鏈接數據:Map類型數據結構,key爲鏈接惟一標識,value爲socket長鏈接對象;
  • (4)鏈接數據:Map類型數據結構,key爲鏈接惟一標識,value爲該鏈接的ObjectOutputStream;

3.3.3 客戶端接口設計

  • (1)做爲服務發佈者:a 註冊服務,與軟負載中心保持長鏈接,發送心跳包;b 關閉鏈接,中止服務;
  • (2)做爲服務調用者:a 訂閱服務,與軟負載中心保持長鏈接,查詢服務地址,並接收軟負載中心發送數據,更新本地緩存;b 查詢服務信息(查詢本地緩存); c 關閉鏈接,刪除訂閱關係 
    本地緩存:map類型的數據結構,key爲服務惟一標識,value爲服務地址列表。

4.實現與使用

4.1 資源下載

軟負載中心的工程代碼,可訪問 實現一個簡單的軟負載中心 進行下載;

4.2 使用示例

pom中寫上對軟負載中心客戶端的依賴,以下:

<dependency>
    <groupId>whu.edu.lcrpc.configserver</groupId>
    <artifactId>configserver-client</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5

4.2.1 服務發佈

使用方式以下代碼:

//軟負載中心客戶端的幫助類
IServiceProviderClient serviceProviderClient = new ServiceProviderClientImpl();

//定義一個服務信息的數據結構
ServiceInfoDO serviceInfoDO = new ServiceInfoDO();
serviceInfoDO.setInterfaceName("interfacename");
serviceInfoDO.setVersion("version");
serviceInfoDO.setIp("10.129.34.19");
serviceInfoDO.setImplClassName("implClassName");
//註冊服務
if (serviceProviderClient.serviceRegistry(serviceInfoDO)){
    System.out.println("服務[" + serviceInfoDO.getInterfaceName() + "_" + serviceInfoDO.getVersion() + "]註冊成功");
}else {
    System.out.println("服務[" + serviceInfoDO.getInterfaceName() + "_" + serviceInfoDO.getVersion() + "]註冊失敗");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

4.2.3 服務訂閱

使用方式以下代碼:

//軟負載中心客戶端提供的輔助類
ServiceConsumerClientImpl serviceConsumerClient = new ServiceConsumerClientImpl();

try {
    //訂閱服務,服務的惟一標識爲"interfacename_version"
    serviceConsumerClient.subscribeServiceInfo("interfacename_version");
    //訂閱服務完成後,查詢服務的地址列表
    Set<String> ips = serviceConsumerClient.queryServiceInfo("interfacename_version");
    //輸出該服務的地址列表
    System.out.println("服務[" + "interfacename_version" + "]的地址列表爲: " + ips);
} catch (NoServiceFoundException noServiceFound) {
    System.out.println("服務[" + "interfacename_version" + "]未找到");
    noServiceFound.printStackTrace();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

4.2.4 效果

  • (1)運行軟負載中心,開啓監聽,以下圖所示 
    這裏寫圖片描述

  • (2)發佈服務,以下圖分別爲軟負載中心接收到服務註冊請求後的效果、服務發佈者輸出效果 
    這裏寫圖片描述 
    這裏寫圖片描述

  • (3)服務訂閱,以下圖分別爲軟負載中心接收到服務訂閱請求後的效果、服務訂閱者輸出效果 
    這裏寫圖片描述
    軟負載中心檢測到服務增長了一個訂閱者 
    這裏寫圖片描述
  • (4)關閉服務發佈後,軟負載中心以及服務發佈端的輸出以下圖所示 
    這裏寫圖片描述
    軟負載中心監測到服務已經下線,所以會將該服務的更新信息推送給該服務的訂閱者。 
    這裏寫圖片描述  服務調用端接收到軟負載中心的推送後,更新了本地緩存,更新了該服務的地址列表信息
相關文章
相關標籤/搜索