Dubbo源碼-從HelloWorld開始


Dubbo簡介

Dubbo,相信做后端的同學應該都用過,或者有所耳聞。沒錯,我就是那個有所耳聞中的一員。

公司在好幾年前實現了一套自己的RPC框架,所以也就沒有機會使用市面上琳琅滿目的RPC框架產品。

之所以想好好看看Dubbo,有以下幾個原因

  • 公司內部的框架一直在做迭代更新,配置越來越簡潔,性能越來越好。但是作為使用者,它就像一個黑盒子,我們無法感知其內部的改動以及實現的原理

  • 現在使用的框架,因為使用了thrift,讓平時的開發顯得格外的蹩腳,常常在各種model的轉換中迷失自我,耗盡了耐心

  • 阿里團隊從去年開始重新維護Dubbo,並在春節之際進入Apache孵化器,在開源的道路上又猛跨一大步,其背后定然有我們值得學習借鑒的地方,更何況有阿里技術的背書

  • 開源項目是很好的學習素材,希望借助學習Dubbo代碼,了解序列化、分布式、網絡通訊等方面的知識

Dubbo是Alibaba開源的分布式服務框架,它最大的特點是按照分層的方式來架構,使用這種方式可以使各個層之間解耦合(或者最大限度地松耦合)。

GitHub:https://github.com/apache/incubator-dubbo

官網:http://dubbo.apache.org/

中文用戶手冊:http://dubbo.io/books/dubbo-user-book/

HelloWorld之前的兩個小問題

1.沒有Dubbo之前,我們是什么樣的工作方式

Dubbo代表的是一類RPC框架,類似的產品還有鼎鼎大名的gRPC。

沒有Dubbo之前是什么樣的,可以回想下我們學生時代做的項目。

一台電腦既是服務器又是客戶端,估計當時也沒有想過我調用的這個接口是哪台電腦上,我是不是可以多部署幾台電腦,怎么樣充分利用這幾台電腦好讓調用的效率更高。

因為即使想了,也搞不了,因為沒錢!

即使我們在自己的PC上把項目做好了,需要部署到服務器上,那么我們只要記住那台服務器的IP,使用Socket通訊,就很簡單的實現了服務的調用和通訊了。

2.Dubbo有什么用

接着學生時代的項目說,那時候我們做個圖書管理系統,學籍管理系統,其訪問量和並發量一般不會太高,准確說,是非常低。

但是如果還是一個服務端,大量的用戶請求,達到高並發的場景,那么問題就來了,一台機子顯然承受不住,這時候需要考慮分布式。

Dubbo的產生於微服務聯系緊密,我們一方面想着借助微服務的思想,實現各個服務或者模塊之間的解耦。那么我們另一方面就不能忽視服務之間的通訊,這時候Dubbo一類的RPC框架就應運而生。

我們需要考慮擴展性,比如為了防止訪問過載,服務所在機器需要進行水平擴展,同時也要考慮不斷增加的服務調用方。

我們需要考慮負載均衡,怎么樣才能將服務集群的威力發揮到最大。

我們需要考慮如何自動的注冊服務以及更新服務,如果做好異常情況下,比如注冊中心宕機時,服務方和調用方之間的服務調用。

如此種種,都是催生Dubbo的重要因素。

HelloWorld的准備工作

  • 下載安裝zookeeper,在命令行執行brew install zookeeper

相應的啟動zk和關閉zk服務的命令分別是zkServer startzkServer stop

運行HelloWorld

導入Dubbo項目並且完成編譯后,可以看到Dubbo項目的目錄結構如下

今天要介紹的是dubbo-demo,該子模塊包括

  • dubbo-demo-api(提取出公共接口)

  • dubbo-demo-consumer(服務調用方)

  • dubbo-demo-provider(服務提供方)

dubbo-demo-api

該模塊最核心的類就是DemoService接口,該接口只有一個方法sayHello


package com.alibaba.dubbo.demo;

public interface DemoService {

    String sayHello(String name);

}

這個接口是聯系調用方和提供方的紐帶。

dubbo-demo-consumer

該模塊核心的類為Consumer,主要是一個main函數


public class Consumer {

