dubbo官方文檔入門

官方文檔

  • 快速啟動

git clone https://github.com/apache/incubator-dubbo.git
cd incubator-dubbo
運行 dubbo-demo-provider中的com.alibaba.dubbo.demo.provider.Provider
如果使用Intellij Idea 請加上-Djava.net.preferIPv4Stack=true
  • 關(guān)鍵配置
<?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://dubbo.apache.org/schema/dubbo"
    xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd        http://dubbo.apache.org/schema/dubbo        http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
 
    <!-- 提供方應(yīng)用信息,用于計算依賴關(guān)系 -->
    <dubbo:application name="hello-world-app"  />
 
    <!-- 使用multicast廣播注冊中心暴露服務(wù)地址 -->
    <dubbo:registry address="zookeeper://224.5.6.7:1234" />
 
    <!-- 用dubbo協(xié)議在20880端口暴露服務(wù) -->
    <dubbo:protocol name="dubbo" port="20880" />

    <!-- 聲明需要暴露的服務(wù)接口 -->
    <dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService" />

  • 啟動類
public class Provider {

    /**
     * To get ipv6 address to work, add
     * System.setProperty("java.net.preferIPv6Addresses", "true");
     * before running your application.
     */
    public static void main(String[] args) throws Exception {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-provider.xml"});
        context.start();
        System.in.read(); // press any key to exit
    }
}

XML配置-標(biāo)簽的含義-配置的優(yōu)先級


dubbo-admin搭建-github
dubbo-admin搭建-官方文檔

## java env
export JAVA_HOME=/usr/local/java/jdk1.8
export JRE_HOME=$JAVA_HOME/jre


nohup java -jar dubbo-admin.jar -Ddubbo.registry.address=zookeeper://eshop-cache01-64:2181 > /dev/null  2>&1 &

  • 啟動時檢查
    check="false"

  • 集群模式配置
    <dubbo:service cluster="failsafe" />

  • 負(fù)載均衡
    <dubbo:service interface="..." loadbalance="roundrobin" />

  • 線程模型
    接口com.alibaba.dubbo.common.threadpool.ThreadPool

    image.png

  • 直連提供者
    ${user.home}/dubbo-resolve.properties
    本地調(diào)試時可用之,消費端配置

  • 只訂閱
    為本地開發(fā)環(huán)境不影響其他環(huán)境的,暫停注冊功能;提供端配置
    <dubbo:registry address="10.20.153.10:9090" register="false" />

  • 只注冊

<dubbo:registry id="hzRegistry" address="10.20.153.10:9090" />
<dubbo:registry id="qdRegistry" address="10.20.141.150:9090" subscribe="false" />
    <!-- 多協(xié)議配置 -->
    <dubbo:protocol name="dubbo" port="20880" />
    <dubbo:protocol name="rmi" port="1099" />
    <!-- 使用dubbo協(xié)議暴露服務(wù) -->
    <dubbo:service interface="com.alibaba.hello.api.HelloService" version="1.0.0" ref="helloService" protocol="dubbo" />
    <!-- 使用rmi協(xié)議暴露服務(wù) -->
    <dubbo:service interface="com.alibaba.hello.api.DemoService" version="1.0.0" ref="demoService" protocol="rmi" /> 
  • 同一服務(wù)多種協(xié)議
    <dubbo:protocol name="dubbo" port="20880" />
    <dubbo:protocol name="hessian" port="8080" />
    <!-- 使用多個協(xié)議暴露服務(wù) -->
    <dubbo:service id="helloService" interface="com.alibaba.hello.api.HelloService" version="1.0.0" protocol="dubbo,hessian" />

    <!-- 多注冊中心配置 -->
    <dubbo:registry id="hangzhouRegistry" address="10.20.141.150:9090" />
    <dubbo:registry id="qingdaoRegistry" address="10.20.141.151:9010" default="false" />
    <!-- 向多個注冊中心注冊 -->
    <dubbo:service interface="com.alibaba.hello.api.HelloService" version="1.0.0" ref="helloService" registry="hangzhouRegistry,qingdaoRegistry" />

  • 同一服務(wù)引用不同注冊中心
    <!-- 多注冊中心配置 -->
    <dubbo:registry id="chinaRegistry" address="10.20.141.150:9090" />
    <dubbo:registry id="intlRegistry" address="10.20.154.177:9010" default="false" />
    <!-- 引用中文站服務(wù) -->
    <dubbo:reference id="chinaHelloService" interface="com.alibaba.hello.api.HelloService" version="1.0.0" registry="chinaRegistry" />
    <!-- 引用國際站站服務(wù) -->
    <dubbo:reference id="intlHelloService" interface="com.alibaba.hello.api.HelloService" version="1.0.0" registry="intlRegistry" />

  • 不同服務(wù)使用不同注冊中心
    <!-- 多注冊中心配置 -->
    <dubbo:registry id="chinaRegistry" address="10.20.141.150:9090" />
    <dubbo:registry id="intlRegistry" address="10.20.154.177:9010" default="false" />
    <!-- 向中文站注冊中心注冊 -->
    <dubbo:service interface="com.alibaba.hello.api.HelloService" version="1.0.0" ref="helloService" registry="chinaRegistry" />
    <!-- 向國際站注冊中心注冊 -->
    <dubbo:service interface="com.alibaba.hello.api.DemoService" version="1.0.0" ref="demoService" registry="intlRegistry" />
  • 服務(wù)分組
    當(dāng)一個接口有多種實現(xiàn)時,可以用 group 區(qū)分。
    <dubbo:service group="feedback" interface="com.xxx.IndexService" />
  • 多版本
    <dubbo:service interface="com.foo.BarService" version="1.0.0" />
  • 分組聚合
    <dubbo:reference interface="com.xxx.MenuService" group="aaa,bbb" merger="true" />
  • 參數(shù)驗證
  • 結(jié)果緩存
    <dubbo:reference interface="com.foo.BarService" cache="lru" />
  • 泛化引用
    <dubbo:reference id="barService" interface="com.foo.BarService" generic="true" />
