Dubbo框架簡介
阿新 • • 發佈:2019-01-03
前言:
今年三月份換了一份工作,在新公司使用阿里開源的Dubbo作為RPC服務框架,其使用方法和原VIP的Venus–OSP框架略有不同,在看過框架介紹後發現,其原理都是相似而共通的,現簡記如下。
參考文件:阿里巴巴Duboo官網
一 、知識點
- SOA(Service Oriented Architecture):面向服務的架構。
- 由 服務治理、服務註冊和發現、RPC、監控中心、排程中心以及服務路由、負載均衡等功能模組組成的資源排程和治理中心。
二、 RPC的演進
- 框架演進:ORM–>MVC–>RPC–>SOA
- 架構演進:單一應用架構–>垂直應用架構—>分散式服務架構–>流動計算架構
- 單一應用架構
- 網站流量小的時候,將所有功能集中到單一應用以減少成本。效能瓶頸在於 ORM框架。
- 垂直應用架構
- 網站流量增大,橫向擴充套件帶來的效益越來越低,將應用拆分為互不相干的幾個應用以提升效率。效能瓶頸在於MVC框架。
- 分散式服務架構
- 當垂直應用越來越多,應用之間互動不可避免,將核心業務抽取出來,作為獨立的服務,逐漸形成穩定的服務中心,使前端應用能更快速的響應多變的市場需求。 此時,用於提高業務複用及整合的分散式服務框架(RPC)是關鍵。
- 彈性計算架構
- 當服務越來越多,容量的評估,小服務資源的浪費等問題逐漸顯現,此時需增加一個排程中心基於訪問壓力實時管理叢集容量,提高叢集利用率。 此時,用於提高機器利用率的資源排程和治理中心(SOA)是關鍵。
三、 架構簡介
架構圖
節點角色
- Provider:服務提供方,在啟動時向註冊中心註冊服務;
- Consumer:服務消費方,向註冊中心請求服務提供方列表,在本地做負載均衡呼叫服務;
- Register:註冊中心,提供服務註冊與發現(一般由Zookeeper擔當),通過長連線與Provider和Consumer保持連線,負責監控Provider的上下線並及時通知Consumer;
- Monitor:監控中心,負責統計服務的效能資料;
- Container:服務執行容器。
呼叫關係
- “0.start”:服務執行容器啟動、載入、執行服務提供方,一般由Spring容器啟動Jar執行;
- “1.register”: 服務提供方在啟動時,向註冊中心註冊自己的IP、服務介面等資訊;
- “2.subscribe”: 服務消費方向註冊中心訂閱自己感興趣的服務提供方;
- “3.notify”: 註冊中心在服務提供方發生變更時將基於長連線向消費方推送訊息;
- “4.invoke”: 服務消費方在本地對服務列表做軟負載均衡演算法,選擇最優的服務提供方進行RPC呼叫;
- “5.count”: 消費方和提供方向監控中心 定時非同步推送服務呼叫次數和時間,消費方的包括網路耗時,提供方不包括網路耗時。
效能說明
- 連通性:註冊中心通過長連線與Provider和Consumer進行通訊,Provider和Consumer直接通過PRC直接呼叫,其只在啟動時向註冊中心註冊和訂閱,註冊中心不轉發請求,當註冊中心宕機,Consumer依然可以通過本地快取的Provider的地址列表進行呼叫;Provider和Consumer與監控中心定時地通過非同步通訊方式進行服務呼叫資訊上傳;
- 健壯性: 服務提供者無狀態,任意一臺宕掉後,不影響使用,服務提供者全部宕掉後,服務消費者應用將無法使用,並無限次重連等待服務提供者恢復。
- 伸縮性:註冊中心為對等叢集,可動態增加機器部署例項,所有客戶端將自動發現新的註冊中心,服務提供者無狀態,可動態增加機器部署例項,註冊中心將推送新的服務提供者資訊給消費者。
- 擴充套件性:當服務叢集規模進一步擴大,帶動IT治理結構進一步升級,需要實現動態部署,進行彈性計算,現有分散式服務架構不會帶來阻力。
四、 使用簡介
Dubbo是基於Spring的框架,其配置採用XML和註解的方式,使用Spring的BeanFactory載入Bean,執行在Spring容器中。
服務提供方
定義服務介面
DemoService.java
package com.alibaba.dubbo.demo; public interface DemoService { String sayHello(String name); }
打包成Jar包在服務提供方和消費者處使用,該工程裡除了介面定義以外,還有各種實體類和通用工具類
實現服務介面
DemoServiceImpl.java
package com.alibaba.dubbo.demo.provider; import com.alibaba.dubbo.demo.DemoService; public class DemoServiceImpl implements DemoService { public String sayHello(String name) { return "Hello " + name; } }
公司裡將介面定義和服務實現分為了兩個工程,不便於開發人員使用,建議採用Maven的多專案結構,將介面定義和服務實現定義在同一個父專案下。
暴露服務
- XML方式
<beans> <!--省略schema--!> <!-- 提供方應用資訊,用於計算依賴關係 --> <dubbo:application name="hello-world-app" /> <!-- 使用multicast廣播註冊中心暴露服務地址 --> <dubbo:registry address="multicast://224.5.6.7:1234" /> <!-- 用dubbo協議在20880埠暴露服務 --> <dubbo:protocol name="dubbo" port="20880" /> <!-- 宣告需要暴露的服務介面 --> <dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService" /> <!-- 和本地bean一樣實現服務 --> <bean id="demoService" class="com.alibaba.dubbo.demo.provider.DemoServiceImpl" /> </beans>
- 註解方式(推薦)
FooServiceImpl.java
import com.alibaba.dubbo.config.annotation.Service; @Service(version="1.0.0") public class FooServiceImpl implements FooService { }
provider.xml
<!-- 公共資訊,也可以用dubbo.properties配置 --> <dubbo:application name="annotation-provider" /> <dubbo:registry address="127.0.0.1:4548" /> <!-- 掃描註解包路徑,多個包用逗號分隔,不填pacakge表示掃描當前ApplicationContext中所有的類--> <dubbo:annotation package="com.foo.bar.service" />
啟動
public static void main(String[] args) throws Exception { //載入xml配置啟動Spring的BeanFactory ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"http://10.20.160.198/wiki/display/dubbo/provider.xml"}); context.start(); System.in.read(); // 按任意鍵退出 }
服務啟動時,將向註冊中心註冊本服務的IP、介面等資訊
服務消費方
引用遠端服務介面
xml方式
consumer.xml
<!-- 消費方應用名,用於計算依賴關係,不是匹配條件,不要與提供方一樣 --> <dubbo:application name="consumer-of-helloworld-app" /> <!-- 使用multicast廣播註冊中心暴露發現服務地址 --> <dubbo:registry address="multicast://224.5.6.7:1234" /> <!-- 生成遠端服務代理,可以和本地bean一樣使用demoService --> <dubbo:reference id="demoService" interface="com.alibaba.dubbo.demo.DemoService" />
註解方式(推薦)
@Component public class BarAction { @Reference(version="1.0.0") private FooService fooService; }
呼叫服務
public static void main(String[] args) throws Exception { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"http://10.20.160.198/wiki/display/dubbo/consumer.xml"}); context.start(); DemoService demoService = (DemoService)context.getBean("demoService"); // 獲取遠端服務代理 String hello = demoService.sayHello("world"); // 執行遠端方法 System.out.println( hello ); // 顯示呼叫結果 }
五、 屬性簡介
六、 服務暴露與引用的原始碼淺析
服務暴露
- 詳見服務暴露
服務引用
- 詳見服務引用