Dubbo快速入门样例

主要按照Apache Dubbo主页上的demo进行编写,涉及到了具体操作和一些问题。

官方环境要求(Maven其实可选):

  • JDK: version 6 or higher

  • Maven: version 3 or higher

基于现在的使用习惯,具体实验使用idea+gradle(4.0)来构建demo

使用IntelliJ IDEA 新建项目(New Project),选择Gradle


定义自己项目的GroupId,ArtifactId,Version(GAV三元组),和maven的GAV三元组概念是一样的。

剩下的新建项目页面不再赘述,一般采用默认即可。

新建完以后等一会,IDEA会进行一些gradle初始化的操作。初始化完成后项目的目录结构为标准的gradle项目目录结构。

首先在build.gradle脚本中添加dubbo的依赖,和maven类似。

在这里贴一下最终版的项目根目录下的build.gradle。里面用到了shadowJar这个gradle的插件,会自动识别的,不需要手动安装。shadowJar是为了将开发的类连同依赖一起打包成一个Jar包(FatJar),方便部署或执行。shadowJar中的配置项是为了解决一些Bug,这个放在后面说。

group'com.miexample'
version'1.0-SNAPSHOT'

buildscript{
        repositories{
                jcenter()
        }
        dependencies{
                classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.4'
        }
}

allprojects{
        apply plugin : 'com.github.johnrengelman.shadow'
        apply plugin : 'java'

        sourceCompatibility=1.8
        
        repositories{
            mavenCentral()
        }
        
        dependencies{
            compile "com.alibaba:dubbo:2.6.1"
            testCompile group: 'junit', name:' junit', version: '4.12'
        }
        
        shadowJar{
                transform(com.github.jengelman.gradle.plugins.shadow.transformers
                    .AppendingTransformer){
                        resource='META-INF/spring.schemas'
                }
                transform(com.github.jengelman.gradle.plugins.shadow.transformers
                    .AppendingTransformer){
                        resource='META-INF/spring.handlers'
                }
                transform(com.github.jengelman.gradle.plugins.shadow.transformers
                    .AppendingTransformer){
                        resource='META-INF/spring.factories'
                }
        }
}

官网建议分成RPC接口,服务提供者(Provider),服务调用者(Consumer)这些不同模块,这样符合分成单个服务的开发情景,Provider和Consumer可以共用公共的接口模块。

使用IDEA 的New -> Module就可以自动帮组创建子模块,本实验过程中创建的子模块也是Gradle模块,既符合IDEA本身管理模块特点也符合Gradle的模块架构。

创建了三个模块 demo-common, demo-provider和demo-consumer。

在子模块demo-consumer的build.gradle中增加如下内容(注意主类的包名根据自己的项目目录进行更改)

dependencies{
        compile project(":demo-common")
}

processResources{
        exclude "**"
}

shadowJar{
        from('src/main/resources'){
                into("META-INF/")
        }
        manifest{
                attributes "Main-Class":"com.miexample.dubbo.consumer.Consumer"
        }
}

在子模块demo-provider的build.gradle中增加如下内容(注意主类的包名根据自己的项目目录进行更改)

dependencies{
        compile project(":demo-common")
}

processResources{
        exclude"**"
}

shadowJar{
        from('src/main/resources'){
                into("META-INF/")
        }
        manifest{
                attributes "Main-Class":"com.miexample.dubbo.provider.Provider"
        }
}

在子模块的build.gradle中定义了打包的jar的主类,并且将资源文件统一打包到META-INF目录中。

接下来就看定义的接口类和实现类吧!

demo-common模块中定义接口:
DemoService.java 核心部分(除去包名,导入等语句):

Public interface DemoService{
        String sayHello(Stringname);
}

demo-provider模块中定义服务实现并定义启动类及相关配置文件:

DemoServiceImpl.java核心部分:

public class DemoServiceImpl implements DemoService {
    @Override
    public String sayHello(String name) {
        return "Hello " + name;
    }
}

Provider.java核心部分:

public class Provider {
    public static void main(String[] args) throws Exception {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                new String[] {"META-INF/spring/dubbo-demo-provider.xml"});
        context.start();
        // press any key to exit
        System.in.read();
    }
}

