dubbo環境搭建

 

主要是經過使用tomcat和使用main方法進行發佈服務html

參考文章:node

http://blog.csdn.net/aixiaoyang168/article/details/51362675算法

http://dubbo.io/spring

代碼下載地址:數據庫

 http://pan.baidu.com/s/1bQOhhc編程

架構如以下:api

 

一下是官網內容:http://dubbo.io/user-guide/preface/architacture.html緩存

使用dubbo的緣由:tomcat

在大規模服務化以前,應用可能只是經過RMI或Hessian等工具,簡單的暴露和引用遠程服務,經過配置服務的URL地址進行調用,經過F5等硬件進行負載均衡。

(1) 當服務愈來愈多時,服務URL配置管理變得很是困難,F5硬件負載均衡器的單點壓力也愈來愈大。
此時須要一個服務註冊中心,動態的註冊和發現服務,使服務的位置透明。 並經過在消費方獲取服務提供方地址列表,實現軟負載均衡和Failover,下降對F5硬件負載均衡器的依賴,也能減小部分紅本。
(2) 當進一步發展,服務間依賴關係變得錯蹤複雜,甚至分不清哪一個應用要在哪一個應用以前啓動,架構師都不能完整的描述應用的架構關係。
這時,須要自動畫出應用間的依賴關係圖,以幫助架構師理清理關係。
(3) 接着,服務的調用量愈來愈大,服務的容量問題就暴露出來,這個服務須要多少機器支撐?何時該加機器?
爲了解決這些問題,第一步,要將服務如今天天的調用量,響應時間,都統計出來,做爲容量規劃的參考指標。 其次,要能夠動態調整權重,在線上,將某臺機器的權重一直加大,並在加大的過程當中記錄響應時間的變化,直到響應時間到達閥值,記錄此時的訪問量,再以此訪問量乘以機器數反推總容量。

dubbo架構安全

節點角色說明:
Provider: 暴露服務的服務提供方
Consumer: 調用遠程服務的服務消費方。
Registry: 服務註冊與發現的註冊中心。
Monitor: 統計服務的調用次調和調用時間的監控中心。
Container: 服務運行容器。

  

 

調用關係說明:
服務容器負責啓動,加載,運行服務提供者。
服務提供者在啓動時,向註冊中心註冊本身提供的服務。
服務消費者在啓動時,向註冊中心訂閱本身所需的服務。
註冊中心返回服務提供者地址列表給消費者,若是有變動,註冊中心將基於長鏈接推送變動數據給消費者。
服務消費者,從提供者地址列表中,基於軟負載均衡算法,選一臺提供者進行調用,若是調用失敗,再選另外一臺調用。
服務消費者和提供者,在內存中累計調用次數和調用時間,定時每分鐘發送一次統計數據到監控中心。
(1) 連通性: 註冊中心負責服務地址的註冊與查找,至關於目錄服務,服務提供者和消費者只在啓動時與註冊中心交互,註冊中心不轉發請求,壓力較小 監控中心負責統計各服務調用次數,調用時間等,統計先在內存彙總後每分鐘一次發送到監控中心服務器,並以報表展現 服務提供者向註冊中心註冊其提供的服務,並彙報調用時間到監控中心,此時間不包含網絡開銷 服務消費者向註冊中心獲取服務提供者地址列表,並根據負載算法直接調用提供者,同時彙報調用時間到監控中心,此時間包含網絡開銷 註冊中心,服務提供者,服務消費者三者之間均爲長鏈接,監控中心除外 註冊中心經過長鏈接感知服務提供者的存在,服務提供者宕機,註冊中心將當即推送事件通知消費者 註冊中心和監控中心所有宕機,不影響已運行的提供者和消費者,消費者在本地緩存了提供者列表 註冊中心和監控中心都是可選的,服務消費者能夠直連服務提供者

(2) 健狀性: 監控中心宕掉不影響使用,只是丟失部分採樣數據 數據庫宕掉後,註冊中心仍能經過緩存提供服務列表查詢,但不能註冊新服務 註冊中心對等集羣,任意一臺宕掉後,將自動切換到另外一臺 註冊中心所有宕掉後,服務提供者和服務消費者仍能經過本地緩存通信 服務提供者無狀態,任意一臺宕掉後,不影響使用 服務提供者所有宕掉後,服務消費者應用將沒法使用,並沒有限次重連等待服務提供者恢復

(3) 伸縮性: 註冊中心爲對等集羣,可動態增長機器部署實例,全部客戶端將自動發現新的註冊中心 服務提供者無狀態,可動態增長機器部署實例,註冊中心將推送新的服務提供者信息給消費者