GenericService barService = (GenericService) applicationContext.getBean("barService");
Object result = barService.$invoke("sayHello", new String[] { "java.lang.String" }, new Object[] { "World" });
<bean id="genericService" class="com.foo.MyGenericService" />
<dubbo:service interface="com.foo.BarService" ref="genericService" />
  • 回聲測試
    所有服務(wù)自動實現(xiàn) EchoService 接口,只需將任意服務(wù)引用強制轉(zhuǎn)型為 EchoService,即可使用
// 遠(yuǎn)程服務(wù)引用
MemberService memberService = ctx.getBean("memberService"); 
 
EchoService echoService = (EchoService) memberService; // 強制轉(zhuǎn)型為EchoService

// 回聲測試可用性
String status = echoService.$echo("OK"); 
 
assert(status.equals("OK"));
  • 上下文信息
    RpcContext 是一個 ThreadLocal 的臨時狀態(tài)記錄器,當(dāng)接收到 RPC 請求,或發(fā)起 RPC 請求時,RpcContext 的狀態(tài)都會變化。比如:A 調(diào) B,B 再調(diào) C,則 B 機器上,在 B 調(diào) C 之前,RpcContext 記錄的是 A 調(diào) B 的信息,在 B 調(diào) C 之后,RpcContext 記錄的是 B 調(diào) C 的信息。
// 遠(yuǎn)程調(diào)用
xxxService.xxx();
// 本端是否為消費端,這里會返回true
boolean isConsumerSide = RpcContext.getContext().isConsumerSide();
// 獲取最后一次調(diào)用的提供方IP地址
String serverIP = RpcContext.getContext().getRemoteHost();
// 獲取當(dāng)前服務(wù)配置信息,所有配置信息都將轉(zhuǎn)換為URL的參數(shù)
String application = RpcContext.getContext().getUrl().getParameter("application");
// 注意:每發(fā)起RPC調(diào)用,上下文狀態(tài)會變化
yyyService.yyy();
注意:path, group, version, dubbo, token, timeout 幾個 key 是保留字段
// 隱式傳參,后面的遠(yuǎn)程調(diào)用都會隱式將這些參數(shù)發(fā)送到服務(wù)器端,類似cookie,
//用于框架集成,不建議常規(guī)業(yè)務(wù)使用
RpcContext.getContext().setAttachment("index", "1"); 
xxxService.xxx(); // 遠(yuǎn)程調(diào)用
<dubbo:reference id="fooService" interface="com.alibaba.foo.FooService">
      <dubbo:method name="findFoo" async="true" sent="true" />
</dubbo:reference>

sent="true" 等待消息發(fā)出,消息發(fā)送失敗將拋出異常。
sent="false" 不等待消息發(fā)出,將消息放入 IO 隊列,即刻返回。

