記錄尚硅谷對於dubbo框架學習

 

分佈式簡要說明

Dubbo是用於分佈式系統的框架所以我們要先了解什麼是分佈式
分佈式系統是若干獨立 計算機的集合,這些計算機對於用戶來說就像單個相關係統。

老式系統(單一應用架構)就是把一個系統,統一放到一個服務器當中然後每一個服務器上放一個系統,如果說要更新代碼的話,每一個服務器上的系統都要重新去部署十分的麻煩。

而分佈式系統就是將一個完整的系統拆分成多個不同的服務,然後在將每一個服務單獨的放到一個服務器當中。(三個臭皮匠賽過諸葛亮)

應用架構及發展演變

Dubbo和SpringCloud對比

發展演變

ORM
單一應用架構:一個項目裝到一個服務器當中,也可以運行多個服務器每一個服務器當中都裝一個項目。
缺點:1.如果要添加某一個功能的話就要把一個項目重新打包,在分別部署到每一個服務器當中去。2.如果後期項目越來越大的話單臺服務器跑一個項目壓力會很大的。會不利於維護,開發和程序的性能。

MVC
垂直應用架構:將應用切割成幾個互不相干的小應用,在將每個小應用獨立放到一個服務器上,如果哪一個應用的訪問數量多就多加幾臺服務器。

分佈式服務架構

RPC簡介

分佈式應用架構(遠程過程調用):當垂直應用越來越多,應用之間交互不可避免,將核心業務抽取出來,作爲獨立的服務,逐漸形成穩定的服務中心,使前端應用能更快速的響應多變的市場需求。

什麼叫RPC

  1. RPC [ Remote Procedure Call]是指遠程過程調用,是一種進程問通信方式,他是一種技術的思想,而不是規範。它允許程序調用另一個地址空間(通常是共享網絡的另一臺機器上)的過程或函數,而不用程序員顯式編碼這個遠程調用的細節。即程序員無論是調用本地的還是遠程的函數,本質上編寫的調用代碼基本相同。
  2. RPC(Remote Procedure Call)—遠程過程調用,它是一種通過網絡從遠程計算機程序上請求服務,而不需要了解底層網絡技術的協議。也就是說兩臺服務器A,B,一個應用部署在A服務器上,想要調用B服務器上應用提供的方法,由於不在一個內存空間,不能直接調用,需要通過網絡來表達調用的語義和傳達調用的數據。

RPC工作原理

  1. Client像調用本地服務似的調用遠程服務;
  2. Client stub接收到調用後,將方法、參數序列化
  3. 客戶端通過sockets將消息發送到服務端
  4. Server stub 收到消息後進行解碼(將消息對象反序列化)
  5. Server stub 根據解碼結果調用本地的服務
  6. 本地服務執行(對於服務端來說是本地執行)並將結果返回給Server stub
  7. Server stub將返回結果打包成消息(將結果消息對象序列化)
  8. 服務端通過sockets將消息發送到客戶端
  9. Client stub接收到結果消息,並進行解碼(將結果消息發序列化)
  10. 客戶端得到最終結果。

RPC 調用分以下兩種:
同步調用:客戶方等待調用執行完成並返回結果。
異步調用:客戶方調用後不用等待執行結果返回,但依然可以通過回調通知等方式獲取返回結果。若客戶方不關心調用返回結果,則變成單向異步調用,單向調用不用返回結果。

RPC步驟解析

RPC相關資料可訪問博客:
http://blog.csdn.net/smartbetter/article/details/100360835

SOA
流動計算架構:在分佈式應用架構的基礎上增加了一個調度、治理中心基於訪問壓力實時管理集羣容量、提高集羣的利用率,用於提高機器利用率的 資源調度和治理中心(SOA) 是關鍵 (不浪費計算機資源)

Dubbo核心概念

Dubbo官網: http://dubbo.apache.org/en-us/index.html

Dubbo 是一款高性能、輕量級的開源Java RPC框架,它提供了三大核心能力:面向接口的遠程方法調用,智能容錯和負載均衡,服務自動註冊和發現。分佈式系統是將一個系統拆分爲多個不同的服務

Dubbo特性一覽

dubbo設計架構


該圖來自Dubbo官網,描述了服務註冊中心、服務提供方、服務消費方、服務監控中心之間的調用關係。

