Apache Dubbo是一款高性能、輕量級的開源Java RPC框架,它提供了三大核心能力;面向接口的遠程方法調用,智能容錯和負載均衡,以及服務自動註冊和發現。html
dubbo官網:點我直達java
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.cyb</groupId> <artifactId>02-first-provider</artifactId> <version>1.0-SNAPSHOT</version> <!--編譯器依賴--> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>13</maven.compiler.source> <maven.compiler.target>13</maven.compiler.target> <!--自定義版本號--> <spring-version>4.3.16.RELEASE</spring-version> </properties> <dependencies> <!--自定義工程依賴--> <dependency> <groupId>org.cyb</groupId> <artifactId>01-common</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <!--dubbo依賴--> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.6.7</version> </dependency> <!--netty--> <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.32.Final</version> </dependency> <!--spring依賴--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</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-context</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-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-tx</artifactId> <version>${spring-version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring-version}</version> </dependency> </dependencies> </project>
<?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="02-first-provider"/> <!--註冊Service,未來服務的提供者--> <bean id="someService" class="com.cyb.service.SomeServiceImpl"></bean> <!--暴露服務,採用直連的方式--> <dubbo:service interface="com.cyb.service.SomeService" ref="someService" registry="N/A"></dubbo:service> </beans>
package com.cyb.service; public class SomeServiceImpl implements SomeService{ @Override public String hello(String name) { System.out.println("Dubbo World Welcome You"+name); return "chenyanbin"; } }
package com.cyb.run; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.io.IOException; public class RunProvider { public static void main(String[] args) throws IOException { //建立spring容器 ApplicationContext ac = new ClassPathXmlApplicationContext("spring-dubbo-provider.xml"); //啓動spring容器 ((ClassPathXmlApplicationContext) ac).start(); //將當前主線程阻塞 System.in.read(); } }
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.cyb</groupId> <artifactId>02-first-consumer</artifactId> <version>1.0-SNAPSHOT</version> <!--編譯器依賴--> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>13</maven.compiler.source> <maven.compiler.target>13</maven.compiler.target> <!--自定義版本號--> <spring-version>4.3.16.RELEASE</spring-version> </properties> <dependencies> <!--自定義工程依賴--> <dependency> <groupId>org.cyb</groupId> <artifactId>01-common</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <!--dubbo依賴--> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.6.7</version> </dependency> <!--netty--> <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.32.Final</version> </dependency> <!--spring依賴--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</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-context</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-aop</artifactId> <version>${spring-version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>${spring-version}</version> </dependency> </dependencies> </project>
<?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="02-first-consumer"/> <!--消費引用--> <dubbo:reference id="someSerivce" interface="com.cyb.service.SomeService" url="dubbo://localhost:20880"></dubbo:reference> </beans>
注:端口號20880固定算法
package com.cyb.run; import com.cyb.service.SomeService; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class RunConsumer { public static void main(String[] args) { //建立Spring容器 ApplicationContext ac=new ClassPathXmlApplicationContext("spring-dubbo-consumer.xml"); SomeService service = (SomeService) ac.getBean("someSerivce"); service.hello("tom"); } }
地址:http://dubbo.apache.org/zh-cn/docs/user/references/registry/introduction.htmlspring
配置參考地址:點我直達數據庫
<!-- zk客戶端依賴:curator-framework--> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>4.0.1</version> </dependency>
<?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="03-provider-zk"/> <!--註冊Service,未來服務的提供者--> <bean id="someService" class="com.cyb.service.SomeServiceImpl"></bean> <!-- 聲明zk服務中心 --> <!-- 單機版 --> <!-- 方式一 --> <dubbo:registry address="zookeeper://192.168.1.111:2181"/> <!-- 方式二 --> <!-- <dubbo:registry protocol="zookeeper" address=""/> --> <!-- 集羣配置 --> <!-- 方式一 --> <!-- <dubbo:registry address="zookeeper://10.20.153.10:2181?backup=10.20.153.11:2181,10.20.153.12:2181" /> --> <!-- 方式二 --> <!-- <dubbo:registry protocol="zookeeper" address="10.20.153.10:2181,10.20.153.11:2181,10.20.153.12:2181" /> --> <!-- 同一Zookeeper,分紅多組註冊中心 --> <!-- <dubbo:registry id="chinaRegistry" protocol="zookeeper" address="10.20.153.10:2181" group="china" /> <dubbo:registry id="intlRegistry" protocol="zookeeper" address="10.20.153.10:2181" group="intl" /> --> <!-- 暴露服務,將服務暴露給zk服務中心 --> <!-- <dubbo:service interface="com.cyb.service.SomeService" ref="someService" registry="N/A"></dubbo:service> --> <dubbo:service interface="com.cyb.service.SomeService" ref="someService"></dubbo:service> </beans>
<!-- zk客戶端依賴:curator-framework--> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>4.0.1</version> </dependency>
<?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="03-consumer-zk"/> <!-- 聲明zk服務中心 --> <!-- 單機版 --> <dubbo:registry address="zookeeper://192.168.1.111:2181"/> <!--消費引用--> <!-- <dubbo:reference id="someSerivce" interface="com.cyb.service.SomeService" url="dubbo://localhost:20880"></dubbo:reference> --> <dubbo:reference id="someSerivce" interface="com.cyb.service.SomeService"></dubbo:reference> </beans>
爲了進一步提升消費者對用戶的響應速度,減小提供者的壓力。Dubbo提供了基於結果的聲明式緩存。該緩存是基於消費者端的,因此使用很簡單,只需修改消費者配置文件,與提供者無關。express
僅需在<dubbo:reference />中添加cache="true"便可apache
先不加緩存,發現提供者執行2次,加上緩存提供者只執行一次緩存
<?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="03-consumer-zk"/> <!-- 聲明zk服務中心 --> <!-- 單機版 --> <dubbo:registry address="zookeeper://192.168.1.111:2181"/> <!-- <dubbo:reference id="someSerivce" interface="com.cyb.service.SomeService" url="dubbo://localhost:20880"></dubbo:reference> --> <!-- <dubbo:reference id="someSerivce" interface="com.cyb.service.SomeService"></dubbo:reference> --> <!--消費引用:基於服務級別的聲明式緩存(結果緩存)--> <!--<dubbo:reference id="someSerivce" interface="com.cyb.service.SomeService" cache="true"></dubbo:reference>--> <!--消費引用:基於方法級別的聲明式緩存(結果緩存)--> <dubbo:reference id="someSerivce" interface="com.cyb.service.SomeService" > <!--lru--> <dubbo:method name="hello" cache="lru"></dubbo:method> <!--threadlocal--> <dubbo:method name="hello" cache="threadlocal"></dubbo:method> </dubbo:reference> </beans>
Dubbo的結果緩存能夠應用在查詢結果不變的場景。即不能使用在以下場景:消費者A調用的業務方法後從DB查詢到一個結果a,此後,消費者B對DB中的該結果相關數據進行了修改,已使該查詢結果變爲b,但因爲使用告終果緩存,消費者A中調用業務方法後的查詢結果將長時間爲a,直到該結果因爲緩存空間滿而被消除,不然,永遠沒法獲得更新過的結果b。微信
Dubbo的多版本控制指的是,服務名稱(接口名)相同的狀況下提供不一樣的服務(實現類不一樣) ,然而消費者是經過服務名稱(接口名)進行服務查詢並進行消費的。提供者所提供的服務名稱相同,如何讓消費者經過名稱進行服務查找呢?爲服務添加一個版本號,使用「服務名稱」+「版本號」的方式來惟一肯定一個服務。併發
多版本控制主要的應用場景是:當一個接口的實現類須要升級時,可使用版本號進行過渡(根據開閉原則,不能直接修改原實現類,只能添加新的實現類)。須要注意的是,版本號不一樣的服務間是不能互相引用的,由於新版本存在的目的是替換老版本。在生產環境中若存在多個提供者須要升級,通常不會一次性所有進行升級,而是會在低壓力時間段先升級一部分,而後在下次再進行部分升級,直到所有升級完成。那麼,這期間就須要使用版本號進行過渡。
拷貝項目
服務分組與多版本控制的使用方式幾乎是相同的,只要將version替換爲group便可。但使用目的不一樣。使用版本控制的目的是爲了升級,將原有老版本替換掉,未來再也不提供老版本的服務,因此不一樣版本間不能出現相互調用。而分組的目的則不一樣,其也是針對相同接口,給出了多種實現類,但不一樣的是,這些不一樣實現並無替換掉誰的意思,是針對不一樣需求,或針對不一樣功能模塊鎖給出的實現。這些實現所提供的服務是並存的,因此他們間能夠出現相互調用關係。例如,支付服務的實現,能夠有微信支付實現與支付寶實現等。
若是咱們的服務啓動過程當中須要warmup事件(預熱事件,與JVM重啓後的預熱過程類似,在啓動後一小段事件後性能才能達到最佳狀態)。好比初始化緩存,等待相關資源就位等。可使用deplay進行延遲暴露。
值須要在服務提供者的<dubbo:service/>標籤中添加delay屬性,其值若爲整數,則單位爲毫秒,表示在指定事件後再發布服務;若爲-1,則表示在spring初始化完畢後再暴露服務。
不少時候一個項目中會有多個註冊中心。
同一個服務能夠註冊到不一樣地域的多個註冊中心,以便爲不一樣地域的服務消費者提供更爲快捷的服務。
修改服務提供者配置文件。多個註冊中心之間使用逗號分隔。
注:不是集羣!!!
修改服務提供者配置文件
同一個消費者須要調用兩個不一樣中心服務,而調用的該服務的名稱(接口)、版本等都是相同的。不一樣中心的這個相同名稱的服務調用時不一樣數據庫中的數據,即相同服務最終執行的結果是不一樣的。
修改服務消費者配置文件
前面的示例中,服務提供者與服務消費者都是經過zookeeper鏈接協議鏈接上ZooKeeper註冊中心的。
提供者與消費者均鏈接上了註冊中心,那麼消費者就理所固然的能夠享受提供者提供的服務了麼?
實際狀況並非這樣的。前述ZooKeeper協議,是消費者/提供者鏈接註冊中心的鏈接協議,而非消費者與提供者間的鏈接協議。
當消費者鏈接上註冊中心後,在消費服務以前,首先須要鏈接上這個服務提供者。雖然消費者經過註冊中心能夠獲取到服務提供者,但提供者對於消費者來講倒是透明的,消費者並不知道真正的服務提供者是誰。不過,不管提供者是誰,消費者都必須鏈接上提供者才能夠獲取到真正的服務,而這個鏈接也是須要專門的鏈接協議的。這個協議稱爲服務暴露協議。
但是咱們以前的代碼示例中並無看到服務暴露協議的相關配置,但仍可正常運行項目,這是爲何呢?由於採用了默認的暴露協議:Dubbo服務暴露協議。處理Dubbo服務暴露協議外,Dubbo框架還支持另外七種服務暴露協議:Hessian協議、HTTP協議、RMI協議、WebService協議、Thrift協議、Memcached協議、Redis協議;但在實際生產中,使用最多的就是Dubbo服務暴露協議。
Dubbo服務暴露協議,適合於小數據量大併發的服務調用,以及服務消費者主機數遠大於服務提供者主機數的狀況。
在服務提供者的spring配置文件中首先須要註冊暴露協議,而後在暴露服務時具體制定所使用的已註冊的暴露協議。
注:protocol屬性用於指定當前服務所使用的暴露協議
直接修改服務提供者的配置文件
直接修改服務提供者配置文件
提供者上儘可能多配置消費者端的屬性,讓提供者實現着一開始就思考提供者服務特色、服務質量等問題。由於做服務的提供者,比服務使用方更清楚服務性能參數,如調用的超時時間、合理的重試次數等。在提供者端配置後,消費者不配置則會使用提供者端的配置值,即提供者配置能夠做爲消費者的缺省值。不然,消費者會使用消費者端的全局設置,這對提供者是不可控的,而且每每不合理的。
如下屬性在<dubbo:method/>上則是針對指定方法,配置在<dubbo:service/>上則是針對整個服務。