Hello World及浅析dubbo通信方式

[TOC]

代码

import java.util.List;

public abstract interface DemoService {
    
    public abstract String build(String name) throws Exception;

    String sayHello(String name);

    List getUsers();

}
import java.util.ArrayList;
import java.util.List;

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

    public List getUsers() {
        List list = new ArrayList();
        User u1 = new User();
        u1.setName("jack");
        u1.setAge(20);
        u1.setSex("男");

        list.add(u1);
        return list;
    }

    public String build(String name) throws Exception {
        return null;
    }
}

import java.io.Serializable;

//必须实现Serializable接口
public class User implements Serializable {
    private static final long serialVersionUID = -2814022769568306965L;
    private String name;
    private Integer age;
    private String sex;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "User{" + "name='" + name + '\'' + ", age=" + age + ", sex='" + sex + '\'' + '}';
    }
}

dubbo-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 = "hello-world-app-provider" />

    <!--zookeeper注册中心 -->
    <dubbo:registry protocol="zookeeper" address="vimda.vimda:2181" />

    <!-- 用dubbo协议在20880端口暴露服务 -->
    <dubbo:protocol name="dubbo" port="20880" />

    <!-- 具体的实现bean -->
    <bean id="demoProvideService" class="dubboxTs.DemoServiceImpl" />

    <!-- 暴露的服务接口 -->
    <dubbo:service interface="dubboxTs.DemoService" ref="demoProvideService"/>
</beans>

bean指定id,此id可用于其他bean或者dubbo:service引用;同时指明实现类dubboxTs.DemoServiceImpl
dubbo:service interface指定服务接口类,ref引用上述已定义的服务bean ID。
dubbo:registry 指明通信协议和zookeeper地址。

dubbo-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="hello-world-app-consumer"/>
        
    <!-- 使用zookeeper注册中心暴露服务地址 -->
    <dubbo:registry protocol="zookeeper" address="vimda.vimda:2181"/>
    
    <!-- 增加引用远程服务配置  -->
    <dubbo:reference id="demoConsumeService" interface="dubboxTs.DemoService"/>

</beans>

consumer先使用<
dubbo:registry>引用zookeeper。
其次使用dubbo:reference 引用已注册在zookeeper中心的provide(demoConsumeService),并指出demoConsumeService的实现接口。

log4j.properties

log4j.rootLogger=debug,A1,DRF

# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender
# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=[%-5p][%d{yyyyMMdd HH:mm:ss,SSS}] [THREAD ID=%t] [%C{1}:%L]  %m%n

#DRF
log4j.appender.DRF=org.apache.log4j.DailyRollingFileAppender
log4j.appender.DRF.Threshold=${log4j.leve}
log4j.appender.DRF.DatePattern='.'yyyy-MM-dd
log4j.appender.DRF.File=./log/monitor.log
#log4j.appender.DRF.File=../log/monitor.log
log4j.appender.DRF.Append=true
log4j.appender.DRF.layout=org.apache.log4j.PatternLayout
log4j.appender.DRF.layout.ConversionPattern=[%-5p][%d{yyyyMMdd HH:mm:ss,SSS}] [THREAD ID=%t] [%C{1}:%L] %m%n

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import dubboxTs.DemoService;
public class ConsumerTs {