服務提供者(Provider):暴露服務的服務提供方,服務提供者在啓動時,向註冊中心註冊自己提供的服務。
服務消費者(Consumer): 調用遠程服務的服務消費方,服務消費者在啓動時,向註冊中心訂閱自己所需的服務,服務消費者,從提供者地址列表中,基於軟負載均衡算法,選一臺提供者進行調用,如果調用失敗,再選另一臺調用。
註冊中心(Registry):註冊中心返回服務提供者地址列表給消費者,如果有變更,註冊中心將基於長連接推送變更數據給消費者。
監控中心(Monitor):服務消費者和提供者,在內存中累計調用次數和調用時間,定時每分鐘發送一次統計數據到監控中心。

Dubbo的特性

(1)服務註冊中心

  • 相比Hessian類RPC框架,Dubbo有自己的服務中心, 寫好的服務可以註冊到服務中心, 客戶端從服務中心尋找服務,然後再到相應的服務提供者機器獲取服務。通過服務中心可以實現集羣、負載均衡、高可用(容錯) 等重要功能。
  • 服務中心一般使用zookeeper實現,也有redis和其他一些方式。以使用zookeeper作爲服務中心爲例,服務提供者啓動後會在zookeeper的/dubbo節點下創建提供的服務節點,包含服務提供者ip、port等信息。服務提供者關閉時會從zookeeper中移除對應的服務。
  • 服務使用者會從註冊中心zookeeper中尋找服務,同一個服務可能會有多個提供者,Dubbo會幫我們找到合適的服務提供者,也就是針對服務提供者的負載均衡。

(2)負載均衡

  • 當同一個服務有多個提供者在提供服務時,客戶端如何正確的選擇提供者實                    現負載均衡呢?dubbo也給我們提供了幾種方案:
    • random 隨機選提供者,並可以給提供者設置權重
    • roundrobin 輪詢選擇提供者
    • leastactive 最少活躍調用數,相同活躍數的隨機,活躍數:指調用前後計數差。使慢的提供者收到更少請求,因爲越慢的提供者的調用前後計數差會越大。
    • consistenthash 一致性hash,相同參數的請求發到同一臺機器上。

(3)簡化測試,允許直連提供者
在開發階段爲了方便測試,通常系統客戶端能指定調用某個服務提供者,那麼可以在引用服務時加一個url參數去指定服務提供者。 配置如下:

 <dubbo:reference id="xxxService"interface="com.alibaba.xxx.XxxService"url="dubbo://localhost:20890"/>

(4)服務版本,服務分組
在Dubbo配置文件中可以通過制定版本實現連接制定提供者,也就是通過服務版本可以控制服務的不兼容升級;當同一個服務有多種實現時,可以使用服務分組進行區分。

dubbo環境搭建 ZooKeeper註冊中心

搭建zookeeper註冊中心環境

Dubbo官方文檔: http://dubbo.apache.org/en-us/docs/user/quick-start.html
在zookeeper官網下載zookeeper
http://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.4.14/

在bin文件下,啓動zkServer.cmd會有報錯,處理需要在condif文件中將zoo_sample.cfg文件複製一份,將名字改爲zoo.cfg。
在zookeeper的文件夾下創建data文件夾,打開zoo.cfg,修改datadir,將dataDir數據保存爲我們自定義的文件中(此步驟可省略)
在這裏插入圖片描述
配置完畢後,我們再次在conf下啓動zkServer.cmd,這次可以成功啓動
在這裏插入圖片描述
繼續運行zkCli.cmd,可以連接到zookeeper的服務器。
在這裏插入圖片描述
此時,我們zookeeper的註冊中心及環境以及搭建完畢。

zookeeper監控中心的配置

1、下載dubbo-admin

dubbo-admin下載地址 :https://github.com/apache/dubbo-admin/tree/master
在這裏插入圖片描述
2、解壓後進入目錄修改指定zookeeper地址
進入如下地址:dubbo-admin-master\dubbo-admin\src\main\resources\application.properties"
將zookeeper的監控中心的地址配置爲本地端口

#註冊中心的地址
dubbo.registry.address=zookeeper://127.0.0.1:2181

