回到頂部
如何釋出服務,需要将需要暴露的服務接口釋出出去供用戶端調用,需要在java同級目錄建立一個resources目錄,然後将resoureces目錄标記成Test Resoureces Root,然後在esources目錄下建立MATE-INF.spring目錄,在該目錄下添加配置檔案dubbo-server.xml檔案
dubbo的服務端配置檔案如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<code><?xml version=</code><code>"1.0"</code> <code>encoding=</code><code>"UTF-8"</code><code>?></code>
<code><beans xmlns=</code><code>"http://www.springframework.org/schema/beans"</code> <code>xmlns:xsi=</code><code>"http://www.w3.org/2001/XMLSchema-instance"</code>
<code> </code><code>xmlns:dubbo=</code><code>"http://code.alibabatech.com/schema/dubbo"</code> <code>xsi:schemaLocation=</code><code>"http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://code.alibabatech.com/schema/dubbohttp://code.alibabatech.com/schema/dubbo/dubbo.xsd"</code><code>></code>
<code><!--提供方資訊,用于計算依賴關系--></code>
<code><dubbo:application name=</code><code>"dubbo-server"</code> <code>owner=</code><code>"mic"</code><code>/></code>
<code><!--注冊中心 暴露服務位址--></code>
<code><dubbo:registry address=</code><code>"zookeeper://192.168.126.129:2181"</code><code>/></code>
<code><!--用dubbo協定在</code><code>20880</code> <code>端口暴露服務--></code>
<code><dubbo:protocol port=</code><code>"20880"</code> <code>name=</code><code>"dubbo"</code><code>/></code>
<code><!--聲明需要暴露的服務接口,指定協定為dubbo,設定版本号</code><code>1.1</code><code>.</code><code>1</code><code>--></code>
<code><dubbo:service</code><code>interface</code><code>=</code><code>"com.gupaoedu.dubbo.IGpHello"</code> <code>ref=</code><code>"gpHelloService"</code> <code>protocol=</code><code>"dubbo"</code> <code>version=</code><code>"1.1.1"</code><code>/></code>
<code><!--聲明需要暴露的服務接口,指定協定為dubbo,設定版本号</code><code>1.1</code><code>.</code><code>2</code><code>--></code>
<code><dubbo:service</code><code>interface</code><code>=</code><code>"com.gupaoedu.dubbo.IDemoService"</code> <code>ref=</code><code>"demoService"</code> <code>protocol=</code><code>"dubbo"</code> <code>version=</code><code>"1.1.2"</code><code>/></code>
<code><!--和本地服務一樣實作服務--></code>
<code><bean id=</code><code>"gpHelloService"</code> <code>class</code><code>=</code><code>"com.gupaoedu.dubbo.GpHelloImpl"</code><code>/></code>
<code><bean id=</code><code>"demoService"</code> <code>class</code><code>=</code><code>"com.gupaoedu.dubbo.DemoService"</code><code>/></code>
<code></beans></code>
服務端的接口以及實作類
<code>public</code> <code>interface</code> <code>IGpHello {String sayHello(String msg);}</code>
<code>public</code> <code>interface</code> <code>IDemoService {String protocolDemo(String msg);}</code>
<code>public</code> <code>class</code> <code>GpHelloImpl</code><code>implements</code> <code>IGpHello{</code>
<code>@Override</code>
<code>public</code> <code>String sayHello(String msg) {</code><code>return</code> <code>"Hello:"</code><code>+msg;}</code>
<code>}</code>
<code>public</code> <code>class</code> <code>GpHelloImpl2</code><code>implements</code> <code>IGpHello{</code>
<code>public</code> <code>String sayHello(String msg) {</code><code>return</code> <code>"Hello,i'm server 2:"</code><code>+msg;}</code>
編寫Main方法,用spring容器來啟動服務
<code>public</code> <code>class</code> <code>Main {</code>
<code>public</code> <code>static</code> <code>void</code> <code>main(String[] args)</code><code>throws</code> <code>IOException {</code>
<code>//預設情況下會使用spring容器來啟動服務</code>
<code>com.alibaba.dubbo.container.Main.main(</code><code>new</code> <code>String[]{</code><code>"spring"</code><code>,</code><code>"log4j"</code><code>});}</code>
服務啟動過程會進行服務注冊,啟動監聽端口,啟動服務之後
在用戶端通過遠端調用通路服務端釋出的服務,相應的用戶端配置檔案 dubbo-client.xml 如下
<code>xmlns:dubbo=</code><code>"http://code.alibabatech.com/schema/dubbo"</code>
<code>xsi:schemaLocation=</code><code>"http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://code.alibabatech.com/schema/dubbohttp://code.alibabatech.com/schema/dubbo/dubbo.xsd"</code><code>></code>
<code><!--提供方資訊--></code>
<code><dubbo:application name=</code><code>"dubbo-client"</code> <code>owner=</code><code>"mic"</code><code>/></code>
<code><!--注冊中心--></code>
<code><dubbo:registry id=</code><code>"zokeeper"</code> <code>address=</code><code>"zookeeper://192.168.126.129:2181?register=false"</code> <code>file=</code><code>"d:/dubbo-server"</code><code>/></code>
<code><!--聲明需要暴露的服務接口,指定版本号--></code>
<code><dubbo:reference id=</code><code>"gpHelloService"</code> <code>interface</code><code>=</code><code>"com.gupaoedu.dubbo.IGpHello"</code> <code>registry=</code><code>"zookeeper"</code> <code>version=</code><code>"1.1.1"</code><code>/></code>
其實我們可以在zookeeper的用戶端可以發現,事實上已經釋出了服務方已經釋出了兩個不同版本的服務,具體如下
我們知道,這兩個版本正是我們在服務釋出方設定的不同版本号,同樣的,在消費端,我們可以通過設定指定的版本号擷取相應的版本服務,消費的代碼如下


在控制台,我們可以看到同樣的服務釋出位址url。
什麼叫主機綁定呢?主機綁定的流程是什麼?
在釋出一個dubbo服務的時候,會生成一個dubbo://ip:port的協定位址。這就是主機綁定過程,那麼這個IP是如何生成的呢?大家可以通過ServiceConfig.java 中的 doExportUrlForlProtocol 方法中找到如下代碼塊。大緻的邏輯是,首先從配置檔案中擷取,如果失敗再嘗試從本地網卡中擷取host,如果這個也失敗,會繼續執行,直到找到合适的IP位址。


在分析dubbo的叢集容錯前,先了解什麼是容錯機制?容錯機制指的是某種系統控制在一 定範圍内的一種允許或包容犯錯情況的發生,舉個簡單例 子,我們在電腦上運作一個程式,有時候會出現無響應的情況,然後系統會彈出一個提示框讓我們選擇,是立即結 束還是繼續等待,然後根據我們的選擇執行對應的操作, 這就是“容錯”。
在分布式架構下,網絡、硬體、應用都可能發生故障,由 于各個服務之間可能存在依賴關系,如果一條鍊路中的其 中一個節點出現故障,将會導緻雪崩效應。為了減少某一 個節點故障的影響範圍,是以我們才需要去建構容錯服務(這裡要說明一點,容錯機制僅僅是處理節點故障的一種機制), 來優雅的處理這種中斷的響應結果 。
Dubbo提供了6種容錯機制,分别如下
1. failsafe 失敗安全,可以認為是把錯誤吞掉(記錄日 志)
2. failover(預設) 重試其他伺服器; retries(2) ,預設的重試次數,不包含第一次
3. failfast 快速失敗, 失敗以後立馬報錯
4. failback 失敗後自動恢複。
5. forking forks. 設定并行數
6. broadcast 廣播,任意一台報錯,則執行的方法報錯
配置方式如下,通過cluster方式,配置指定的容錯方案
配置的優先級别
用戶端會優于服務端,這裡還可以細化,可以細化到方法級别
1. 方法級優先,接口級次之,全局配置再次之。
2. 如果級别一樣,則消費方優先,提供方次之
其中,服務提供方配置,通過URL經由注冊中心傳遞給消 費方
什麼應該配置在用戶端,什麼應該配置在服務端,retires、loadBlance、cluster(用戶端)、timeout(服務端)
以 timeout 為例,建議由服務提供方設定逾時,因為一個方法需要執行多長 時間,服務提供方更清楚,如果一個消費方同時引用多個 服務,就不需要關心每個服務的逾時設定。
降級的目的是為了保證核心服務可用。
降級可以有幾個層面的分類: 自動降級和人工降級; 按 照功能可以分為:讀服務降級和寫服務降級;
1. 對一些非核心服務進行人工降級,在大促之前通過降級 開關關閉哪些推薦内容、評價等對主流程沒有影響的功 能
2. 故障降級,比如調用的遠端服務挂了,網絡故障、或者 RPC服務傳回異常。 那麼可以直接降級,降級的方案比 如設定預設值、采用兜底資料(系統推薦的行為廣告挂 了,可以提前準備靜态頁面做傳回)等等
3. 限流降級,在秒殺這種流量比較集中并且流量特别大的 情況下,因為突發通路量特别大可能會導緻系統支撐不 了。這個時候可以采用限流來限制通路量。當達到閥值 時,後續的請求被降級,比如進入排隊頁面,比如跳轉 到錯誤頁(活動太火爆,稍後重試等)
dubbo的降級方式: Mock 機制
實作步驟
1. 在client端建立一個TestMock類,實作對應IGpHello 的接口(需要對哪個接口進行 mock,就實作哪個), 名稱必須以Mock結尾
2. 在client端的xml配置檔案中,添加如下配置,增加一 個mock屬性指向建立的TestMock
3. 模拟錯誤(設定 timeout),模拟逾時異常,運作測試代碼即可通路到TestMock這個類。當服務端故障解除 以後,調用過程将恢複正常
服務端的類及實作類,以及配置檔案,參考第一點的類及實作類以及配置檔案,然後再用戶端的配置檔案的加上mock,具體見如下截圖。
根據Mock機制實作步驟
首先我們再用戶端添加一個TestMock類,實作IGpHello接口,配置檔案我已經添加好了,可以看到我這裡的配置相對第一點用戶端的配置添加了幾個參數 timeout、failover、mock。這裡主要是看mock和timeout配置,因為我們是要去驗證mock機制,而failover是叢集容錯的配置,之是以我這裡沒有将這個參數去掉,是因為确定這裡他們不會有配置沖突,配置好之後,先釋出服務端的服務,然後運氣用戶端的App.java.在控制台我們可以看到列印結果,系統繁忙,這個結果說明,我們設定1秒逾時,用戶端遠端調用服務逾時,報錯了,然後就走到了Mock裡。
然後我們再驗證,将逾時間加大,設定為100,再運作,此時就不會報錯,就會正常輸出Hello world,輸出結果如下
好了,總結一下,整理了兩個晚上,沒有整理出我預想的效果,這篇文章主要是以一種開發文檔的形式簡單介紹了dubbo的多版本機制實作、主機綁定、叢集容錯處理機制、以及服務降級處理。後續會介紹dubbo的SPI機制,他是dubbo一種核心機制,我也是剛學習dubbo源碼不久,到時候有問題忘大家指正。該篇文章也存在許多不足的地方,比如結構可能不是非常清晰,描述也可能不是非常通俗易懂,後續我會努力矯正,今天就到這了,太困了現在,不寫了睡覺。
歡迎掃碼關注我的微信公衆号,我會不定期的更新一些個人技術文章