(4) 升級性: 當服務集羣規模進一步擴大,帶動IT治理結構進一步升級,須要實現動態部署,進行流動計算,現有分佈式服務架構不會帶來阻力:

  

 

  • Deployer: 自動部署服務的本地代理。
  • Repository: 倉庫用於存儲服務應用發佈包。
  • Scheduler: 調度中心基於訪問壓力自動增減服務提供者。
  • Admin: 統一管理控制檯。

 如下爲官網上說明文檔:

 schema說明

服務提供者暴露服務配置
<dubbo:service>
服務消費者引用服務配置
<dubbo:reference>
服務提供者協議配置:
<dubbo:protocol>
註冊中心配置
<dubbo:registry>
監控中心配置
<dubbo:monitor>
應用信息配置
<dubbo:application>
當前應用名稱,用於註冊中心計算應用間依賴關係,注意:消費者和提供者應用名不要同樣,此參數不是匹配條件,你當前項目叫什麼名字就填什麼,和提供者消費者角色無關,好比:kylin應用調用了morgan應用的服務,則kylin項目配成kylin,morgan項目配成morgan,可能kylin也提供其它服務給別人使用,但kylin項目永遠配成kylin,這樣註冊中心將顯示kylin依賴於morgan

服務提供者缺省值配置:
<dubbo:provider>
配置類:com.alibaba.dubbo.config.ProviderConfig
說明:該標籤爲|<dubbo:service>和|<dubbo:protocol>標籤的缺省值設置。

服務消費者缺省值配置:
<dubbo:consumer>
配置類:com.alibaba.dubbo.config.ConsumerConfig
說明:該標籤爲|<dubbo:reference>標籤的缺省值設置。

 

Dubbo缺省會在啓動時檢查依賴的服務是否可用,不可用時會拋出異常,阻止Spring初始化完成,以便上線時,能及早發現問題,默認 check="true"

warning若是你的Spring容器是懶加載的,或者經過API編程延遲引用服務,請關閉check,不然服務臨時不可用時,會拋出異常,拿到null引用,若是 check="false",老是會返回引用,當服務恢復時,能自動連上。

關閉某個服務的啓動時檢查:

沒有提供者時報錯

<dubbo:reference interface="com.foo.BarService" check="false" />
關閉全部服務的啓動時檢查:

沒有提供者時報錯

<dubbo:consumer check="false" />
關閉註冊中心啓動時檢查:

註冊訂閱失敗時報錯

<dubbo:registry check="false" />

集羣容錯

 

各節點關係:

  • 這裏的Invoker是Provider的一個可調用Service的抽象,Invoker封裝了Provider地址及Service接口信息。
  • Directory表明多個Invoker,能夠把它當作List,但與List不一樣的是,它的值多是動態變化的,好比註冊中心推送變動。
  • Cluster將Directory中的多個Invoker假裝成一個Invoker,對上層透明,假裝過程包含了容錯邏輯,調用失敗後,重試另外一個。
  • Router負責從多個Invoker中按路由規則選出子集,好比讀寫分離,應用隔離等。
  • LoadBalance負責從多個Invoker中選出具體的一個用於本次調用,選的過程包含了負載均衡算法,調用失敗後,須要重選
集羣容錯模式

能夠自行擴展集羣容錯策略,參見:集羣擴展

Failover Cluster
  • 失敗自動切換,當出現失敗,重試其它服務器。(缺省)
  • 一般用於讀操做,但重試會帶來更長延遲。
  • 可經過 retries="2" 來設置重試次數(不含第一次)。
Failfast Cluster
  • 快速失敗,只發起一次調用,失敗當即報錯。
  • 一般用於非冪等性的寫操做,好比新增記錄。
Failsafe Cluster
  • 失敗安全,出現異常時,直接忽略。
  • 一般用於寫入審計日誌等操做。
Failback Cluster
  • 失敗自動恢復,後臺記錄失敗請求,定時重發。
  • 一般用於消息通知操做。
Forking Cluster
  • 並行調用多個服務器,只要一個成功即返回。
  • 一般用於實時性要求較高的讀操做,但須要浪費更多服務資源。
  • 可經過 forks="2" 來設置最大並行數。
Broadcast Cluster
  • 廣播調用全部提供者,逐個調用,任意一臺報錯則報錯。(2.1.0開始支持)
  • 一般用於通知全部提供者更新緩存或日誌等本地資源信息。

重試次數配置如: (failover集羣模式生效)

<dubbo:service retries="2" /> 

<dubbo:reference retries="2" /> 

<dubbo:reference> <dubbo:method name="findFoo" retries="2" /> </dubbo:reference> 

集羣模式配置如:

<dubbo:service cluster="failsafe" /> 

<dubbo:reference cluster="failsafe" />
 

 負載均衡

Random LoadBalance