在這裏插入圖片描述
配置完畢後,我們在dubo-zookeeper\dubbo-admin-master\dubbo-admin文件夾下cmd打包測試下。

mvn clean package

 

在target文件中打包完成的jar包
cmd命令 java -jar dubbo-admin-0.0.1-SNAPSHOT.jar運行打包好的jar包
啓動成功後,可以看到一個7001的端口
在這裏插入圖片描述
此時我們的zookeeper的服務都爲啓動狀態,在瀏覽器中訪問 localhost:7001,訪問到註冊中心,輸入賬號密碼root。

此時,我們zookeeper監控中心的配置完成。注意,要訪問到監控中心,一定要啓動zookeeper註冊中心的啓動類

Dubbo環境搭建,創建提供者、消費者項目

基於以下圖實現服務 提供者、消費者
在這裏插入圖片描述

Dubbo服務提供消費者接口搭建

創建Maven項目=> user-service-provider  服務提供者
在這裏插入圖片描述在這裏插入圖片描述
UserAddress

public class UserAddress implements Serializable{
    private Integer id;
    private String userAddress; //用戶地址
    private String userId; //用戶id
    private String consignee; //收貨人
    private String phoneNum; //電話號碼
    private String isDefault; //是否爲默認地址    Y-是     N-否
    //get     set 
    //有參構造  無參構造
  }

UserService

//用戶服務
public interface UserService {
    /**
     * 按照用戶id返回所有的收貨地址
     * @param userId
     * @return
     */
    public List<UserAddress> getUserAddressList(String userId);
}

UserServiceImpl

public class UserServiceImpl implements UserService {
    public List<UserAddress> getUserAddressList(String userId) {

        UserAddress address1 = new UserAddress(1, "河南省鄭州鞏義市宋陵大廈2F", "1", "安然", "150360313x", "Y");
        UserAddress address2 = new UserAddress(2, "北京市昌平區沙河鎮沙陽路", "1", "情話", "1766666395x", "N");

        return Arrays.asList(address1,address2);
    }
}

創建Maven項目=> order-service-consumer  服務消費者(訂單服務)

OrderService

public interface OrderService {
    /**
     * 初始化訂單
     * @param userID
     */
    public void initOrder(String userID);
}

OrderServiceImpl

public class OrderServiceImpl implements OrderService {
    public void initOrder(String userID) {
        //查詢用戶的收貨地址

    }
}

因服務消費者要拿到提供者的方法
將 服務提供者 中的 實體類 及 UserService 複製到當前消費者同級文件中。

OrderServiceImpl

public class OrderServiceImpl implements OrderService {
    public UserService userService;
    public void initOrder(String userID) {
        //查詢用戶的收貨地址
        List<UserAddress> userAddressList = userService.getUserAddressList(userID);
        System.out.println(userAddressList);
    }
}

此時我們調用userservice肯定是要報錯的。這種面向接口的方式,我們這裏只是調到了接口,而接口實際是在另外一個項目中,如果我們兩個項目工程都創建共同的實體類,太過於麻煩了,我們可以將服務接口,服務模型等單獨放在一個項目中,更爲方便調用。

創建Maven項目=> gmail-interface 用於存放共同的服務接口

將 提供者 和 消費者 項目中的所有實體類複製到當前相關的文件包下,刪除原有的實體類包及service包,也就是將實體類及service放在了當前公共的項目中。

把服務提供者和消費者項目中引入以下依賴,引入後項目不在報錯.

    <dependency>
        <groupId>com.lemon.gmail</groupId>
        <artifactId>gmail-interface</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>

服務提供者配置及測試

在 user-service-provider 服務提供者項目中引入依賴

     <!--dubbo-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>dubbo</artifactId>
        <version>2.6.2</version>
    </dependency>
    <!--註冊中心是 zookeeper,引入zookeeper客戶端-->
    <dependency>
        <groupId>org.apache.curator</groupId>
        <artifactId>curator-framework</artifactId>
        <version>2.12.0</version>
    </dependency>

