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
  • 关键配置
<?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">
 
    <!-- 提供方应用信息,用于计算依赖关系 -->
    <dubbo:application name="hello-world-app"  />
 
    <!-- 使用multicast广播注册中心暴露服务地址 -->
    <dubbo:registry address="zookeeper://224.5.6.7:1234" />
 
    <!-- 用dubbo协议在20880端口暴露服务 -->
    <dubbo:protocol name="dubbo" port="20880" />

    <!-- 声明需要暴露的服务接口 -->
    <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配置-标签的含义-配置的优先级


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" />

  • 负载均衡
    <dubbo:service interface="..." loadbalance="roundrobin" />

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

    image.png

  • 直连提供者
    ${user.home}/dubbo-resolve.properties
    本地调试时可用之,消费端配置

  • 只订阅
    为本地开发环境不影响其他环境的,暂停注册功能;提供端配置
    <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" />
  • 静态服务
    <dubbo:registry address="10.20.141.150:9090" dynamic="false" />
  • 多协议
  • 不同服务不同协议
    <!-- 多协议配置 -->
    <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" /> 
  • 同一服务多种协议
    <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" />

    <!-- 多注册中心配置 -->
    <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" />

  • 同一服务引用不同注册中心
    <!-- 多注册中心配置 -->
    <dubbo:registry id="chinaRegistry" address="10.20.141.150:9090" />
    <dubbo:registry id="intlRegistry" address="10.20.154.177:9010" default="false" />
    <!-- 引用中文站服务 -->
    <dubbo:reference id="chinaHelloService" interface="com.alibaba.hello.api.HelloService" version="1.0.0" registry="chinaRegistry" />
    <!-- 引用国际站站服务 -->
    <dubbo:reference id="intlHelloService" interface="com.alibaba.hello.api.HelloService" version="1.0.0" registry="intlRegistry" />

  • 不同服务使用不同注册中心
    <!-- 多注册中心配置 -->
    <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" />
  • 服务分组
    当一个接口有多种实现时,可以用 group 区分。
    <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" />
  • 参数验证
  • 结果缓存
    <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" />
  • 回声测试
    所有服务自动实现 EchoService 接口,只需将任意服务引用强制转型为 EchoService,即可使用
// 远程服务引用
MemberService memberService = ctx.getBean("memberService"); 
 
EchoService echoService = (EchoService) memberService; // 强制转型为EchoService

// 回声测试可用性
String status = echoService.$echo("OK"); 
 
assert(status.equals("OK"));
  • 上下文信息
    RpcContext 是一个 ThreadLocal 的临时状态记录器,当接收到 RPC 请求,或发起 RPC 请求时,RpcContext 的状态都会变化。比如:A 调 B,B 再调 C,则 B 机器上,在 B 调 C 之前,RpcContext 记录的是 A 调 B 的信息,在 B 调 C 之后,RpcContext 记录的是 B 调 C 的信息。
// 远程调用
xxxService.xxx();
// 本端是否为消费端,这里会返回true
boolean isConsumerSide = RpcContext.getContext().isConsumerSide();
// 获取最后一次调用的提供方IP地址
String serverIP = RpcContext.getContext().getRemoteHost();
// 获取当前服务配置信息,所有配置信息都将转换为URL的参数
String application = RpcContext.getContext().getUrl().getParameter("application");
// 注意:每发起RPC调用,上下文状态会变化
yyyService.yyy();
注意:path, group, version, dubbo, token, timeout 几个 key 是保留字段
// 隐式传参,后面的远程调用都会隐式将这些参数发送到服务器端,类似cookie,
//用于框架集成,不建议常规业务使用
RpcContext.getContext().setAttachment("index", "1"); 
xxxService.xxx(); // 远程调用
<dubbo:reference id="fooService" interface="com.alibaba.foo.FooService">
      <dubbo:method name="findFoo" async="true" sent="true" />
</dubbo:reference>

sent="true" 等待消息发出,消息发送失败将抛出异常。
sent="false" 不等待消息发出,将消息放入 IO 队列,即刻返回。

// 此调用会立即返回null
fooService.findFoo(fooId);
// 拿到调用的Future引用,当结果返回后,会被通知和设置到此Future
Future<Foo> fooFuture = RpcContext.getContext().getFuture(); 
 
// 此调用会立即返回null
barService.findBar(barId);
// 拿到调用的Future引用,当结果返回后,会被通知和设置到此Future
Future<Bar> barFuture = RpcContext.getContext().getFuture(); 
 
// 此时findFoo和findBar的请求同时在执行,客户端不需要启动多线程来支持并行,而是借助NIO的非阻塞完成
 
// 如果foo已返回,直接拿到返回值,否则线程wait住,等待foo返回后,线程会被notify唤醒
Foo foo = fooFuture.get(); 
// 同理等待bar返回
Bar bar = barFuture.get(); 
 
// 如果foo需要5秒返回,bar需要6秒返回,实际只需等6秒,即可获取到foo和bar,进行接下来的处理。
<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;
    
    // 构造函数传入真正的远程代理对象
    public (BarService barService) {
        this.barService = barService;
    }
 
    public String sayHello(String name) {
        // 此代码在客户端执行, 你可以在客户端做ThreadLocal本地缓存,或预先验证参数是否合法,等等
        try {
            return barService.sayHello(name);
        } catch (Exception e) {
            // 你可以容错,可以做任何AOP拦截事项
            return "容错数据";
        }
    }
}
  • 本地伪装
    本地伪装通常用于服务降级
    <dubbo:reference interface="com.foo.BarService" mock="com.foo.BarServiceMock" />
package com.foo;
public class BarServiceMock implements BarService {
    public String sayHello(String name) {
        // 你可以伪造容错数据,此方法只在出现RpcException时被执行
        return "容错数据";
    }
}

