Dubbo(一) —— 基礎知識和項目搭建

1、分佈式基礎理論

一、什麼是分佈式系統

《分佈式系統原理與範型》定義:前端

「分佈式系統是若干獨立計算機的集合,這些計算機對於用戶來講就像單個相關係統」java

分佈式系統(distributed system)是創建在網絡之上的軟件系統。git

 

隨着互聯網的發展,網站應用的規模不斷擴大,常規的垂直應用架構已沒法應對,分佈式服務架構以及流動計算架構勢在必行,亟需一個治理系統確保架構有條不紊的演進。程序員

 

二、發展演變

 

單一應用架構

當網站流量很小時,只需一個應用,將全部功能都部署在一塊兒,以減小部署節點和成本。此時,用於簡化增刪改查工做量的數據訪問框架(ORM)是關鍵。github

適用於小型網站,小型管理系統,將全部功能都部署到一個功能裏,簡單易用。web

缺點:一、性能擴展比較難,比喻新增功能,修改功能,每臺機子都要從新部署算法

           二、協同開發問題,不少人都在同一個功能模塊裏面作,容易亂spring

           3、不利於升級維護,功能增長超量,項目大小增長,單臺機子就承受不住apache

垂直應用架構

當訪問量逐漸增大,單一應用增長機器帶來的加速度愈來愈小,將應用拆成互不相干的幾個應用,以提高效率。此時,用於加速前端頁面開發的Web框架(MVC)是關鍵。界面和業務邏輯是在一塊兒。windows

經過切分業務來實現各個模塊獨立部署,下降了維護和部署的難度,團隊各司其職更易管理,性能擴展也更方便,更有針對性。

缺點: 公用模塊沒法重複利用,開發性的浪費

分佈式服務架構

當垂直應用愈來愈多,應用之間交互不可避免,將核心業務抽取出來,做爲獨立的服務,逐漸造成穩定的服務中心,使前端應用能更快速的響應多變的市場需求。此時,用於提升業務複用及整合的分佈式服務框架(RPC)是關鍵。

流動計算架構

當服務愈來愈多,容量的評估,小服務資源的浪費等問題逐漸顯現,此時需增長一個調度中心基於訪問壓力實時管理集羣容量,提升集羣利用率。此時,用於提升機器利用率的資源調度和治理中心(SOA)[ Service Oriented Architecture]是關鍵

 

三、RPC

 什麼叫RPC

 RPCRemote Procedure Call】是指遠程過程調用,是一種進程間通訊方式,他是一種技術的思想,而不是規範。它容許程序調用另外一個地址空間(一般是共享網絡的另外一臺機器上)的過程或函數,而不用程序員顯式編碼這個遠程調用的細節。即程序員不管是調用本地的仍是遠程的函數,本質上編寫的調用代碼基本相同。

  RPC基本原理

 

 

 

 

RPC兩個核心模塊:通信,序列化。

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

 1)服務消費方(client)調用以本地調用方式調用服務;

  2client stub接收到調用後負責將方法、參數等組裝成可以進行網絡傳輸的消息體;

  3client stub找到服務地址,並將消息發送到服務端;

  4server stub收到消息後進行解碼;

  5server stub根據解碼結果調用本地的服務;

  6)本地服務執行並將結果返回給server stub

  7server stub將返回結果打包成消息併發送至消費方;

  8client stub接收到消息,並進行解碼;

 9)服務消費方獲得最終結果。

 RPC框架的目標就是要2~8這些步驟都封裝起來,這些細節對用戶來講是透明的,不可見的。

 

2、dubbo核心概念

一、簡介

Apache Dubbo (incubating) |ˈdʌbəʊ| 是一款高性能、輕量級的開源Java RPC框架,它提供了三大核心能力:面向接口的遠程方法調用,智能容錯和負載均衡,以及服務自動註冊和發現。

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

 

二、基本概念

 

服務提供者(Provider):暴露服務的服務提供方,服務提供者在啓動時,向註冊中心註冊本身提供的服務。

服務消費者(Consumer): 調用遠程服務的服務消費方,服務消費者在啓動時,向註冊中心訂閱本身所需的服務,服務消費者,從提供者地址列表中,基於軟負載均衡算法,選一臺提供者進行調用,若是調用失敗,再選另外一臺調用。

註冊中心(Registry):註冊中心返回服務提供者地址列表給消費者,若是有變動,註冊中心將基於長鏈接推送變動數據給消費者

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

容器(Container):服務運行容器

 

