咱們將這個接口單獨抽取出來,打成jar包被多個服務鎖依賴html
Provider工程的pom文件以下:算法
<properties>
<!--2.6.4版本的duboo依賴的Spring的版本-->
<spring-version>4.3.16.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>com.dubbo.test</groupId>
<artifactId>00-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--dubbo的依賴-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.4</version>
</dependency>
<!--Spring的依賴-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
spring-dubbo-provider.xml的配置以下所示:spring
這裏須要注意的是xml文件頭的問題,必定要注意,不然啓動會報異常:數據庫
Exception:通配符的匹配很全面, 但沒法找到元素 'dubbo:application' 的聲明;express
<?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://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <!--當前服務的應用名稱,將在監控平臺上顯示,通常與項目名相同-->
<dubbo:application name="01-first-provider"/>
<!--註冊service ,其就是真正的服務提供者-->
<bean id="service" class="com.test.service.someServiceImpl"/>
<!--將service的服務暴露 肯定接口,肯定實現,使用點對點的方式鏈接,暫時不是用Zookeeper-->
<dubbo:service interface="com.test.service.someService" ref="service" registry="N/A" />
</beans>
啓動類 providerRun以下所示apache
/** * 啓動類 */
public class providerRun { public static void main(String[] args) throws IOException { //在容器啓動到時候,就把咱們的服務註冊到註冊中心,或者稱之爲暴露 //建立Spring容器
ApplicationContext ac = new ClassPathXmlApplicationContext("spring-dubbo-provider.xml"); //Spring容器啓動
((ClassPathXmlApplicationContext) ac).start(); //使當前主線程阻塞,以提供持續服務
System.in.read(); } }
pom.xml內容以下:緩存
<properties>
<!--2.6.4版本的duboo依賴的Spring的版本-->
<spring-version>4.3.16.RELEASE</spring-version>
</properties> <dependencies>
<dependency>
<groupId>com.dubbo.test</groupId>
<artifactId>00-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--dubbo的依賴-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.4</version>
</dependency>
<!--Spring的依賴-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
spring-dubbo-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://code.alibabatech.com/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!--當前服務的應用名稱,將在監控平臺上顯示,通常與項目名相同-->
<dubbo:application name="01-first-consumer"/>
<!--肯定服務接口,肯定鏈接方式-->
<dubbo:reference id="someService" interface="com.test.service.someService" url="dubbo://localhost:20880"/>
</beans>
啓動類以下所示:網絡
/** * consumer啓動兼服務消費類 */
public class consumerRun { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("sprin-dubbo-consumer.xml"); someService service = (someService) ac.getBean("someService"); service.hello("Toney"); } }
咱們先啓動服務提供者providerRun,再啓動消費者consumerRun,觀察到以下信息併發
咱們經過消費者consumer在本身工程的Spring容器中獲取到的someService引用,成功調用了provider工程的hello方法
至於中途是怎麼調用的,就要着重關注咱們的兩個spring配置文件了
在上一個案列中,咱們使用的是直連的方式創建鏈接,如今咱們採用ZK做爲咱們的註冊中心
Dubbo的註冊中心官方推薦的就是Zookeeper
工程的話,複製服務提供者和消費者,稍加改動便可
pom.xml文件 增添一個依賴便可:
<!-- ZK的客戶端依賴:在進入到阿帕奇孵化器後由zkClient改成curator -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency>
配置文件以下所示:增改
使用的是集羣的方式,集羣機器的前後順序沒有影響
<!--聲明ZK服務中心 (單機)-->
<!--<dubbo:registry address="zookeeper://192.168.159.159:2181"/>-->
<!--第二中方式聲明ZK服務中心 (單機)-->
<!--<dubbo:registry protocol="zookeeper" address="192.68.159.159:2181" />-->
<!--聲明ZK服務中心,ZK集羣的方式-->
<dubbo:registry address="zookeeper://192.168.159.159:2181?backup=192.168.159.169:2181,192.168.159.179:2181"/>
<!--指定實列名,指定服務接口,不指定url,默認爲ZK-->
<dubbo:reference id="someService" interface="com.test.service.someService"/>
pom.xml 添加一個依賴
<!-- ZK的客戶端依賴:在進入到阿帕奇孵化器後由zkClient改成curator -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency>
配置文件以下所示: 增改
<!--聲明ZK服務中心 (單機)-->
<!--<dubbo:registry address="zookeeper://192.168.159.159:2181"/>-->
<!--第二中方式聲明ZK服務中心 (單機)-->
<!--<dubbo:registry protocol="zookeeper" address="192.68.159.159:2181" />-->
<!--聲明ZK服務中心,ZK集羣的方式-->
<dubbo:registry address="zookeeper://192.168.159.159:2181?backup=192.168.159.169:2181,192.168.159.179:2181"/>
<!--指定實列名,指定服務接口,不指定url,默認爲ZK--> <dubbo:reference id="someService" interface="com.test.service.someService"/>
咱們指定了ip爲192.168.159.159這臺機器上的ZK,那咱們就啓動之,
詳情翻閱:http://www.javashuo.com/article/p-bjtwezeg-ek.html(ZK的單機&集羣環境搭建)
首運行服務提供者。其次運行服務消費者,咱們觀察控制檯輸出
再觀察消費者的控制檯,我作了點修改,獲得了返回值並打印:
鏈接單機ZK,集羣ZK都已測試經過,暫時就寫到這兒吧,我要作一個被寫代碼耽誤的中華小當家(煮夫!!)
緩存嘛?就是緩存嘛!爲了減小服務提供者的壓力,Dubbo提供了基於結果的聲明式緩存,該緩存是基於消費者端的,只須要修改消費者配置文件便可,使用很簡單。
咱們就使用ZK的這個工程作演示
修改消費者的配置文件,添加如上屬性便可
咱們修改消費者的啓動了,對同一個函數進行兩次相同的訪問,以下:
而後咱們看服務的提供者,打印了幾回,若是是一次的話,則 說明第二次函數的調用並無通過服務的提供者的函數
——
經過上面的兩張圖,就能夠知道,咱們的緩存起效果了,但在這裏不得不瞭解瞭解Dubbo提供了三種結果緩存機制
固然下面三個就是cache屬性的值,直接指定使用哪一種緩存機制,默認是lru
lru:服務級別緩存的默認機制,該機制能夠默認緩存1000個結果集,若超過,採用最近最少使用原則拋出刪除緩存,以保證新的結果被緩存
threadlocal:當前線程緩存,當多個線程要對當前線程進行某一操做時首先須要查詢當前線程的某個信息,經過線程緩存,能夠有效減小緩存
jcache:能夠橋接第三方緩存產品
Dubbo的緩存是基於結果的,是在服務的消費方的主觀能動控制的,通常用於查詢結果不變的場景,由於他沒有緩存失效時間控制這玩意兒,只有等緩存結果滿了,pop出去最近最少使用的結果,若是一個數據是變更的,那麼服務消費者獲取到的永遠都是沒有更新的數據,除非該數據被POP
Dubbo的多版本控制指的是:服務名稱(即接口名)相同的狀況下提供不一樣的服務(實現類不一樣),爲服務添加一個版本號,使用"服務名稱"+"版本號"的方式來肯定一個服務
多版本控制主要的應用場景:當一個接口的實現類須要升級時,咱們能夠是喲個版本號進行過渡,注意版本不一樣的服務之間是不能相互引用的,設想這樣一個環境,一個服務的一個版本須要升級,在生產環境中通常不會一次性所有進行升級,而是在訪問最少的時候先升級一部分,而後下一次訪問最少的時候再升級一部分,而這一部分又一部分就可使用版本號來進行過渡
以前someService的實現類只有一個,如今咱們增長一個,用做版本演示
咱們的服務提供者由一個實現類變爲了兩個實現類,各自都有不一樣的實現,咱們首先對其進行註冊,其次在暴露服務時,指定本身的版本號
而消費者在遠程調用服務的時候,指定服務的版本便可調用指定了版本號的服務
——
直接在消費端修改版本號便可消費消費相同接口下不一樣的服務實現
服務分組和多版本控制的使用方式基本都是同樣的,知識將version改爲group就行了,可是各自適用的環境有點不一樣,使用版本控制是爲了升級,新版本替代老版本,老版本再也不提供服務 : version="1.0.0" 、 version="2.0.0";
分組也是相同接口給出了不一樣的實現類,可是這些實現類並無誰要替換掉誰的意思,針對不一樣的需求調用不一樣的服務接口,他們是並存的,就像支付服務的實現,能夠有微信支付,能夠有支付寶支付,還能夠銀聯,服務並存想用那個服務消費者就指定該服務所對應的分組便可 :group="pay.weixin" 、 group="pay.zhifubao"
若是咱們的服務啓動過程當中須要預熱事件(再啓動一段時間後性能才能到達最佳狀態)好比初始化緩存,等待相關資源就位等,可使用deplay進行延遲暴露
如上所示:咱們只須要在服務的提供方的<dubbo:service />標籤中添加delay屬性,單位毫秒
若值爲正數,則表示延遲暴露多少毫秒,在指定時間後再發布服務,
若值爲-1,則表示在spring初始化完成後暴露服務
不少時候一個項目會有多個註冊中心
同一個服務能夠註冊到多個不一樣地域的註冊中心,爲多個不一樣地域的服務提供服務
修改服務提供者的配置文件,多個註冊中心之間使用逗號分割,以下:
固然第二個集羣是假的,知道牛啃南瓜怎麼下嘴就行?固然你也可使用ZK單機模式演示
一個項目中,不一樣的服務能夠註冊不一樣的註冊中心:以下
同一個消費者須要調用兩個註冊中心的服務,而被調用的服務的接口名,版本號,分組等是相同的,不一樣中心的這個相同名稱的服務CURD的是不一樣的數據庫,即服務名相同,可是實現是不一樣的,修改服務消費者以下:
在咱們前面的Demo中,服務提供者和服務的消費者是經過zookeepeer鏈接協議鏈接上Zookeeper註冊中心的
爲何服務的提供者和消費者鏈接上Zookeeper,消費者就能夠消費服務了呢?
zookeeper協議:是提供者/消費者鏈接註冊中心的鏈接協議,並非提供者和消費者之間的鏈接協議
當消費者鏈接上註冊中心後,在消費服務以前,首先須要鏈接上這個服務的提供者,雖然服務的消費者能夠經過註冊中心獲取到服務提供者,但提供者對於消費者來講確實透明的,消費者並不知道真正的服務提供者是誰,不過不管服務的提供者是誰,消費者都須要鏈接上服務的提供者才能夠獲取到真正的服務,而這個鏈接也是須要專門的連接協議的,這個協議被稱爲服務的暴露協議
在咱們以前的Demo中並無看到服務暴露協議的相關配置,項目也是能夠運行,由於Dubbo採用了默認的暴露協議,Dubbo服務暴露協議
Dubbo服務暴露協議,適用於小數據量大併發的服務調用,以及服務消費者主機數遠遠大於服務提供者主機的狀況,服務提供少,需求多,單個主機應對高併發。
瞭解內容:除了Dubbo服務暴露協議,Dubbo框架還支持另外七種服務暴露協議,Hessian協議,Http協議,RMI協議,WebService協議,THrift協議,Memcached協議,Redis協議,在實際中使用最多的就是Dubbo服務暴露協議
下面咱們以Dubbo服務暴露協議做爲列子來講明服務暴露協議的用法
在服務的提供者的Spring配置文件中註冊服務暴露協議,
而後在暴露服務時具體指定所使用的已經被註冊的暴露協議
2、同一服務支持多種協議(修改服務提供者的配置文件)
3、不一樣服務使用不一樣的協議(修改服務提供者的配置文件)
牛啃南瓜知道怎麼啃就行,這裏我就沒作過多的演示
使得Provider實現着一開始就考慮到Provider的服務特色、服務質量等問題,由於做爲服務的提供者比服務的消費者更加清楚服務的性能參數,如調用的超時時間,合理的重試次數等,在Provider配置後,Consumer不配置則會默認使用Provider端的配置值,若是Consumer沒有配置,Provider也沒有配置,就會使用Consumer端的全局設置,這對於Provider而言是不可控的,也是不合理的
粒度到能夠針對某一個服務也能夠針對服務的同時針對某一個方法(hello方法)
timeout:遠程服務調用超時的時限
retries:失敗重試次數,默認爲2
loadbalance:負載均衡算法,默認是隨機random,還能夠選擇輪詢(roundrobin)、最不活躍優先(leastactive)等
actives:消費者最大併發調用限制,達到上限後,新的調用會被阻塞直到超時,0表示不限制
threads:用於指定服務的線程池大小
executes:一個服務並行執行的請求上限,超過上限,新請求確定被阻塞,可能阻塞到超時,該屬性在<dubbo:method/>則是針對指定的方法,配置在<dubbo:service />上則是針對整個服務
參數名 | 做用範圍 | 默認值 | 說明 | 備註 |
threads | provider | 200 | 業務處理線程池大小 | |
iothreads | provider | CPU+1 | io線程池大小 | |
queues | provider | 0 | 線程池隊列大小,當線程池滿時,排隊等待執行的隊列大小, 建議不要設置,當線程程池時應當即失敗, 重試其它服務提供機器,而不是排隊,除非有特殊需求 |
|
connections | consumer | 0 | 對每一個提供者的最大鏈接數, rmi、http、hessian等短鏈接協議表示限制鏈接數, Dubbo等長鏈接協表示創建的長鏈接個數 |
Dubbo協議默認共享一個長鏈接 |
actives | consumer | 0 | 每服務消費者每服務每方法最大併發調用數 | 0表示不限制 |
acceptes | provider | 0 | 服務提供方最大可接受鏈接數 | 0表示不限制 |
executes | provider | 0 | 服務提供者每服務每方法最大可並行執行請求數 | 0表示不限制 |