天天看點

51spark draft

51spark draft

Sina Architecture

51spark draft

Dubbo distribute architecture

51spark draft

       服務消費者程式通過服務接口使用服務,而服務接口通過代理加載具體服務,具體服務可以是本地的代碼子產品,也可以是遠端服務,是以對應用較少侵入:應用程式隻需要調用服務接口,服務架構根據配置自動調用本地或遠端實作.

      服務架構用戶端子產品通過服務注冊中心加載服務提供者清單(服務提供者啟動後自動向服務注冊中心注冊自己可提供的服務接口清單),查找需要的服務接口,并根據配置的負載均衡政策将服務調用請求發送到某台服務提供者伺服器. 如果服務調用失敗,用戶端子產品會自動從服務提供者清單選擇一個可提供同樣服務的另一台伺服器重新請求服務,實作服務的自動失效轉移,保證服務高可用.

     Dubbo的遠端服務通信子產品支援多種通信協定和資料序列化協定,使用NIO通信架構,具有較高的網絡通信性能.

(1)連通性:

注冊中心負載服務位址的注冊與查找,相當于目錄服務,服務提供者和消費者隻在啟動時與注冊中心互動,注冊中心不轉發請求,壓力小

控制中心負載統計各服務調用次數,調用時間等,統計先在記憶體彙總後每分鐘一次發送到監控中心伺服器,并以報表展示

服務提供者向注冊中心注冊其提供的服務,并彙報調用時間到監控中心,此時間不包含網絡開銷

服務消費者向注冊中心擷取服務提供者位址清單,并根據負載算法直接調用提供者,同時彙報調用時間到監控中心,此時間包含網絡開銷

注冊中心,服務提供者,服務消費者均為長連接配接,監控中心除外

注冊中心通過長連接配接感覺服務提供者的存在,服務提供者當機,注冊中心将立即推送事件通知消費者

注冊中心和監控中心全部當機,不影響已經運作的的提供者和消費者,消費者在本地緩存了提供者

注冊中心和監控中心都是可選的,服務消費者可用直連服務提供者

(2)健壯性:

監控中心宕掉不影響使用,隻是丢失部分采樣資料

資料庫宕掉後,注冊中心仍能通過緩存提供服務清單查詢,但不能注冊新服務

注冊中心對等叢集,任意一台宕掉後,将自動切換到另一台

注冊中心全部宕掉後,服務提供者和服務消費者仍能通過本地緩存通訊

服務提供者無狀态,任意一台宕掉不影響使用

服務提供者全部宕掉後,服務消費者應用将無法使用,不無限次重連等待服務提供者恢複

(3)伸縮性:

注冊中心為對等叢集,可動态添加機器布署執行個體,所有用戶端将自動發現新的注冊中心

服務提供者無狀态,可動态添加機器布署執行個體,注冊中心将推送新的服務提供者資訊給消費者

(4)更新性:

當服務叢集規模進一步擴大,帶動IT結構進一步更新,需要實作動态布署,進行流動計算,現有分布式服務架構不會帶來阻力

分析源代碼,基本原理如下:

1.client一個線程調用遠端接口,生成一個唯一的ID(比如一段随機字元串,UUID等),Dubbo是使用AtomicLong從0開始累計數字的

2.将打包的方法調用資訊(如調用的接口名稱,方法名稱,參數值清單等),和處理結果的回調對象callback,全部封裝在一起,組成一個對象object

3.向專門存放調用資訊的全局ConcurrentHashMap裡面put(ID, object)

4.将ID和打包的方法調用資訊封裝成一對象connRequest,使用IoSession.write(connRequest)異步發送出去

5.目前線程再使用callback的get()方法試圖擷取遠端傳回的結果,在get()内部,則使用synchronized擷取回調對象callback的鎖, 再先檢測是否已經擷取到結果,如果沒有,然後調用callback的wait()方法,釋放callback上的鎖,讓目前線程處于等待狀态。

6.服務端接收到請求并處理後,将結果(此結果中包含了前面的ID,即回傳)發送給用戶端,用戶端socket連接配接上專門監聽消息的線程收到消息,分析結果,取到ID,再從前面的ConcurrentHashMap裡面get(ID),進而找到callback,将方法調用結果設定到callback對象裡。

7.監聽線程接着使用synchronized擷取回調對象callback的鎖(因為前面調用過wait(),那個線程已釋放callback的鎖了),再notifyAll(),喚醒前面處于等待狀态的線程繼續執行(callback的get()方法繼續執行就能拿到調用結果了),至此,整個過程結束。

•目前線程怎麼讓它“暫停”,等結果回來後,再向後執行?

     答:先生成一個對象obj,在一個全局map裡put(ID,obj)存放起來,再用synchronized擷取obj鎖,再調用obj.wait()讓目前線程處于等待狀态,然後另一消息監聽線程等到服務端結果來了後,再map.get(ID)找到obj,再用synchronized擷取obj鎖,再調用obj.notifyAll()喚醒前面處于等待狀态的線程。

•正如前面所說,Socket通信是一個全雙工的方式,如果有多個線程同時進行遠端方法調用,這時建立在client server之間的socket連接配接上會有很多雙方發送的消息傳遞,前後順序也可能是亂七八糟的,server處理完結果後,将結果消息發送給client,client收到很多消息,怎麼知道哪個消息結果是原先哪個線程調用的?

     答:使用一個ID,讓其唯一,然後傳遞給服務端,再服務端又回傳回來,這樣就知道結果是原先哪個線程的了。

51Spark Architect 

51spark draft

網址涉及業務

51spark draft

業務拆分

51spark draft

繼續閱讀