調用關係說明

  1. 服務容器負責啓動,加載,運行服務提供者。
  2. 服務提供者在啓動時,向註冊中心註冊本身提供的服務。
  3. 服務消費者在啓動時,向註冊中心訂閱本身所需的服務。
  4. 註冊中心返回服務提供者地址列表給消費者,若是有變動,註冊中心將基於長鏈接推送變動數據給消費者。
  5. 服務消費者,從提供者地址列表中,基於軟負載均衡算法,選一臺提供者進行調用,若是調用失敗,再選另外一臺調用。
  6. 服務消費者和提供者,在內存中累計調用次數和調用時間,定時每分鐘發送一次統計數據到監控中心。

Dubbo 架構具備如下幾個特色,分別是連通性、健壯性、伸縮性、以及向將來架構的升級性。

 

三、dubbo環境搭建

windows-安裝zookeeper

1、下載zookeeper

網址 https://archive.apache.org/dist/zookeeper/zookeeper-3.4.13/ 

2、解壓zookeeper

解壓運行zkServer.cmd 初次運行會報錯,沒有zoo.cfg配置文件

3修改zoo.cfg配置文件

conf下的zoo_sample.cfg複製一份更名爲zoo.cfg便可。

注意幾個重要位置:

dataDir=./   臨時數據存儲的目錄(可寫相對路徑)

clientPort=2181   zookeeper的端口號

修改完成後再次啓動zookeeper

4使用zkCli.cmd測試

ls /列出zookeeper根下保存的全部節點

create –e /chen 123建立一個臨時chen節點,值爲123

get /chen獲取/chen節點的值

5流程說明:

服務提供者啓動時:  /dubbo/com.foo.BarService/providers 目錄下寫入本身的 URL 地址

服務消費者啓動時: 訂閱 /dubbo/com.foo.BarService/providers 目錄下的提供者 URL 地址。並向 /dubbo/com.foo.BarService/consumers 目錄下寫入本身的 URL 地址

監控中心啓動時: 訂閱 /dubbo/com.foo.BarService 目錄下的全部提供者和消費者 URL 地址。

6支持如下功能:

當提供者出現斷電等異常停機時,註冊中心能自動刪除提供者信息

當註冊中心重啓時,能自動恢復註冊數據,以及訂閱請求

當會話過時時,能自動恢復註冊數據,以及訂閱請求

當設置 <dubbo:registry check="false" /> 時,記錄失敗註冊和訂閱請求,後臺定時重試

可經過 <dubbo:registry username="admin" password="1234" /> 設置 zookeeper 登陸信息

可經過 <dubbo:registry group="dubbo" /> 設置 zookeeper 的根節點,不設置將使用無根樹

支持 * 號通配符 <dubbo:reference group="*" version="*" />,可訂閱服務的全部分組和全部版本的提供者

 

windows-安裝dubbo-admin管理控制檯

dubbo自己並非一個服務軟件。它其實就是一個jar包可以幫你的java程序鏈接到zookeeper,並利用zookeeper消費、提供服務。因此你不用在Linux上啓動什麼dubbo服務。

可是爲了讓用戶更好的管理監控衆多的dubbo服務,官方提供了一個可視化的監控程序,不過這個監控即便不裝也不影響使用。

 

1、下載dubbo-admin

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

2、進入目錄,修改dubbo-admin配置

修改 src\main\resources\application.properties 指定zookeeper地址

 

3、打包dubbo-admin

mvn clean package -Dmaven.test.skip=true 

4、運行dubbo-admin

java -jar dubbo-admin-0.0.1-SNAPSHOT.jar

默認使用root/root 登錄

 

 

四、dubbo-helloworld

提出需求

某個電商系統,訂單服務須要調用用戶服務獲取某個用戶的全部地址;

咱們如今  須要建立兩個服務模塊進行測試 

模塊

功能

訂單服務web模塊

建立訂單等

用戶服務service模塊

查詢用戶地址等

 
 
 
 
 
 
 

測試預期結果:

訂單服務web模塊在A服務器用戶服務模塊在B服務器,A能夠遠程調用B的功能

工程架構

根據 dubbo《服務化最佳實踐》

1、分包

建議將服務接口,服務模型,服務異常等均放在 API 包中,由於服務模型及異常也是 API 的一部分,同時,這樣作也符合分包原則:重用發佈等價原則(REP),共同重用原則(CRP)

若是須要,也能夠考慮在 API 包中放置一份 spring 的引用配置,這樣使用方,只需在 spring 加載過程當中引用此配置便可,配置建議放在模塊的包目錄下,以避免衝突,如:com/alibaba/china/xxx/dubbo-reference.xml

2、粒度

服務接口儘量大粒度,每一個服務方法應表明一個功能,而不是某功能的一個步驟,不然將面臨分佈式事務問題,Dubbo 暫未提供分佈式事務支持。

