1. 程式人生 > >Dubbo 原始碼分析系列之一環境搭建

Dubbo 原始碼分析系列之一環境搭建

環境搭建的步驟有哪些

  1. 依賴外部的環境
  2. 使用的開發工具
  3. 原始碼的拉取
  4. 結構大致介紹

1 依賴的外部環境

  • 安裝JDK
  • 安裝Git
  • 安裝maven

這邊我們就不介紹怎麼安裝這些外部環境了,大家自行從安裝這些外部環境哈

2 使用的外部工具

  • 編輯器使用 IntelliJ IDEA (簡單好用,快捷鍵豐富)
  • GitHub Desktop GitHub的客戶端軟體,用起來真順手

3 原始碼的拉取

原始碼的話我們上GitHub 上面直接拉取dubbo的原始碼即可, Dubbo 然後我們 Fork出一個屬於我們自己的倉庫,之後我們就可以在我們GitHub的倉庫中看到這個專案了。然後我們將這個專案down到本地進行除錯

具體Git操作不詳細介紹,下面貼出幾個比較好的供大家參考

https://blog.csdn.net/qq_32040767/article/details/77096761

https://blog.csdn.net/menggudaoke/article/details/77744541

https://juejin.im/entry/5a5f3b286fb9a01c9064e83b

https://www.cnblogs.com/MrJun/p/3351478.html

這裡我們為什麼使用Fork 而不是Star,這是因為star的專案你不是Pull Request 到源專案的,而Fork 是可以的。想想一下要是你在看原始碼的過程中發現了bug。然後提交給他們並稽核這是一件多酷的事情

4 Dubbo的大致介紹

下面的這個 Dubbo 官網上最為經典的介紹,一張圖就將整個Dubbo 過程大致的介紹的差不多。

什麼是Dubbo?

一個分散式服務治理框架

Dubbo的作用是什麼?

作用是解決下面的問題

  • 單一應用架構

  • 垂直應用架構

  • 分散式服務架構

  • 流動計算架構

節點角色說明

節點角色說明
Provider 暴露服務的服務提供方
Consumer 呼叫遠端服務的服務消費方
Registry 服務註冊與發現的註冊中心
Monitor 統計服務的呼叫次數和呼叫時間的監控中心
Container 服務執行容器

呼叫關係說明

  1. 服務容器負責啟動,載入,執行服務提供者。

  2. 服務容器負責啟動,載入,執行服務提供者。
  3. 服務提供者在啟動時,向註冊中心註冊自己提供的服務。
  4. 服務消費者在啟動時,向註冊中心訂閱自己所需的服務。
  5. 註冊中心返回服務提供者地址列表給消費者,如果有變更,註冊中心將基於長連線推送變更資料給消費者。
  6. 服務消費者,從提供者地址列表中,基於軟負載均衡演算法,選一臺提供者進行呼叫,如果呼叫失敗,再選另一臺呼叫。
  7. 服務消費者和提供者,在記憶體中累計呼叫次數和呼叫時間,定時每分鐘傳送一次統計資料到監控中心。

詳細介紹下 Registry Provider Consumer

因為這三者是整個Dubbo 呼叫過程的鏈路核心

talk is cheap show me the code

光說不行,咱們通過看下專案中的原始碼來看下dubbo整個結構

dubbo提供了 一個demo專案供大家測試除錯 整個demo已經在你down的dubbo的專案中了

開啟我們的dubbo專案,我們會看到這樣的一個子專案

這裡就是那個demo子專案 就是我們可以直接執行測試的專案

將整個測試專案展開,我們會看見這幾個檔案

我們先進入consumer專案中的 Consumer類中,執行這個類。在這裡是一個main函式,我們直接執行就ok了

之後我們再啟動Provider 類。這樣的話,我們就啟動了一對消費者和生產類。這樣的話,最簡單的dubbo程式就 啟動了。

下面我們根據這個最簡單的類來分析下

package org.apache.dubbo.demo;
// 服務對外暴露介面
public interface DemoService {

    String sayHello(String name);

}
package org.apache.dubbo.demo.consumer;

import org.apache.dubbo.demo.DemoService;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Consumer {

    /**
     * To get ipv6 address to work, add
     * System.setProperty("java.net.preferIPv6Addresses", "true");
     * before running your application.
     */
    public static void main(String[] args) {
        //載入配置的xml檔案
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-consumer.xml"});
        context.start();
        //從這個上下文bean中獲取類
        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();
            }
        }
    }
}

消費者的測試demo,迴圈呼叫方法

<?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://dubbo.apache.org/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://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/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="multicast://224.5.6.7:1234"/>

    <!-- 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="org.apache.dubbo.demo.DemoService"/>

</beans>

我們通過配置檔案xml來進行服務的發現和啟用,還有對註冊中心的配置

下面介紹下服務的提供者Provider

package org.apache.dubbo.demo.provider;

import org.apache.dubbo.demo.DemoService;
import org.apache.dubbo.rpc.RpcContext;

import java.text.SimpleDateFormat;
import java.util.Date;

public class DemoServiceImpl implements DemoService {

    @Override
    public String sayHello(String name) {
        //對外暴露的服務內部實現類
        System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] Hello " + name + ", request from consumer: " + RpcContext.getContext().getRemoteAddress());
        return "Hello " + name + ", response from provider: " + RpcContext.getContext().getLocalAddress();
    }

}
package org.apache.dubbo.demo.provider;

import org.springframework.context.support.ClassPathXmlApplicationContext;

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 {
        //載入xml配置
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-provider.xml"});
        context.start();
        System.in.read(); // press any key to exit
    }
}
<?xml version="1.0" encoding="UTF-8"?>

    <!-- provider's application name, used for tracing dependency relationship -->
    <!-- 提供一個應用名稱,用於查詢依賴的關係-->
    <dubbo:application name="demo-provider"/>

    <!-- use multicast registry center to export service -->
    <!-- 使用組播來進行服務的暴露-->
    <dubbo:registry address="multicast://224.5.6.7:1234"/>

    <!-- use dubbo protocol to export service on port 20880 -->
    <!-- 使用dubbo協議對外暴露時的埠-->
    <dubbo:protocol name="dubbo" port="20880"/>

    <!-- service implementation, as same as regular local bean -->
    <!-- 業務實現類,對外暴露類的內部實現-->
    <bean id="demoService" class="org.apache.dubbo.demo.provider.DemoServiceImpl"/>

    <!-- declare the service interface to be exported -->
    <!-- 對外暴露服務的介面 -->
    <dubbo:service interface="org.apache.dubbo.demo.DemoService" ref="demoService"/>

</beans>

部落格園展示效果不好,可以移步到GitHub 部落格上