resource文件中創建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://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd
        http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
    <!--1、指定當前服務/應用的名字(同樣的服務名字相同,不要和別的服務同名)-->
   <dubbo:application name="user-service-provider"></dubbo:application>
    <!--2、指定註冊中心的位置-->
    <!--<dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry>-->
    <dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"></dubbo:registry>
    <!--3、指定通信規則(通信協議? 服務端口)-->
    <dubbo:protocol name="dubbo" port="20880"></dubbo:protocol>
    <!--4、暴露服務 讓別人調用 ref指向服務的真正實現對象-->
    <dubbo:service interface="com.lemon.gmail.service.UserService" ref="userServiceImpl"></dubbo:service>

    <!--服務的實現-->
    <bean id="userServiceImpl" class="com.lemon.gmail.service.impl.UserServiceImpl"></bean>
</beans>

編寫一個ProviderApplication啓動類程序,運行測試配置

public class MailApplication {
    public static void main(String[] args) throws IOException {
        ClassPathXmlApplicationContext applicationContext= new ClassPathXmlApplicationContext("provider.xml");
        applicationContext.start();
        System.in.read();
    }
}

啓動zookeeper註冊中心的的zkServer.cmd、和zkCli.cmd服務
在dubbo-admin  target中cmd運行 java -jar dubbo-admin-0.0.1-SNAPSHOT.jar
再次啓動項目,我們可以看到在zookeeper中已經發現服務提供者。
服務提供者的配置和測試完成

服務消費者配置及測試

在 order-service-consumer 服務消費者項目中引入依賴

  <!--dubbo-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.6.2</version>
        </dependency>
        <!--註冊中心是 zookeeper,引入zookeeper客戶端-->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>2.12.0</version>
        </dependency>

創建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://dubbo.apache.org/schema/dubbo"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd
        http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
   <!--包掃描-->
    <context:component-scan base-package="com.lemon.gmail.service.impl"/>

    <!--指定當前服務/應用的名字(同樣的服務名字相同,不要和別的服務同名)-->
    <dubbo:application name="order-service-consumer"></dubbo:application>
    <!--指定註冊中心的位置-->
    <dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry>

    <!--調用遠程暴露的服務,生成遠程服務代理-->
    <dubbo:reference interface="com.lemon.gmail.service.UserService" id="userService"></dubbo:reference>
</beans>

把當前OrderServiceImpl實現類中加上註解

@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    public UserService userService;
    public void initOrder(String userID) {
        //查詢用戶的收貨地址
        List<UserAddress> userAddressList = userService.getUserAddressList(userID);
        
        //爲了直觀的看到得到的數據,以下內容也可不寫
        System.out.println("當前接收到的userId=> "+userID);
        System.out.println("**********");
        System.out.println("查詢到的所有地址爲:");
        for (UserAddress userAddress : userAddressList) {
            //打印遠程服務地址的信息
            System.out.println(userAddress.getUserAddress());
        }
        
    }
}

編寫一個ConsumerApplication啓動類程序,運行測試配置

public class ConsumerApplication {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("consumer.xml");
        OrderService orderService = applicationContext.getBean(OrderService.class);

        //調用方法查詢出數據
        orderService.initOrder("1");
        System.out.println("調用完成...");
        System.in.read();
    }
}

注意:消費者的運行測試需要先啓動提供者。
啓動服務提供者、消費者。及zookeeper的和dubbo-admin,查看監控信息。
localhost:7001
此時可以看到一個提供者,一個消費者的信息監控信息。

dubbo-monitor-simple簡易監控中心

進入dubbo-monitor-simple文件,執行cmd命令,mvn package打包成jar包
將 dubbo-monitor-simple-2.0.0-assembly.tar.gz 壓縮包解壓至當前文件夾,解壓後config文件查看properties的配置是否是本地的zookeeper。
打開解壓後的 assembly.bin 文件,start.bat 啓動dubbo-monitor-simple監控中心
在瀏覽器 localhost:8080 ,可以看到一個監控中心。
在服務提供者和消費者的xml中配置以下內容,再次啓動服務提供和消費者啓動類。

    <!--dubbo-monitor-simple監控中心發現的配置-->
    <dubbo:monitor protocol="registry"></dubbo:monitor>
    <!--<dubbo:monitor address="127.0.0.1:7070"></dubbo:monitor>-->

可以看到,這個監控中心也捕獲到了服務提供和消費者信息

Dubbo與SpringBoot整合

boot-user-service-provider 服務提供者