dubbo-demo-provider.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/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
    <dubbo:application name="demo-provider"/>
    <dubbo:registry address="multicast://224.5.6.7:1234"/>
    <dubbo:protocol name="dubbo" port="20880"/>
    <dubbo:service interface="com.miexample.dubbo.common.DemoService" ref="demoService"/>
    <bean id="demoService" class="com.miexample.dubbo.provider.DemoServiceImpl"/>
</beans>

demo-consumer模块中定义服务调用者:


Consumer.java核心部分:

public class Consumer {
    public static void main(String[] args) throws Exception {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                new String[]{"META-INF/spring/dubbo-demo-consumer.xml"});
        context.start();
        // obtain proxy object for remote invocation
        DemoService demoService = (DemoService) context.getBean("demoService");
        // execute remote invocation
        String hello = demoService.sayHello("world");
        // show the result
        System.out.println(hello);
    }
}

dubbo-demo-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/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
    <dubbo:application name="demo-consumer"/>
    <dubbo:registry address="multicast://224.5.6.7:1234"/>
    <dubbo:reference id="demoService" interface="com.miexample.dubbo.common.DemoService"/>
</beans>

接下来就是build了,在IDEA的右侧可以方便的使用gradle:

双击相应的task就可以执行,双击shadowJar来进行统一打包。这里出现了一个问题,因为打好的包中META-INF下的spring.schemas同时出现在dubbo依赖包和sping依赖包中,打包过程会导致文件覆盖(这也是依赖冲突的一种情况),虽然一般不会用什么问题,但是会影响xml文件中的的文件校验,xml引用的阿里巴巴地址已经失效,有可能出现校验失败的问题。为了解决这个冲突,利用了shadow插件的合并文件的功能,对应了在文章前面项目根目录下的build.gradle中的配置。

build完了就可以在每个模块的build/libs/下找到打包好的jar,可以直接运行。先运行provider的包,然后运行consumer的包。

运行过程中的问题:

运行过程中发现provider运行正常,但是consumer报错,错误日志如下:


这是一个常见错误,Consumer在找不到Provider时都会报这个错误。

经过改变网络环境和跟踪源码最后发现是由于在同一台机器上运行provider和consumer并且采用组播的registry,并且有虚拟网卡会导致此问题(这种实验方式和网络环境在写demo时会碰到)。

根本原因是源码中会判断发送给consumer的服务消息是采用单播还是组播,因为虚拟网卡对ip地址的影响导致判断逻辑出错,误认为consumer可以接收到单播,但其实consumer在收到单播消息之前provider自己就把这个消息给抢着处理了(因为provider和consumer在同一台机器上,相当于provider自发自收),导致consumer无法获取服务消息。此问题在linux系统上实验时又无法复现,因为linux和windows的接口对待是否回环是不同的,linux下的consumer可以在provider之先获取到单播消息。以下是源码判断逻辑

解决方式有多种:

1、禁用虚拟网卡。

2、在两台机器上分别部署

3、采用其它registry

4、将服务提供者的spring配置文件中改为(注意url后面的参数配置)

<dubbo:registry address="multicast://224.5.6.7:1234?unicast=false"/>

第四个解决方式在官方文档上有提到,但是经测试2.6.1和2.6.2版本的dubbo配置了以后还是有问题,经查证发现解析URL参数时会将unicast丢失,应该是个bug。

使用zookeeper当作registry也可能会遇到多IP的问题,参考https://dubbo.gitbooks.io/dubbo-user-book/content/demos/hostname-binding.html进行绑定provider的IP配置。

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

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,039评论 25 707
  • 1、准备 在分析探索Dubbo架构原理之前,我们需要准备一下环境,用于后面我们来分析dubbo的架构。 1.1 Z...
    墨渊丶阅读 2,601评论 1 20
  • Dubbo是什么 Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式...
    Coselding阅读 17,201评论 3 196
  • 我是你身边那个爱闹的小孩 长大了 是否就可以不用再爱你了 我不懂大人的相对无言 爱是一种怎样的成熟体验 你说过我只...
    洛水无月阅读 286评论 0 0
  • 环境 Mac 10.12 搭建DDS失败,安装上之后,网页打开不开 方案 live555 Media Server...
    ashura_阅读 4,087评论 0 1