如果服务的消费方经常需要 try-catch 捕获异常,请考虑改为 Mock 实现,并在 Mock 实现中 return null

  • 延迟暴露
    延迟到 Spring 初始化完成后,再暴露服务
    <dubbo:service delay="-1" />

Spring 2.x 初始化死锁问题规避办法
强烈建议不要在服务的实现类中有 applicationContext.getBean() 的调用,全部采用 IoC 注入的方式使用 Spring的Bean。
如果实在要调 getBean(),可以将 Dubbo 的配置放在 Spring 的最后加载。
如果不想依赖配置顺序,可以使用 <dubbo:provider delay=”-1” />,使 Dubbo 在 Spring 容器初始化完后,再暴露服务。
如果大量使用 getBean(),相当于已经把 Spring 退化为工厂模式在用,可以将 Dubbo 的服务隔离单独的 Spring 容器。

  • 并发控制
    服务端:<dubbo:service interface="com.foo.BarService" executes="10" />
    客户端:<dubbo:reference interface="com.foo.BarService" actives="10" />
    如果 <dubbo:service> 和 <dubbo:reference> 都配了actives,<dubbo:reference> 优先
    Load Balance 均衡
    配置服务的客户端的 loadbalance 属性为 leastactive,此 Loadbalance 会调用并发数最小的 Provider(Consumer端并发数)。
    <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 协议生效
  • 粘滞连接
  1. 粘滞连接用于有状态服务,尽可能让客户端总是向同一提供者发起调用
  2. 自动开启延迟连接
    <dubbo:protocol name="dubbo" sticky="true" />
  • 令牌验证
    可以在全局,服务,协议级别设置
    <dubbo:provider interface="com.foo.BarService" token="true" />
  • 路由规则
    分为条件路由规则和脚本路由规则,并且支持可扩展
  • 配置规则
    向注册中心写入动态配置覆盖规则
  • 服务降级
    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 表示消费方对该服务的方法调用都直接返回 null 值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。
还可以改为 mock=fail:return+null 表示消费方对该服务的方法调用在失败后,再返回 null 值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。

  • 优雅停机
    Dubbo 是通过 JDK 的 ShutdownHook 来完成优雅停机的
    设置优雅停机超时时间,缺省超时时间是 10 秒,如果超时则强制关闭
    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" />
  • 服务容器
  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对象,并且调用ReferenceConfig.get方法启动ReferenceConfig
XxxService xxxService = cache.get(reference);
// 注意! Cache会持有ReferenceConfig,不要在外部再调用ReferenceConfig的destroy方法,导致Cache内的ReferenceConfig失效!
// 使用xxxService对象
xxxService.sayHello();
<dubbo:application ...>
    <dubbo:parameter key="dump.directory" value="/tmp" />
</dubbo:application>

默认策略:
导出路径,user.home标识的用户主目录
导出间隔,最短间隔允许每隔10分钟导出一次

  • 序列化
    启用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. 将服务接口,服务模型,服务异常等均放在 API 包中,分包原则:重用发布等价原则(REP),共同重用原则(CRP)
  2. 服务接口尽可能大粒度,每个服务方法应代表一个功能,而不是某功能的一个步骤,否则将面临分布式事务问题,Dubbo 暂未提供分布式事务支持
  3. 不建议使用过于抽象的通用接口,如:Map query(Map),这样的接口没有明确语义,会给后期维护带来不便。
  4. 每个接口都应定义版本号,为后续不兼容升级提供可能,如: <dubbo:service interface="com.xxx.XxxService" version="1.0" />
  5. 服务接口增加方法,或服务模型增加字段,可向后兼容,删除方法或删除字段,将不兼容,枚举类型新增字段也不兼容,需通过变更版本号升级。详细参见 服务协议
  6. 如果是完备集,可以用 Enum,比如:ENABLE, DISABLE。如果是业务种类,以后明显会有类型增加,不建议用 Enum,可以用String 代替;注意升级的顺序.
  7. 服务参数及返回值建议使用 POJO 对象,即通过 setter, getter 方法表示属性的对象
  8. 建议使用异常汇报错误,而不是返回错误码,异常信息能携带更多信息,以及语义更友好。
    如果担心性能问题,在必要时,可以通过 override 掉异常类的 fillInStackTrace()方法为空方法,使其不拷贝栈信息。
  9. 不要只是因为是 Dubbo 调用,而把调用 try...catch 起来。try...catch 应该加上合适的回滚边界上。
    对于输入参数的校验逻辑在 Provider 端要有。如有性能上的考虑,服务实现者可以考虑在 API 包上加上服务 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” />
    这个文件会缓存注册中心的列表和服务提供者列表。有了这项配置后,当应用重启过程中,Dubbo 注册中心不可用时则应用会从这个缓存文件读取服务提供者列表的信息,进一步保证应用可靠性。
  4. 监控配置
  5. 不要使用 dubbo.properties 文件配置,推荐使用对应 XML 配置

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,100评论 18 139
  • 0 准备 安装注册中心:Zookeeper、Dubbox自带的dubbo-registry-simple;安装Du...
    七寸知架构阅读 13,905评论 0 88
  • Dubbo是什么 Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式...
    Coselding阅读 17,043评论 3 196
  • 没有买肉经验的我去市场买肉,市场里有二十多家卖肉的,转了一圈,看着肉都一样,不知道哪家的肉好,更重要的是不...
    鱼翔浅底韬光养晦阅读 282评论 0 1
  • 住在成华区的时候,是电梯房五楼。那时候大门的门禁是虚设的,不用门禁卡也能推开,但是必须手扶,有一个关门的力。 有一...
    早安十二阅读 70评论 0 0