創建Maven項目 boot-user-service-provider 服務提供者
導入以下依賴

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
        <relativePath />
    </parent>

    <dependencies>
        <dependency>
            <groupId>com.lemon.gmail</groupId>
            <artifactId>gmail-interface</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.boot</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>0.2.0</version>
        </dependency>
    </dependencies>

把 user-service-provider 中的service拿到此項目中。
注意,以此方法爲返回的需要更改 interface包中的void爲 List

@Service//dubbo的服務暴露
@Component
public class UserServiceImpl implements UserService {
    public List<UserAddress> getUserAddressList(String userId) {

        UserAddress address1 = new UserAddress(1, "河南省鄭州鞏義市宋陵大廈2F", "1", "安然", "150360313x", "Y");
        UserAddress address2 = new UserAddress(2, "北京市昌平區沙河鎮沙陽路", "1", "情話", "1766666395x", "N");

        return Arrays.asList(address1,address2);
    }
}

配置 application.properties

dubbo.application.name=boot-user-service-provider
dubbo.registry.address=127.0.0.1:2181
dubbo.registry.protocol=zookeeper

dubbo.protocol.name=dubbo
dubbo.protocol.port=20880

#連接監控中心
dubbo.monitor.protocol=registry

BootProviderApplication 啓動類配置

@EnableDubbo //開啓基於註解的dubbo功能
@SpringBootApplication
public class BootProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(BootProviderApplication.class, args);
    }
}

啓動註冊中心,啓動當前服務提供者,可以在瀏覽器看到一個服務提供者。

boot-order-service-consumer 服務消費者

創建Maven項目 boot-order-service-consumer 服務消費者
導入以下依賴

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

    <dependencies>
        <dependency>
            <groupId>com.lemon.gmail</groupId>
            <artifactId>gmail-interface</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.boot</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>0.2.0</version>
        </dependency>
    </dependencies>

把order-service-consumer項目中的service複製到當前項目。

@Service
public class OrderServiceImpl implements OrderService {

    @Reference//引用遠程提供者服務
    UserService userService;

    public List<UserAddress> initOrder(String userID) {
        //查詢用戶的收貨地址
        List<UserAddress> userAddressList = userService.getUserAddressList(userID);

        System.out.println("當前接收到的userId=> "+userID);
        System.out.println("**********");
        System.out.println("查詢到的所有地址爲:");
        for (UserAddress userAddress : userAddressList) {
            //打印遠程服務地址的信息
            System.out.println(userAddress.getUserAddress());
        }
        return userAddressList;
    }
}

創建 OrderController 控制器

@Controller
public class OrderController {
    @Autowired
    OrderService orderService;

    @RequestMapping("/initOrder")
    @ResponseBody
    public List<UserAddress> initOrder(@RequestParam("uid")String userId) {
        return orderService.initOrder(userId);
    }
}

創建application.properties  配置

server.port=8081
dubbo.application.name=boot-order-service-consumer
dubbo.registry.address=zookeeper://127.0.0.1:2181

#連接監控中心 註冊中心協議
dubbo.monitor.protocol=registry

BootConsumerApplication 啓動類創建

@EnableDubbo //開啓基於註解的dubbo功能
@SpringBootApplication
public class BootConsumerApplication {
    public static void main(String[] args){
        SpringApplication.run(BootConsumerApplication.class,args);
    }
}

配置完畢,此時啓動zookeeper註冊中心及監控。
啓動springboot配置的服務提供者和消費者
在瀏覽器輸入 localhost:7001 查看結果
http://localhost:8081/initOrder?uid=1  查詢到地址信息
duboo的springboot整合配置完成。

Dubbo配置

dubbo配置官網參考:http://dubbo.apache.org/zh-cn/docs/user/references/xml/dubbo-service.html
1、配置原則

JVM 啓動 -D 參數優先,這樣可以使用戶在部署和啓動時進行參數重寫,比如在啓動時需改變協議的端口。
XML 次之,如果在 XML 中有配置,則 dubbo.properties 中的相應配置項無效。
Properties 最後,相當於缺省值,只有 XML 沒有配置時,dubbo.properties 的相應配置項纔會生效,通常用於共享公共配置,比如應用名。
2、啓動時檢查
Dubbo 缺省會在啓動時檢查依賴的服務是否可用,不可用時會拋出異常,阻止 Spring 初始化完成,以便上線時,能及早發現問題,默認 check=“true”。