// 此調(diào)用會立即返回null
fooService.findFoo(fooId);
// 拿到調(diào)用的Future引用,當(dāng)結(jié)果返回后,會被通知和設(shè)置到此Future
Future<Foo> fooFuture = RpcContext.getContext().getFuture(); 
 
// 此調(diào)用會立即返回null
barService.findBar(barId);
// 拿到調(diào)用的Future引用,當(dāng)結(jié)果返回后,會被通知和設(shè)置到此Future
Future<Bar> barFuture = RpcContext.getContext().getFuture(); 
 
// 此時findFoo和findBar的請求同時在執(zhí)行,客戶端不需要啟動多線程來支持并行,而是借助NIO的非阻塞完成
 
// 如果foo已返回,直接拿到返回值,否則線程wait住,等待foo返回后,線程會被notify喚醒
Foo foo = fooFuture.get(); 
// 同理等待bar返回
Bar bar = barFuture.get(); 
 
// 如果foo需要5秒返回,bar需要6秒返回,實際只需等6秒,即可獲取到foo和bar,進(jìn)行接下來的處理。
<dubbo:service protocol="injvm" />
<dubbo:reference injvm="true" .../>
<dubbo:service injvm="true" .../>
<bean id ="demoCallback" class = "com.alibaba.dubbo.callback.implicit.NofifyImpl" />
<dubbo:reference id="demoService" interface="com.alibaba.dubbo.callback.implicit.IDemoService" version="1.0.0" group="cn" >
      <dubbo:method name="get" async="true" onreturn = "demoCallback.onreturn" onthrow="demoCallback.onthrow" />
</dubbo:reference>

<dubbo:service interface="com.foo.BarService" stub="com.foo.BarServiceStub" />

package com.foo;
public class BarServiceStub implements BarService { 
    private final BarService barService;
    
    // 構(gòu)造函數(shù)傳入真正的遠(yuǎn)程代理對象
    public (BarService barService) {
        this.barService = barService;
    }
 
    public String sayHello(String name) {
        // 此代碼在客戶端執(zhí)行, 你可以在客戶端做ThreadLocal本地緩存,或預(yù)先驗證參數(shù)是否合法,等等
        try {
            return barService.sayHello(name);
        } catch (Exception e) {
            // 你可以容錯,可以做任何AOP攔截事項
            return "容錯數(shù)據(jù)";
        }
    }
}
  • 本地偽裝
    本地偽裝通常用于服務(wù)降級
    <dubbo:reference interface="com.foo.BarService" mock="com.foo.BarServiceMock" />
package com.foo;
public class BarServiceMock implements BarService {
    public String sayHello(String name) {
        // 你可以偽造容錯數(shù)據(jù),此方法只在出現(xiàn)RpcException時被執(zhí)行
        return "容錯數(shù)據(jù)";
    }
}

如果服務(wù)的消費方經(jīng)常需要 try-catch 捕獲異常,請考慮改為 Mock 實現(xiàn),并在 Mock 實現(xiàn)中 return null

  • 延遲暴露
    延遲到 Spring 初始化完成后,再暴露服務(wù)
    <dubbo:service delay="-1" />

Spring 2.x 初始化死鎖問題規(guī)避辦法
強烈建議不要在服務(wù)的實現(xiàn)類中有 applicationContext.getBean() 的調(diào)用,全部采用 IoC 注入的方式使用 Spring的Bean。
如果實在要調(diào) getBean(),可以將 Dubbo 的配置放在 Spring 的最后加載。
如果不想依賴配置順序,可以使用 <dubbo:provider delay=”-1” />,使 Dubbo 在 Spring 容器初始化完后,再暴露服務(wù)。
如果大量使用 getBean(),相當(dāng)于已經(jīng)把 Spring 退化為工廠模式在用,可以將 Dubbo 的服務(wù)隔離單獨的 Spring 容器。

  • 并發(fā)控制
    服務(wù)端:<dubbo:service interface="com.foo.BarService" executes="10" />
    客戶端:<dubbo:reference interface="com.foo.BarService" actives="10" />
    如果 <dubbo:service> 和 <dubbo:reference> 都配了actives,<dubbo:reference> 優(yōu)先
    Load Balance 均衡
    配置服務(wù)的客戶端的 loadbalance 屬性為 leastactive,此 Loadbalance 會調(diào)用并發(fā)數(shù)最小的 Provider(Consumer端并發(fā)數(shù))。
    <dubbo:reference interface="com.foo.BarService" loadbalance="leastactive" />
  • 連接控制
    <dubbo:provider protocol="dubbo" accepts="10" />
    <dubbo:reference interface="com.foo.BarService" connections="10" />
  • 延遲連接
    <dubbo:protocol name="dubbo" lazy="true" />
    注意:該配置只對使用長連接的 dubbo 協(xié)議生效
  • 粘滯連接
  1. 粘滯連接用于有狀態(tài)服務(wù),盡可能讓客戶端總是向同一提供者發(fā)起調(diào)用
  2. 自動開啟延遲連接
    <dubbo:protocol name="dubbo" sticky="true" />
  • 令牌驗證
    可以在全局,服務(wù),協(xié)議級別設(shè)置
    <dubbo:provider interface="com.foo.BarService" token="true" />
  • 路由規(guī)則
    分為條件路由規(guī)則和腳本路由規(guī)則,并且支持可擴展
  • 配置規(guī)則
    向注冊中心寫入動態(tài)配置覆蓋規(guī)則
  • 服務(wù)降級
    registry.register(URL.valueOf("override://0.0.0.0/com.foo.BarService?category=configurators&dynamic=false&application=foo&mock=force:return+null"));