服務接口建議以業務場景爲單位劃分,並對相近業務作抽象,防止接口數量爆炸。

不建議使用過於抽象的通用接口,如:Map query(Map),這樣的接口沒有明確語義,會給後期維護帶來不便。

 

建立模塊

1gmall-interface公共接口層modelserviceexception

 做用:定義公共接口,也能夠導入公共依賴

Bean模型

public class UserAddress implements Serializable{
    private Integer id;
    private String userAddress;
    private String userId;
    private String consignee;
    private String phoneNum;
    private String isDefault;

}

Service接口

UserService、OrderService

 

 2.boot-user-service-provider用戶模塊(對用戶接口的實現)

 做用:做爲提供者,提供接口的實現

pom.xml

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
   <groupId>com.gmall</groupId>
   <artifactId>gmall-interface</artifactId>
   <version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
   <groupId>com.alibaba.boot</groupId>
   <artifactId>dubbo-spring-boot-starter</artifactId>
   <version>0.2.0</version>
</dependency>
View Code

Impl實現類

//@Service//使用dubbo提供的Service暴露服務
@Component
public class UserServiceImpl implements UserService {
    @HystrixCommand
    @Override
    public List<UserAddress> getUserAddressList(String userId) {
        System.out.println("UserServiceImpl.......");
        UserAddress address1 = new UserAddress(1, "深圳市創業投資大廈", "1", "小明", "010-00000000", "Y");
        UserAddress address2 = new UserAddress(2, "深圳市怡化金融大廈", "2", "小李", "010-11111111", "N");
        System.out.println(address1);
        return Arrays.asList(address1,address2);
    }
}
View Code

provider.xml

    <!-- 一、指定當前服務/應用的名字(一樣的服務名字相同,不要和別的服務同名) -->
    <dubbo:application name="boot-user-service-provider"></dubbo:application>
    
    <!-- 二、指定註冊中心的位置 -->
    <!-- <dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry> -->
    <dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"></dubbo:registry>
    
    <!-- 三、指定通訊規則(通訊協議?通訊端口) -->
    <dubbo:protocol name="dubbo" port="20880"></dubbo:protocol>
    
    <!-- 四、暴露服務   ref:指向服務的真正的實現對象 -->
    <dubbo:service interface="com.gmall.service.UserService"
        ref="userServiceImpl" retries="2"  timeout="1000">
        <dubbo:method name="getUserAddressList" timeout="1000"></dubbo:method>
    </dubbo:service>

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

    <!-- 開啓dubbo註解支持 -->
    <!-- 掃描註解包路徑,多個包用逗號分隔,不填pacakge表示掃描當前ApplicationContext中全部的類 -->
    <!--<dubbo:annotation package="com.gmall.service.impl"/>-->

    <!--統一設置服務提供方的規則  -->
    <dubbo:provider timeout="1000" retries="3"></dubbo:provider>

    <!-- 鏈接監控中心 -->
    <dubbo:monitor protocol="registry"></dubbo:monitor>
View Code

application.properties

#dubbo.application.name=user-service-provider
#dubbo.registry.address=127.0.0.1:2181
#dubbo.registry.protocol=zookeeper
#
#dubbo.protocol.name=dubbo
#dubbo.protocol.port=20881
#
#dubbo.monitor.protocol=registry
#dubbo.scan.base-packages=com.gmall
View Code

Application啓動類

/**
 * 一、導入依賴;
 *         1)、導入dubbo-starter
 *         2)、導入dubbo的其餘依賴
 * @author chenhao
 *
 * SpringBoot與dubbo整合的兩種方式:
 * 1)、保留dubbo xml配置文件;
 *         導入dubbo-starter,使用@ImportResource導入dubbo的配置文件便可
 * 2)、導入dubbo-starter,在application.properties配置屬性,使用@Service【暴露服務】使用@Reference【引用服務】
 */
//@EnableDubbo //開啓基於註解的dubbo功能
//@ImportResource(locations="classpath:provider.xml")
//@EnableDubbo
@ImportResource(locations="classpath:provider.xml")
@EnableHystrix //開啓服務容錯
@SpringBootApplication
public class BootUserServiceProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(BootUserServiceProviderApplication.class, args);
    }
}
View Code

①、能夠用原始xml配置方式:如上provider.xml中配置,Application啓動類中須要註解引入@ImportResource(locations="classpath:provider.xml");

使用註解方式:使用註解須要先開啓dubbo註解,如provider.xml使用<dubbo:annotation package="com.gmall.service.impl"/>開啓dubbo註解,可是這種方式dubbo官網說下個版本再也不使用,或者在Application啓動類中使用@EnableDubbo註解,使用註解後就不須要再provider.xml中配置暴露服務,只須要在須要暴露的服務類上添加註解@Service //使用dubbo提供的service註解註冊暴露服務