可以通過 check=“false” 關閉檢查,比如,測試時,有些服務不關心,或者出現了循環依賴,必須有一方先啓動。

另外,如果你的 Spring 容器是懶加載的,或者通過 API 編程延遲引用服務,請關閉 check,否則服務臨時不可用時,會拋出異常,拿到 null 引用,如果 check=“false”,總是會返回引用,當服務恢復時,能自動連上。

order-service-consumer消費者爲例,在consumer.xml中添加配置

<!--配置當前消費者的統一規則,當前所有的服務都不啓動時檢查-->
 <dubbo:consumer check="false"></dubbo:consumer>

添加後,即使服務提供者不啓動,啓動當前的消費者,也不會出現錯誤。
3、全局超時配置

全局超時配置
<dubbo:provider timeout="5000" />

指定接口以及特定方法超時配置
<dubbo:provider interface="com.foo.BarService" timeout="2000">
    <dubbo:method name="sayHello" timeout="3000" />
</dubbo:provider>

配置原則
dubbo推薦在Provider上儘量多配置Consumer端屬性

1、作服務的提供者,比服務使用方更清楚服務性能參數,如調用的超時時間,合理的重試次數,等等
2、在Provider配置後,Consumer不配置則會使用Provider的配置值,即Provider配置可以作爲Consumer的缺省值。否則,Consumer會使用Consumer端的全局設置,這對於Provider不可控的,並且往往是不合理的

配置的覆蓋規則:

  1. 方法級配置別優於接口級別,即小Scope優先
  2. Consumer端配置 優於 Provider配置 優於 全局配置,
  3. 最後是Dubbo Hard Code的配置值(見配置文檔)
    多版本控制

    http://dubbo.apache.org/zh-cn/docs/user/demos/multi-versions.html
    在服務提供者中複製多個impl。起不同的名字

在這裏插入圖片描述
在這裏插入圖片描述配置多個文件的路徑及信息。
服務消費者調用時,可自由配置版本
在這裏插入圖片描述

dubbo與springboot整合的三種方式

1、將服務提供者註冊到註冊中心(如何暴露服務)
1.1導入Dubbo的依賴 和 zookeeper 客戶端

2、讓服務消費者去註冊中心訂閱服務提供者的服務地址
Springboot與Dubbo整合的三種方式
2.1導入dubbo-starter。在application.properties配置屬性,使用@Service【暴露服務】,使用@Reference【引用服務】
2.2保留Dubbo 相關的xml配置文件
導入dubbo-starter,使用@ImportResource導入Dubbo的xml配置文件

3、使用 註解API的方式
將每一個組件手動配置到容器中,讓dubbo來掃描其他的組件

高可用

zookeeper宕機與dubbo直連
現象:zookeeper註冊中心宕機,還可以消費dubbo暴露的服務。
原因:

健壯性↓

  • 監控中心宕掉不影響使用,只是丟失部分採樣數據
  • 數據庫宕掉後,註冊中心仍能通過緩存提供服務列表查詢,但不能註冊新服務
  • 註冊中心對等集羣,任意一臺宕掉後,將自動切換到另一臺
  • 註冊中心全部宕掉後,服務提供者和服務消費者仍能通過本地緩存通訊
  • 服務提供者無狀態,任意一臺宕掉後,不影響使用
  • 服務提供者全部宕掉後,服務消費者應用將無法使用,並無限次重連等待服務提供者恢復
    高可用:通過設計,減少系統不能提供服務的時間;

集羣下dubbo負載均衡配置

在集羣負載均衡時,Dubbo 提供了多種均衡策略,缺省爲 random 隨機調用。

負載均衡策略如下

Random LoadBalance 基於權重的隨機負載均衡機制

隨機,按權重設置隨機概率。 在一個截面上碰撞的概率高,但調用量越大分佈越均勻,而且按概率使用權重後也比較均勻,有利於動態調整提供者權重。

RoundRobin LoadBalance 基於權重的輪詢負載均衡機制

輪循,按公約後的權重設置輪循比率。 存在慢的提供者累積請求的問題,比如:第二臺機器很慢,但沒掛,當請求調到第二臺時就卡在那,久而久之,所有請求都卡在調到第二臺上。