隨機,按權重設置隨機機率。
在一個截面上碰撞的機率高,但調用量越大分佈越均勻,並且按機率使用權重後也比較均勻,有利於動態調整提供者權重。
RoundRobin LoadBalance

輪循,按公約後的權重設置輪循比率。
存在慢的提供者累積請求的問題,好比:第二臺機器很慢,但沒掛,當請求調到第二臺時就卡在那,長此以往,全部請求都卡在調到第二臺上。
LeastActive LoadBalance

最少活躍調用數,相同活躍數的隨機,活躍數指調用先後計數差。
使慢的提供者收到更少請求,由於越慢的提供者的調用先後計數差會越大。
ConsistentHash LoadBalance

一致性Hash,相同參數的請求老是發到同一提供者。
當某一臺提供者掛時,本來發往該提供者的請求,基於虛擬節點,平攤到其它提供者,不會引發劇烈變更。
算法參見:http://en.wikipedia.org/wiki/Consistent_hashing。
缺省只對第一個參數Hash,若是要修改,請配置<dubbo:parameter key="hash.arguments" value="0,1" />
缺省用160份虛擬節點,若是要修改,請配置 <dubbo:parameter key="hash.nodes" value="320" />
配置如:

<dubbo:service interface="..." loadbalance="roundrobin" />
或

<dubbo:reference interface="..." loadbalance="roundrobin" />
或

<dubbo:service interface="...">
    <dubbo:method name="..." loadbalance="roundrobin"/>
</dubbo:service>
或

<dubbo:reference interface="...">
    <dubbo:method name="..." loadbalance="roundrobin"/>
</dubbo:reference>

  

線程模型

事件處理線程說明

若是事件處理的邏輯能迅速完成,而且不會發起新的IO請求,好比只是在內存中記個標識,則直接在IO線程上處理更快,由於減小了線程池調度。
但若是事件處理邏輯較慢,或者須要發起新的IO請求,好比須要查詢數據庫,則必須派發到線程池,不然IO線程阻塞,將致使不能接收其它請求。
若是用IO線程處理事件,又在事件處理過程當中發起新的IO請求,好比在鏈接事件中發起登陸請求,會報「可能引起死鎖」異常,但不會真死鎖。
Dispatcher

all 全部消息都派發到線程池,包括請求,響應,鏈接事件,斷開事件,心跳等。
direct 全部消息都不派發到線程池,所有在IO線程上直接執行。
message 只有請求響應消息派發到線程池,其它鏈接斷開事件,心跳等消息,直接在IO線程上執行。
execution 只請求消息派發到線程池,不含響應,響應和其它鏈接斷開事件,心跳等消息,直接在IO線程上執行。
connection 在IO線程上,將鏈接斷開事件放入隊列,有序逐個執行,其它消息派發到線程池。
ThreadPool

fixed 固定大小線程池,啓動時創建線程,不關閉,一直持有。(缺省)
cached 緩存線程池,空閒一分鐘自動刪除,須要時重建。
limited 可伸縮線程池,但池中的線程數只會增加不會收縮。(爲避免收縮時忽然來了大流量引發的性能問題)。
配置以下:

<dubbo:protocol name="dubbo" dispatcher="all" threadpool="fixed" threads="100" />

 (1) 不一樣服務不一樣協議

好比:不一樣服務在性能上適用不一樣協議進行傳輸,好比大數據用短鏈接協議,小數據大併發用長鏈接協議

consumer.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
    xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://code.alibabatech.com/schema/dubbohttp://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <dubbo:application name="world"  />
    <dubbo:registry id="registry" address="10.20.141.150:9090" username="admin" password="hello1234" />

    <!-- 多協議配置 -->
    <dubbo:protocol name="dubbo" port="20880" />
    <dubbo:protocol name="rmi" port="1099" />

    <!-- 使用dubbo協議暴露服務 -->
    <dubbo:service interface="com.alibaba.hello.api.HelloService" version="1.0.0" ref="helloService" protocol="dubbo" />
    <!-- 使用rmi協議暴露服務 -->
    <dubbo:service interface="com.alibaba.hello.api.DemoService" version="1.0.0" ref="demoService" protocol="rmi" /> 
</beans>
(2) 多協議暴露服務

好比:須要與http客戶端互操做

consumer.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
    xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://code.alibabatech.com/schema/dubbohttp://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <dubbo:application name="world"  />
    <dubbo:registry id="registry" address="10.20.141.150:9090" username="admin" password="hello1234" />

    <!-- 多協議配置 -->
    <dubbo:protocol name="dubbo" port="20880" />
    <dubbo:protocol name="hessian" port="8080" />

    <!-- 使用多個協議暴露服務 -->
    <dubbo:service id="helloService" interface="com.alibaba.hello.api.HelloService" version="1.0.0" protocol="dubbo,hessian" />