mock=force:return+null 表示消費方對該服務(wù)的方法調(diào)用都直接返回 null 值,不發(fā)起遠(yuǎn)程調(diào)用。用來屏蔽不重要服務(wù)不可用時對調(diào)用方的影響。
還可以改為 mock=fail:return+null 表示消費方對該服務(wù)的方法調(diào)用在失敗后,再返回 null 值,不拋異常。用來容忍不重要服務(wù)不穩(wěn)定時對調(diào)用方的影響。

  • 優(yōu)雅停機
    Dubbo 是通過 JDK 的 ShutdownHook 來完成優(yōu)雅停機的
    設(shè)置優(yōu)雅停機超時時間,缺省超時時間是 10 秒,如果超時則強制關(guān)閉
    dubbo.service.shutdown.wait=15000
  • 主機綁定
  • 日志適配
    <dubbo:application logger="log4j" />
  • 訪問日志
    <dubbo:protocol accesslog="true" />
    <dubbo:protocol accesslog="http://10.20.160.198/wiki/display/dubbo/foo/bar.log" />
  • 服務(wù)容器
  1. 自動加載 META-INF/spring 目錄下的所有 Spring 配置。
  2. 配置 spring 配置加載位置:dubbo.spring.config=classpath*:META-INF/spring/*.xml
    java com.alibaba.dubbo.container.Main -Ddubbo.container=spring,jetty,log4j
  • ReferenceConfig 緩存
    ReferenceConfig 實例很重,封裝了與注冊中心的連接以及與提供者的連接,需要緩存,參見 ReferenceConfigCache
ReferenceConfigCache cache = ReferenceConfigCache.getCache();
// cache.get方法中會緩存 Reference對象,并且調(diào)用ReferenceConfig.get方法啟動ReferenceConfig
XxxService xxxService = cache.get(reference);
// 注意! Cache會持有ReferenceConfig,不要在外部再調(diào)用ReferenceConfig的destroy方法,導(dǎo)致Cache內(nèi)的ReferenceConfig失效!
// 使用xxxService對象
xxxService.sayHello();
<dubbo:application ...>
    <dubbo:parameter key="dump.directory" value="/tmp" />
</dubbo:application>

默認(rèn)策略:
導(dǎo)出路徑,user.home標(biāo)識的用戶主目錄
導(dǎo)出間隔,最短間隔允許每隔10分鐘導(dǎo)出一次

  • 序列化
    啟用Kryo和FST
    <dubbo:protocol name="dubbo" serialization="kryo"/>

com.alibaba.dubbo.config.ServiceConfig
com.alibaba.dubbo.config.ReferenceConfig
com.alibaba.dubbo.config.ProtocolConfig
com.alibaba.dubbo.config.RegistryConfig
com.alibaba.dubbo.config.MonitorConfig
com.alibaba.dubbo.config.ApplicationConfig
com.alibaba.dubbo.config.ModuleConfig
com.alibaba.dubbo.config.ProviderConfig
com.alibaba.dubbo.config.ConsumerConfig
com.alibaba.dubbo.config.MethodConfig
com.alibaba.dubbo.config.ArgumentConfig
dubbo>help
Please input "help [command]" show detail.
 status [-l]                      - Show status.
 pwd                              - Print working default service.
 trace [service] [method] [times] - Trace the service.
 help [command]                   - Show help.
 exit                             - Exit the telnet.
 invoke [service.]method(args)    - Invoke the service method.
 clear [lines]                    - Clear screen.
 count [service] [method] [times] - Count the service.
 ls [-l] [service]                - List services and methods.
 log level                        - Change log level or show log
 ps [-l] [port]                   - Print server ports and connections.
 cd [service]                     - Change default service.

  1. 將服務(wù)接口,服務(wù)模型,服務(wù)異常等均放在 API 包中,分包原則:重用發(fā)布等價原則(REP),共同重用原則(CRP)
  2. 服務(wù)接口盡可能大粒度,每個服務(wù)方法應(yīng)代表一個功能,而不是某功能的一個步驟,否則將面臨分布式事務(wù)問題,Dubbo 暫未提供分布式事務(wù)支持
  3. 不建議使用過于抽象的通用接口,如:Map query(Map),這樣的接口沒有明確語義,會給后期維護(hù)帶來不便。
  4. 每個接口都應(yīng)定義版本號,為后續(xù)不兼容升級提供可能,如: <dubbo:service interface="com.xxx.XxxService" version="1.0" />
  5. 服務(wù)接口增加方法,或服務(wù)模型增加字段,可向后兼容,刪除方法或刪除字段,將不兼容,枚舉類型新增字段也不兼容,需通過變更版本號升級。詳細(xì)參見 服務(wù)協(xié)議
  6. 如果是完備集,可以用 Enum,比如:ENABLE, DISABLE。如果是業(yè)務(wù)種類,以后明顯會有類型增加,不建議用 Enum,可以用String 代替;注意升級的順序.
  7. 服務(wù)參數(shù)及返回值建議使用 POJO 對象,即通過 setter, getter 方法表示屬性的對象
  8. 建議使用異常匯報錯誤,而不是返回錯誤碼,異常信息能攜帶更多信息,以及語義更友好。
    如果擔(dān)心性能問題,在必要時,可以通過 override 掉異常類的 fillInStackTrace()方法為空方法,使其不拷貝棧信息。
  9. 不要只是因為是 Dubbo 調(diào)用,而把調(diào)用 try...catch 起來。try...catch 應(yīng)該加上合適的回滾邊界上。
    對于輸入?yún)?shù)的校驗邏輯在 Provider 端要有。如有性能上的考慮,服務(wù)實現(xiàn)者可以考慮在 API 包上加上服務(wù) Stub 類來完成檢驗。

  1. 在 Provider 上盡量多配置 Consumer 端屬性
<dubbo:service interface="com.alibaba.hello.api.WorldService" version="1.0.0" ref="helloService"
    timeout="300" retry="2" loadbalance="random" actives="0" >
    <dubbo:method name="findAllPerson" timeout="10000" retries="9" loadbalance="leastactive" actives="5" />
<dubbo:service/>
  1. Provider 上配置合理的 Provider 端屬性
  2. 配置管理信息
  3. 配置 Dubbo 緩存文件
    <dubbo:registry file=”${user.home}/output/dubbo.cache” />
    這個文件會緩存注冊中心的列表和服務(wù)提供者列表。有了這項配置后,當(dāng)應(yīng)用重啟過程中,Dubbo 注冊中心不可用時則應(yīng)用會從這個緩存文件讀取服務(wù)提供者列表的信息,進(jìn)一步保證應(yīng)用可靠性。
  4. 監(jiān)控配置
  5. 不要使用 dubbo.properties 文件配置,推薦使用對應(yīng) XML 配置

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,695評論 19 139
  • 0 準(zhǔn)備 安裝注冊中心:Zookeeper、Dubbox自帶的dubbo-registry-simple;安裝Du...
    七寸知架構(gòu)閱讀 14,114評論 0 88
  • Dubbo是什么 Dubbo是Alibaba開源的分布式服務(wù)框架,它最大的特點是按照分層的方式來架構(gòu),使用這種方式...
    Coselding閱讀 17,459評論 3 196
  • 沒有買肉經(jīng)驗的我去市場買肉,市場里有二十多家賣肉的,轉(zhuǎn)了一圈,看著肉都一樣,不知道哪家的肉好,更重要的是不...
    魚翔淺底韜光養(yǎng)晦閱讀 351評論 0 1
  • 住在成華區(qū)的時候,是電梯房五樓。那時候大門的門禁是虛設(shè)的,不用門禁卡也能推開,但是必須手扶,有一個關(guān)門的力。 有一...
    早安十二閱讀 107評論 0 0

友情鏈接更多精彩內(nèi)容