LeastActive LoadBalance最少活躍數負載均衡機制
最少活躍調用數,相同活躍數的隨機,活躍數指調用前後計數差。 使慢的提供者收到更少請求,因爲越慢的提供者的調用前後計數差會越大。

ConsistentHash LoadBalance一致性hash 負載均衡機制

一致性 Hash,相同參數的請求總是發到同一提供者。 當某一臺提供者掛時,原本發往該提供者的請求,基於虛擬節點,平攤到其它提供者,不會引起劇烈變動。算法參見:http://en.wikipedia.org/wiki/Consistent_hashing 缺省只對第一個參數 Hash,如果要修改,請配置 <dubbo:parameter key="hash.arguments" value="0,1" /> 缺省用 160 份虛擬節點,如果要修改,請配置 <dubbo:parameter key="hash.nodes" value="320" />

整合hystrix,服務熔斷與降級處理

服務降級

當服務器壓力劇增的情況下,根據實際業務情況及流量,對一些服務和頁面有策略的不處理或換種簡單的方式處理,從而釋放服務器資源以保證核心交易正常運作或高效運作。
可以通過服務降級功能臨時屏蔽某個出錯的非關鍵服務,並定義降級後的返回策略。
向註冊中心寫入動態配置覆蓋規則:

RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
Registry registry = registryFactory.getRegistry(URL.valueOf("zookeeper://10.20.153.10:2181"));
registry.register(URL.valueOf("override://0.0.0.0/com.foo.BarService?category=configurators&dynamic=false&application=foo&mock=force:return+null"));
  • 1
  • 2
  • 3

其中:
mock=force:return+null 表示消費方對該服務的方法調用都直接返回 null 值,不發起遠程調用。用來屏蔽不重要服務不可用時對調用方的影響。
還可以改爲 mock=fail:return+null 表示消費方對該服務的方法調用在失敗後,再返回 null 值,不拋異常。用來容忍不重要服務不穩定時對調用方的影響。

集羣容錯

在集羣調用失敗時,Dubbo 提供了多種容錯方案,缺省爲 failover 重試。
集羣容錯模式

Failover Cluster
失敗自動切換,當出現失敗,重試其它服務器。通常用於讀操作,但重試會帶來更長延遲。可通過 retries=“2” 來設置重試次數(不含第一次)。

重試次數配置如下:
<dubbo:service retries=“2” />

<dubbo:reference retries=“2” />

dubbo:reference
<dubbo:method name=“findFoo” retries=“2” />
</dubbo:reference>

Failfast Cluster
快速失敗,只發起一次調用,失敗立即報錯。通常用於非冪等性的寫操作,比如新增記錄。

Failsafe Cluster
失敗安全,出現異常時,直接忽略。通常用於寫入審計日誌等操作。

Failback Cluster
失敗自動恢復,後臺記錄失敗請求,定時重發。通常用於消息通知操作。

Forking Cluster
並行調用多個服務器,只要一個成功即返回。通常用於實時性要求較高的讀操作,但需要浪費更多服務資源。可通過 forks=“2” 來設置最大並行數。

Broadcast Cluster
廣播調用所有提供者,逐個調用,任意一臺報錯則報錯 [2]。通常用於通知所有提供者更新緩存或日誌等本地資源信息。

集羣模式配置
按照以下示例在服務提供方和消費方配置集羣模式
<dubbo:service cluster=“failsafe” />

<dubbo:reference cluster=“failsafe” />

整合hystrix

服務熔斷錯處理配置參考=> https://www.cnblogs.com/xc-xinxue/p/12459861.html

Hystrix 旨在通過控制那些訪問遠程系統、服務和第三方庫的節點,從而對延遲和故障提供更強大的容錯能力。Hystrix具備擁有回退機制和斷路器功能的線程和信號隔離,請求緩存和請求打包,以及監控和配置等功能
配置spring-cloud-starter-netflix-hystrix
spring boot官方提供了對hystrix的集成,直接在pom.xml里加入依賴:

 <dependency>
     <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
      <version>1.4.4.RELEASE</version>
</dependency>

然後在Application類上增加@EnableHystrix來啓用hystrix starter:

@SpringBootApplication
@EnableHystrix //開啓服務容錯功能
public class ProviderApplication {
    ...啓動方法
}