②、也可使用properties的方式:Application啓動類中不須要引入provider.xml,可是要開啓dubbo註解,而且須要在須要暴露的服務類上添加dubbo提供的service註解註冊暴露服務

application.name就是服務名,不能跟別的dubbo提供端重複registry.protocol 是指定註冊中心協議

registry.address 是註冊中心的地址加端口號

protocol.name 是分佈式固定是dubbo,不要改。

base-package  註解方式要掃描的包

 

三、boot-order-service-consumer訂單模塊(調用用戶模塊)

 做用:做爲消費者

pom.xml

<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>


<dependency>
    <groupId>com.gmall</groupId>
    <artifactId>gmall-interface</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>
View Code

Controller

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

}
View Code

Impl實現類

    //@Reference
    @Autowired
    UserService userService;
    //@HystrixCommand(fallbackMethod="hello")
    @Override
    public List<UserAddress> initOrder(String userId) {
        // TODO Auto-generated method stub
        System.out.println("用戶id:"+userId);
        //一、查詢用戶的收貨地址
        List<UserAddress> addressList = userService.getUserAddressList(userId);
        return addressList;
    }
View Code

consumer.xml

    <dubbo:application name="boot-order-service-consumer"></dubbo:application>
    
    <dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry>
    
    <!--聲明須要調用的遠程服務的接口;生成遠程服務代理  -->
    <!-- 
        1)、精確優先 (方法級優先,接口級次之,全局配置再次之)
        2)、消費者設置優先(若是級別同樣,則消費方優先,提供方次之)
    -->
    <!-- timeout="0" 默認是1000ms-->
    <!-- retries="":重試次數,不包含第一次調用,0表明不重試-->
    <!-- 冪等(設置重試次數)【查詢、刪除、修改】、非冪等(不能設置重試次數)【新增】 -->
    <dubbo:reference interface="com.gmall.service.UserService"
        id="userService" timeout="5000" retries="3" >
        <dubbo:method name="getUserAddressList" timeout="1000"></dubbo:method>
    </dubbo:reference>
        
    <!-- 配置當前消費者的統一規則:全部的服務都不檢查 -->
    <dubbo:consumer check="false" timeout="5000"></dubbo:consumer>

    <dubbo:monitor protocol="registry"></dubbo:monitor>
    <!-- <dubbo:monitor address="127.0.0.1:7070"></dubbo:monitor> -->
View Code

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
View Code

Application啓動類

//@EnableDubbo
//@EnableHystrix
@ImportResource(locations="classpath:consumer.xml")
@SpringBootApplication
public class BootOrderServiceConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(BootOrderServiceConsumerApplication.class, args);
    }
}
View Code

①、能夠用原始xml配置方式:如上consumer.xml中配置,Application啓動類中須要註解引入@ImportResource(locations="classpath:consumer.xml");

使用註解方式:使用註解須要先開啓dubbo註解,在Application啓動類中使用@EnableDubbo註解,使用註解後就不須要再provider.xml中聲明須要調用的遠程服務的接口,只須要在須要引用的服務上UserService userService;添加註解@Reference  //使用dubbo提供的reference註解引用遠程服務

②、也可使用properties的方式:Application啓動類中不須要引入consumer.xml,可是要開啓dubbo註解,而且須要在須要引用的服務上UserService userService;添加註解@Reference  //使用dubbo提供的reference註解引用遠程服務

 

五、監控中心

dubbo-admin

圖形化的服務管理頁面;安裝時須要指定註冊中心地址,便可從註冊中心中獲取到全部的提供者/消費者進行配置管理,上面已經安裝

dubbo-monitor-simple

簡單的監控中心

 

1、安裝

 

下載 dubbo-ops

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

修改配置指定註冊中心地址

進入 dubbo-monitor-simple\src\main\resources\conf

修改 dubbo.properties文件

打包dubbo-monitor-simple

mvn clean package -Dmaven.test.skip=true

解壓 tar.gz 文件,並運行start.bat

雙擊運行start.bat

啓動訪問8080

 

2、監控中心配置

 

全部服務配置鏈接監控中心,進行監控統計

<!-- 監控中心協議,若是爲protocol="registry",表示從註冊中心發現監控中心地址,不然直連監控中心 -->

<dubbo:monitor protocol="registry"></dubbo:monitor>

Simple Monitor 掛掉不會影響到 Consumer Provider 之間的調用,因此用於生產環境不會有風險。

 

源碼地址:https://gitee.com/chenhaozi/SpringBoot_dubbo.git

相關文章
相關標籤/搜索