    @Test
    public void startConsumer() {
        try {
            String configLocation = "dubbo-consumer.xml";
            ApplicationContext context = new ClassPathXmlApplicationContext(configLocation);
            String[] names = context.getBeanDefinitionNames();
            System.out.print("Beans:");
            for (String string : names) {
                System.out.print(string);
                System.out.print(",");
            }
            System.out.println();

            DemoService ds = (DemoService) context.getBean("demoConsumeService");
            System.out.println(ds.sayHello("hehe"));
            System.out.println(ds.getUsers());

            Thread.sleep(Long.MAX_VALUE);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}


import java.io.IOException;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ProviderTs {

    
    @Test
    public void startProvider(){
        String configLocation = "dubbo-provider.xml";
        ApplicationContext context = new ClassPathXmlApplicationContext(configLocation);
        String[] names = context.getBeanDefinitionNames();
        System.out.print("Beans:");
        System.out.println();
        
        for (String string : names){
            System.out.print(string + ";");
        }
        
        try {
            System.in.read();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

先启动ProviderTs,后启动ConsumerTs
provider控制台

property source. Returning [null]
Beans:
hello-world-app-provider;com.alibaba.dubbo.config.RegistryConfig;dubbo;demoProvideService;dubboxTs.DemoService;

consumer控制台

property source. Returning [null]
Beans:
hello-world-app-provider;com.alibaba.dubbo.config.RegistryConfig;dubbo;demoProvideService;dubboxTs.DemoService;[DEBUG][20170115 00:41:36,583]

讲解


流程如下图所示:

1.jpg

节点角色说明:
Provider: 暴露服务的服务提供方。
Consumer: 调用远程服务的服务消费方。
Registry: 服务注册与发现的注册中心。
Monitor: 统计服务的调用次调和调用时间的监控中心。
Container: 服务运行容器。

调用关系说明:

  1. 服务容器负责启动,加载,运行服务提供者。
  2. 服务提供者在启动时,向注册中心注册自己提供的服务。
  3. 服务消费者在启动时,向注册中心订阅自己所需的服务。
  4. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
  5. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
  6. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

窥看dubbo调用过程

问题

  1. consumer如何找到消费者

  2. consumer如何调用消费者的方法

  3. provider如何接受消费者的请求和参数,并如何调用对应方法

  4. provider如何返回调用结果

首次调用
首先在ReferenceConfig的createProxy()等到invoker

interface DemoService -> zookeeper://192.168.91.25:2181/com.alibaba.dubbo.registry.RegistryService?anyhost=true&application=hello-world-app-consumer&check=false&dubbo=2.5.3&interface=DemoService&methods=sayHello,build,getUsers&pid=13388&side=consumer&timestamp=1489659254215

我的zookeeper IP 端口为192.168.91.25:2181.
如下图,未执行ds.sayHello("hehe")前,消费者仍未知 提供者的具体"位置".

2.png

在 MockClusterInvoker处, result = this.invoker.invoke(invocation);进入AbstractClusterInvoker

public Result invoke(Invocation invocation) throws RpcException {Result result = null;String value = directory.getUrl().getMethodParameter(invocation.getMethodName(), Constants.MOCK_KEY, Boolean.FALSE.toString()).trim();if (value.length() == 0 || value.equalsIgnoreCase("false")){//no mock result = this.invoker.invoke(invocation);} else if (value.startsWith("force")) {if (logger.isWarnEnabled()) {logger.info("force-mock: " + invocation.getMethodName() + " force-mock enabled , url : " + directory.getUrl());}//force:direct mock result = doMockInvoke(invocation, null);} else {//fail-mock try {result = this.invoker.invoke(invocation);}catch (RpcException e) {if (e.isBiz()) {throw e;} else {if (logger.isWarnEnabled()) {logger.info("fail-mock: " + invocation.getMethodName() + " fail-mock enabled , url : " + directory.getUrl(), e);}result = doMockInvoke(invocation, e);}}}return result;}

在AbstractClusterInvoker 226行处获得invokers的ip,端口,服务.


public Result invoke(final Invocation invocation) throws RpcException {

        checkWheatherDestoried();

        LoadBalance loadbalance;
        
        List<Invoker<T>> invokers = list(invocation);
        if (invokers != null && invokers.size() > 0) {
            loadbalance = ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(invokers.get(0).getUrl()
                    .getMethodParameter(invocation.getMethodName(),Constants.LOADBALANCE_KEY, Constants.DEFAULT_LOADBALANCE));
        } else {
            loadbalance = ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(Constants.DEFAULT_LOADBALANCE);
        }
        RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
        return doInvoke(invocation, invokers, loadbalance);
    }

Paste_Image.png

227行调用远程方法并返回调用结果.

Paste_Image.png

provider方面

Paste_Image.png

参考:

http://blog.csdn.net/a258831020/article/details/48011777


希望你能指出文章写得不好之处,感激不尽.

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

推荐阅读更多精彩内容

  • Dubbo是什么 Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式...
    Coselding阅读 17,168评论 3 196
  • 0 准备 安装注册中心:Zookeeper、Dubbox自带的dubbo-registry-simple;安装Du...
    七寸知架构阅读 13,970评论 0 88
  • 先看官网两张图【引用来自官网】:image.png 官网说明: 1.首先 ReferenceConfig 类的 i...
    致虑阅读 1,021评论 0 2
  • 1.背景 想象下这么个场景: 有个做生活服务的APP,主要提供一些生活化的咨询信息,比如天气、新闻、个人三金账单、...
    点融黑帮阅读 3,868评论 0 33
  • 走过半生,经历过挫折也感受过惊喜,渐渐读懂了人生、读懂了朋友、读懂了健康……一路走来仍然觉得自己是如此幸运,仍然被...
    颜小可_047a阅读 184评论 0 0