配置Provider端
在Dubbo的Provider上增加@HystrixCommand配置,這樣子調用就會經過Hystrix代理。

@Service(version = "1.0.0")
public class HelloServiceImpl implements HelloService {
    @HystrixCommand(commandProperties = {
     @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),
     @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000") })
    @Override
    public String sayHello(String name) {
        // System.out.println("async provider received: " + name);
        // return "annotation: hello, " + name;
        throw new RuntimeException("Exception to show hystrix enabled.");
    }
}

配置Consumer端
對於Consumer端,則可以增加一層method調用,並在method上配置@HystrixCommand。當調用出錯時,會走到fallbackMethod = "reliable"的調用裏。

@Reference(version = "1.0.0")
    private HelloService demoService;

    @HystrixCommand(fallbackMethod = "reliable")
    public String doSayHello(String name) {
        return demoService.sayHello(name);
    }
    public String reliable(String name) {
        return "hystrix fallback value";
    }

dubbo原理

RPC原理


一次完整的RPC調用流程(同步調用,異步另說)如下:

  1. 服務消費方(client)調用以本地調用方式調用服務;
  2. client stub接收到調用後負責將方法、參數等組裝成能夠進行網絡傳輸的消息體;
  3. client stub找到服務地址,並將消息發送到服務端;
  4. server stub收到消息後進行解碼;
  5. server stub根據解碼結果調用本地的服務;
  6. 本地服務執行並將結果返回給server stub;
  7. server stub將返回結果打包成消息併發送至消費方;
  8. client stub接收到消息,並進行解碼;
  9. 服務消費方得到最終結果。

dubbo只用了兩步1和8,中間的過程是透明的看不到的。RPC框架的目標就是要2~8這些步驟都封裝起來,這些細節對用戶來說是透明的,不可見的。

netty通信原理

Netty是一個異步事件驅動的網絡應用程序框架, 用於快速開發可維護的高性能協議服務器和客戶端。它極大地簡化並簡化了TCP和UDP套接字服務器等網絡編程。
BIO:(Blocking IO)
NIO (Non-Blocking IO)
Selector 一般稱 爲選擇器 ,也可以翻譯爲 多路複用器,
Connect(連接就緒)、Accept(接受就緒)、Read(讀就緒)、Write(寫就緒)

Netty基本原理:
netty基本原理,可參考https://www.sohu.com/a/272879207_463994

dubbo原理

1.dubbo原理    -框架設計

  • config 配置層:對外配置接口,以 ServiceConfig, ReferenceConfig 爲中心,可以直接初始化配置類,也可以通過 spring 解析配置生成配置類
  • proxy 服務代理層:服務接口透明代理,生成服務的客戶端 Stub 和服務器端 Skeleton, 以 ServiceProxy 爲中心,擴展接口爲 ProxyFactory
  • registry 註冊中心層:封裝服務地址的註冊與發現,以服務 URL 爲中心,擴展接口爲 RegistryFactory, Registry, RegistryService
  • cluster 路由層:封裝多個提供者的路由及負載均衡,並橋接註冊中心,以 Invoker 爲中心,擴展接口爲 Cluster, Directory, Router, LoadBalance
  • monitor 監控層:RPC 調用次數和調用時間監控,以 Statistics 爲中心,擴展接口爲 MonitorFactory, Monitor, MonitorService
  • protocol 遠程調用層:封裝 RPC 調用,以 Invocation, Result 爲中心,擴展接口爲 Protocol, Invoker, Exporter
  • exchange 信息交換層:封裝請求響應模式,同步轉異步,以 Request, Response 爲中心,擴展接口爲 Exchanger, ExchangeChannel, ExchangeClient, ExchangeServer
  • transport 網絡傳輸層:抽象 mina 和 netty 爲統一接口,以 Message 爲中心,擴展接口爲 Channel, Transporter, Client, Server, Codec
  • serialize 數據序列化層:可複用的一些工具,擴展接口爲 Serialization, ObjectInput, ObjectOutput, ThreadPool

2.dubbo原理 -啓動解析、加載配置信息

3.dubbo原理 -服務暴露

4.dubbo原理 -服務引用

5.dubbo原理 -服務調用

                                   

                                               

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章