    public static void main(String[] args) {
        //Prevent to get IPV6 address,this way only work in debug mode
        //But you can pass use -Djava.net.preferIPv4Stack=true,then it work well whether in debug mode or not
        System.setProperty("java.net.preferIPv4Stack", "true");
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-consumer.xml"});
        context.start();
        DemoService demoService = (DemoService) context.getBean("demoService"); // get remote service proxy

        while (true) {
            try {
                Thread.sleep(1000);
                String hello = demoService.sayHello("world"); // call remote method
                System.out.println(hello); // get result

            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }


        }

    }
}

其主要功能是加載配置文件,用於尋找服務提供方所在的位置,拿到DemoService接口的實現類DemoServiceImpl,並調用其方法實現sayHello

dubbo-demo-provider

該模塊包含了DemoService的實現類DemoServiceImpl,同時包含一個服務啟動類Provider


public class Provider {

    public static void main(String[] args) throws Exception {
        //Prevent to get IPV6 address,this way only work in debug mode
        //But you can pass use -Djava.net.preferIPv4Stack=true,then it work well whether in debug mode or not
        System.setProperty("java.net.preferIPv4Stack", "true");
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-provider.xml"});
        context.start();

        System.in.read(); // press any key to exit
    }

}

啟動注冊中心

因為調用方和服務提供方需要靠注冊中心來聯系,提供方將自己的服務登記到注冊中心,調用方需要拉取可用的服務提供方的位置信息,比較常見的關系描述如下圖所示

調用關系說明

  • 服務容器負責啟動,加載,運行服務提供者。

  • 服務提供者在啟動時,向注冊中心注冊自己提供的服務。

  • 服務消費者在啟動時,向注冊中心訂閱自己所需的服務。

  • 注冊中心返回服務提供者地址列表給消費者,如果有變更,注冊中心將基於長連接推送變更數據給消費者。

  • 服務消費者,從提供者地址列表中,基於軟負載均衡算法,選一台提供者進行調用,如果調用失敗,再選另一台調用。

  • 服務消費者和提供者,在內存中累計調用次數和調用時間,定時每分鍾發送一次統計數據到監控中心。

鑒於Dubbo源碼中,配置文件中的默認配置是multicast,但是我在運行的時候總是出現can't assign address的情況,所以改用zookeeper。

相應修改如下,在dubbo-demo-provider項目中,將dubbo-demo-provider.xml修改為


<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License.  You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
       http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <!-- provider's application name, used for tracing dependency relationship -->
    <dubbo:application name="demo-provider"/>

    <!-- use multicast registry center to export service -->
    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>

    <!-- use dubbo protocol to export service on port 20880 -->
    <dubbo:protocol name="dubbo" port="20880"/>

    <!-- service implementation, as same as regular local bean -->
    <bean id="demoService" class="com.alibaba.dubbo.demo.provider.DemoServiceImpl"/>

    <!-- declare the service interface to be exported -->
    <dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService"/>

</beans>

將dubbo-demo-consumer項目中的dubbo-demo-consumer.xml修改為


<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License.  You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
       http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <!-- consumer's application name, used for tracing dependency relationship (not a matching criterion),
    don't set it same as provider -->
    <dubbo:application name="demo-consumer"/>

    <!-- use multicast registry center to discover service -->
    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>

    <!-- generate proxy for the remote service, then demoService can be used in the same way as the
    local regular interface -->
    <dubbo:reference id="demoService" check="false" interface="com.alibaba.dubbo.demo.DemoService"/>

</beans>

同時在命令行輸入zkServer start啟動zk

分別啟動Proiver和Consumer

運行Provider類,將自己的服務接口對外開放

運行Consumer類,尋找服務提供方,並調用其接口實現

至此,對於Dubbo有了一個初步的認識並通過dubbo-demo項目了解Dubbo的運作模式。

網上找了一份PDF版的源碼閱讀心得,如果有需要,下方留下你的郵箱

如果您覺得閱讀本文對您有幫助,請點一下“推薦”按鈕,您的“推薦”將是我最大的寫作動力!如果您想持續關注我的文章,請掃描二維碼,關注JackieZheng的微信公眾號,我會將我的文章推送給您,並和您一起分享我日常閱讀過的優質文章。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM