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;

//必須實現(xiàn)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協(xié)議在20880端口暴露服務 -->
    <dubbo:protocol name="dubbo" port="20880" />

    <!-- 具體的實現(xiàn)bean -->
    <bean id="demoProvideService" class="dubboxTs.DemoServiceImpl" />

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

bean指定id塞栅,此id可用于其他bean或者dubbo:service引用;同時指明實現(xiàn)類dubboxTs.DemoServiceImpl 启泣。
dubbo:service interface指定服務接口類,ref引用上述已定義的服務bean ID。
dubbo:registry 指明通信協(xié)議和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的實現(xiàn)接口烛亦。

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

節(jié)點角色說明:
Provider: 暴露服務的服務提供方。
Consumer: 調(diào)用遠程服務的服務消費方煤禽。
Registry: 服務注冊與發(fā)現(xiàn)的注冊中心铐达。
Monitor: 統(tǒng)計服務的調(diào)用次調(diào)和調(diào)用時間的監(jiān)控中心。
Container: 服務運行容器檬果。

調(diào)用關系說明:

  1. 服務容器負責啟動瓮孙,加載唐断,運行服務提供者。
  2. 服務提供者在啟動時杭抠,向注冊中心注冊自己提供的服務脸甘。
  3. 服務消費者在啟動時,向注冊中心訂閱自己所需的服務偏灿。
  4. 注冊中心返回服務提供者地址列表給消費者丹诀,如果有變更,注冊中心將基于長連接推送變更數(shù)據(jù)給消費者翁垂。
  5. 服務消費者铆遭,從提供者地址列表中,基于軟負載均衡算法沿猜,選一臺提供者進行調(diào)用枚荣,如果調(diào)用失敗,再選另一臺調(diào)用啼肩。
  6. 服務消費者和提供者橄妆,在內(nèi)存中累計調(diào)用次數(shù)和調(diào)用時間,定時每分鐘發(fā)送一次統(tǒng)計數(shù)據(jù)到監(jiān)控中心祈坠。

窺看dubbo調(diào)用過程

問題

  1. consumer如何找到消費者

  2. consumer如何調(diào)用消費者的方法

  3. provider如何接受消費者的請求和參數(shù),并如何調(diào)用對應方法

  4. provider如何返回調(diào)用結(jié)果

首次調(diào)用
首先在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.
如下圖,未執(zhí)行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行調(diào)用遠程方法并返回調(diào)用結(jié)果.

Paste_Image.png

provider方面

Paste_Image.png

參考:

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


希望你能指出文章寫得不好之處,感激不盡.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末害碾,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子颁虐,更是在濱河造成了極大的恐慌蛮原,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,919評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件另绩,死亡現(xiàn)場離奇詭異儒陨,居然都是意外死亡,警方通過查閱死者的電腦和手機笋籽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評論 3 392
  • 文/潘曉璐 我一進店門蹦漠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人车海,你說我怎么就攤上這事笛园。” “怎么了侍芝?”我有些...
    開封第一講書人閱讀 163,316評論 0 353
  • 文/不壞的土叔 我叫張陵研铆,是天一觀的道長。 經(jīng)常有香客問我州叠,道長棵红,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,294評論 1 292
  • 正文 為了忘掉前任咧栗,我火速辦了婚禮逆甜,結(jié)果婚禮上虱肄,老公的妹妹穿的比我還像新娘。我一直安慰自己交煞,他們只是感情好咏窿,可當我...
    茶點故事閱讀 67,318評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著素征,像睡著了一般集嵌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上稚茅,一...
    開封第一講書人閱讀 51,245評論 1 299
  • 那天纸淮,我揣著相機與錄音,去河邊找鬼亚享。 笑死,一個胖子當著我的面吹牛绘面,可吹牛的內(nèi)容都是我干的欺税。 我是一名探鬼主播,決...
    沈念sama閱讀 40,120評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼揭璃,長吁一口氣:“原來是場噩夢啊……” “哼晚凿!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起瘦馍,我...
    開封第一講書人閱讀 38,964評論 0 275
  • 序言:老撾萬榮一對情侶失蹤歼秽,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后情组,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體燥筷,經(jīng)...
    沈念sama閱讀 45,376評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,592評論 2 333
  • 正文 我和宋清朗相戀三年院崇,在試婚紗的時候發(fā)現(xiàn)自己被綠了肆氓。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,764評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡底瓣,死狀恐怖谢揪,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情捐凭,我是刑警寧澤拨扶,帶...
    沈念sama閱讀 35,460評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站茁肠,受9級特大地震影響患民,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜官套,卻給世界環(huán)境...
    茶點故事閱讀 41,070評論 3 327
  • 文/蒙蒙 一酒奶、第九天 我趴在偏房一處隱蔽的房頂上張望蚁孔。 院中可真熱鬧,春花似錦惋嚎、人聲如沸杠氢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鼻百。三九已至,卻和暖如春摆尝,著一層夾襖步出監(jiān)牢的瞬間温艇,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評論 1 269
  • 我被黑心中介騙來泰國打工堕汞, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留勺爱,地道東北人。 一個月前我還...
    沈念sama閱讀 47,819評論 2 370
  • 正文 我出身青樓讯检,卻偏偏與公主長得像琐鲁,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子人灼,可洞房花燭夜當晚...
    茶點故事閱讀 44,665評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Dubbo是什么 Dubbo是Alibaba開源的分布式服務框架围段,它最大的特點是按照分層的方式來架構(gòu),使用這種方式...
    Coselding閱讀 17,211評論 3 196
  • 0 準備 安裝注冊中心:Zookeeper投放、Dubbox自帶的dubbo-registry-simple奈泪;安裝Du...
    七寸知架構(gòu)閱讀 13,989評論 0 88
  • 先看官網(wǎng)兩張圖【引用來自官網(wǎng)】:image.png 官網(wǎng)說明: 1.首先 ReferenceConfig 類的 i...
    致慮閱讀 1,027評論 0 2
  • 1.背景 想象下這么個場景: 有個做生活服務的APP,主要提供一些生活化的咨詢信息灸芳,比如天氣涝桅、新聞、個人三金賬單耗绿、...
    點融黑幫閱讀 3,878評論 0 33
  • 走過半生苹支,經(jīng)歷過挫折也感受過驚喜,漸漸讀懂了人生误阻、讀懂了朋友债蜜、讀懂了健康……一路走來仍然覺得自己是如此幸運,仍然被...
    顏小可_047a閱讀 187評論 0 0