</beans>

 多版本

當一個接口實現,出現不兼容升級時,能夠用版本號過渡,版本號不一樣的服務相互間不引用。

在低壓力時間段,先升級一半提供者爲新版本
再將全部消費者升級爲新版本
而後將剩下的一半提供者升級爲新版本
老版本服務

<dubbo:service interface="com.foo.BarService" version="1.0.0" />
新版本服務

<dubbo:service interface="com.foo.BarService" version="2.0.0" />
引用老版本

<dubbo:reference id="barService" interface="com.foo.BarService" version="1.0.0" />
引用新版本

<dubbo:reference id="barService" interface="com.foo.BarService" version="2.0.0" />
不區分版本:(2.2.0以上版本支持)

<dubbo:reference id="barService" interface="com.foo.BarService" version="*" />

上下文信息:

上下文中存放的是當前調用過程當中所需的環境信息。

warning全部配置信息都將轉換爲URL的參數,參見 配置項一覽表 中的「對應URL參數」一列。

注意 RpcContext是一個ThreadLocal的臨時狀態記錄器,當接收到RPC請求,或發起RPC請求時,RpcContext的狀態都會變化。 好比:A調B,B再調C,則B機器上,在B調C以前,RpcContext記錄的是A調B的信息,在B調C以後,RpcContext記錄的是B調C的信息。

(1) 服務消費方

xxxService.xxx(); // 遠程調用
boolean isConsumerSide = RpcContext.getContext().isConsumerSide(); // 本端是否爲消費端,這裏會返回true
String serverIP = RpcContext.getContext().getRemoteHost(); // 獲取最後一次調用的提供方IP地址
String application = RpcContext.getContext().getUrl().getParameter("application"); // 獲取當前服務配置信息,全部配置信息都將轉換爲URL的參數
// ...
yyyService.yyy(); // 注意:每發起RPC調用,上下文狀態會變化
// ...
(2) 服務提供方

public class XxxServiceImpl implements XxxService {

    public void xxx() { // 服務方法實現
        boolean isProviderSide = RpcContext.getContext().isProviderSide(); // 本端是否爲提供端,這裏會返回true
        String clientIP = RpcContext.getContext().getRemoteHost(); // 獲取調用方IP地址
        String application = RpcContext.getContext().getUrl().getParameter("application"); // 獲取當前服務配置信息,全部配置信息都將轉換爲URL的參數
        // ...
        yyyService.yyy(); // 注意:每發起RPC調用,上下文狀態會變化
        boolean isProviderSide = RpcContext.getContext().isProviderSide(); // 此時本端變成消費端,這裏會返回false
        // ...
    } 
}

異步調用:

基於NIO的非阻塞實現並行調用,客戶端不須要啓動多線程便可完成並行調用多個遠程服務,相對多線程開銷較小。

warning2.0.6及其以上版本支持

/user-guide/images/future.jpg

配置聲明:

consumer.xml

<dubbo:reference id="fooService" interface="com.alibaba.foo.FooService">
      <dubbo:method name="findFoo" async="true" />
</dubbo:reference>
<dubbo:reference id="barService" interface="com.alibaba.bar.BarService">
      <dubbo:method name="findBar" async="true" />
</dubbo:reference>
調用代碼:

fooService.findFoo(fooId); // 此調用會當即返回null
Future<Foo> fooFuture = RpcContext.getContext().getFuture(); // 拿到調用的Future引用,當結果返回後,會被通知和設置到此Future。

barService.findBar(barId); // 此調用會當即返回null
Future<Bar> barFuture = RpcContext.getContext().getFuture(); // 拿到調用的Future引用,當結果返回後,會被通知和設置到此Future。

// 此時findFoo和findBar的請求同時在執行,客戶端不須要啓動多線程來支持並行,而是藉助NIO的非阻塞完成。

Foo foo = fooFuture.get(); // 若是foo已返回,直接拿到返回值,不然線程wait住,等待foo返回後,線程會被notify喚醒。
Bar bar = barFuture.get(); // 同理等待bar返回。

// 若是foo須要5秒返回,bar須要6秒返回,實際只需等6秒,便可獲取到foo和bar,進行接下來的處理。
你也能夠設置是否等待消息發出:(異步老是不等待返回)

sent="true" 等待消息發出,消息發送失敗將拋出異常。
sent="false" 不等待消息發出,將消息放入IO隊列,即刻返回。
<dubbo:method name="findFoo" async="true" sent="true" />
若是你只是想異步,徹底忽略返回值,能夠配置 return="false",以減小Future對象的建立和管理成本:

<dubbo:method name="findFoo" async="true" return="false" />
相關文章
相關標籤/搜索