(github地址:https://github.com/jiangcaijun/dubbo)html
這裏輸入引用文本Dubbo是一個分佈式服務框架,致力於提供高性能和透明化的RPC遠程服務調用方案,以服務者與消費者的方式在dubbo上註冊java
dubbo的架構圖,以下(圖片來源於internet)git
Provider: 暴露服務的服務提供方。 Consumer: 調用遠程服務的服務消費方。 Registry: 服務註冊與發現的註冊中心。 Monitor: 統計服務的調用次調和調用時間的監控中心。 Container: 服務運行容器。github
調用關係說明:算法
- 服務容器負責啓動,加載,運行服務提供者。
- 服務提供者在啓動時,向註冊中心註冊本身提供的服務。
- 服務消費者在啓動時,向註冊中心訂閱本身所需的服務。
- 註冊中心返回服務提供者地址列表給消費者,若是有變動,註冊中心將基於長鏈接推送變動數據給消費者。
- 服務消費者,從提供者地址列表中,基於軟負載均衡算法,選一臺提供者進行調用,若是調用失敗,再選另外一臺調用。
- 服務消費者和提供者,在內存中累計調用次數和調用時間,定時每分鐘發送一次統計數據到監控中心。
參考自:Dubbo與Zookeeper、SpringMVC整合和使用(負載均衡、容錯) - 好庫文摘spring
新建三個項目,均用maven進行管理,基於JDK1.7。實現點對點的生產與消費。apache
新建該項目,其pom以下api
<groupId>com.dubbo.demo</groupId> <artifactId>dubbo-api</artifactId> <version>1.0-SNAPSHOT</version>
新建一個接口,生產者將會負責該接口的實現,消費者將會調用該接口tomcat
package com.dubbo.demo; public interface IHelloWorld { public String sayHello(String name); public Object doSomeThing(); }
接着,利用maven install將其發佈至本地倉庫中,生產者與消費者將均會在pom.xml中引入該依賴。架構
其項目結構如圖:
新建該項目,其pom以下。
<groupId>com.dubbo.demo.provider</groupId> <artifactId>dubbo-provider</artifactId> <version>1.0-SNAPSHOT</version> <properties> <slf4j.version>1.7.21</slf4j.version> </properties> <dependencies> <dependency> <groupId>com.dubbo.demo</groupId> <artifactId>dubbo-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.5.3</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${slf4j.version}</version> </dependency> </dependencies>
該生產者引入了dubbo-api (註冊中心)和dubbo的依賴,同時爲了方便調試,還添加了日誌相關依賴。
實現dubbo-api (註冊中心)的接口
package com.dubbo.demo.provider; import com.dubbo.demo.IHelloWorld; public class HelloWorldServiceImpl implements IHelloWorld { public String sayHello(String name) { return "Hello World " + name + ", I come from dubbo-api " ; } public Object doSomeThing() { return "i am doSomeThing, I come from dubbo-api " ; } }
在resource目錄下新建配p2p_provider.xml,暴露IHelloWorld接口
<?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="hello_world_provider" owner="jcj" /> <!--表示咱們的服務註冊到哪一個位置--> <dubbo:registry address="N/A"></dubbo:registry> <!-- 用dubbo協議在20880端口暴露服務 --> <dubbo:protocol name="dubbo" port="20880"></dubbo:protocol> <!-- 具體的實現bean --> <bean id="helloService" class="com.dubbo.demo.provider.HelloWorldServiceImpl" /> <!-- 聲明須要暴露的服務接口 --> <dubbo:service interface="com.dubbo.demo.IHelloWorld" ref="helloService" /> </beans>
同時新建一個dubboTest方法,用來啓動dubbo-provider (生產者)。
public class dubboTest { public static void main(String []args) throws IOException { ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext(new String("provider.xml")); classPathXmlApplicationContext.start(); System.in.read(); } }
其項目結構如圖(圖中紅圈表明其引入了dubbo-api(註冊中心)的依賴):
其pom和dubbo-provider (生產者)相似,均須要引入dubbo-api (註冊中心)和dubbo的依賴。
在resource目錄下新建p2p_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="hello_world_provider" owner="jcj" /> <!--表示咱們的服務註冊到哪一個位置--> <dubbo:registry address="N/A"></dubbo:registry> <!-- 聲明須要暴露的服務接口 --> <dubbo:reference interface="com.dubbo.demo.IHelloWorld" url="dubbo://127.0.0.1:20880/com.dubbo.demo.IHelloWorld" id="helloService"></dubbo:reference> </beans>
與dubbo-provider (生產者)的p2p_provider.xml比較,均聲明須要暴露的服務接口,即暴露了dubbo-api(註冊中心)的接口方法。
新建一個測試方法dubboConsumerTest
import com.dubbo.demo.IHelloWorld; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.io.IOException; public class dubboConsumerTest { public static void main(String []args) throws IOException { ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext(new String("p2p_consumer.xml")); IHelloWorld iHelloWorld = (IHelloWorld)classPathXmlApplicationContext.getBean("helloService"); String result = iHelloWorld.sayHello("哈哈哈"); System.out.println("dubboConsumerTest.main: " + result); Object object = iHelloWorld.doSomeThing(); System.out.println("dubboConsumerTest.main: " + object.toString()); } }
其項目結構如圖(圖中紅圈表明其引入了dubbo-api(註冊中心)的依賴):
先啓動dubbo-provider (生產者)的dubboTest方法,此時服務開始提供; 此時生產者控制檯輸出以下:
[ com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol ] - [ INFO ] [DUBBO] disconected from /192.168.58.1:54584,url:dubbo://192.168.58.1:20880/com.dubbo.demo.IHelloWorld?anyhost=true&application=hello_world_provider&channel.readonly.sent=true&codec=dubbo&dubbo=2.5.3&heartbeat=60000&interface=com.dubbo.demo.IHelloWorld&methods=doSomeThing,sayHello&owner=jcj&pid=15740&revision=1.0-SNAPSHOT&side=provider×tamp=1498555464131, dubbo version: 2.5.3, current host: 127.0.0.1
再啓動dubbo-consumer (消費者)的dubboConsumerTest,嘗試調用該方法。 此時消費者控制檯輸出:
Refer dubbo service com.dubbo.demo.IHelloWorld from url dubbo://127.0.0.1:20880/com.dubbo.demo.IHelloWorld?application=hello_world_provider&dubbo=2.5.3&interface=com.dubbo.demo.IHelloWorld&methods=doSomeThing,sayHello&owner=jcj&pid=8296&revision=1.0-SNAPSHOT&side=consumer×tamp=1498555502597, dubbo version: 2.5.3, current host: 192.168.58.1 dubboConsumerTest.main: Hello World 哈哈哈, I come from dubbo-api dubboConsumerTest.main: i am doSomeThing, I come from dubbo-api
證實測試經過。
在pom.xml中添加zookeeper相關依賴,dubbo-consumer (消費者)也須要添加
<!--zookeeper apache--> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.6</version> </dependency> <!--zkclient--> <dependency> <groupId>com.github.sgroschupf</groupId> <artifactId>zkclient</artifactId> <version>0.1</version> </dependency>
在resource目錄下新建zk_provider.xml,鏈接zookeeper
<!-- 提供方應用信息,用於計算依賴關係 --> <dubbo:application name="hello_world_provider" owner="jcj" /> <!-- 使用zookeeper註冊中心暴露服務地址--> <dubbo:registry address="zookeeper://182.254.xx.xx:2181" check="false" subscribe="false" register="" /> <!-- 用dubbo協議在20880端口暴露服務 --> <dubbo:protocol name="dubbo" port="20880"></dubbo:protocol> <!-- 聲明須要暴露的服務接口 --> <dubbo:service interface="com.dubbo.demo.IHelloWorld" ref="helloService" /> <!-- 具體的實現bean --> <bean id="helloService" class="com.dubbo.demo.provider.HelloWorldServiceImpl" />
dubbo:registry 標籤一些屬性的說明:
dubbo:service標籤的一些屬性說明:
以上,引用自:Dubbo與Zookeeper、SpringMVC整合和使用(負載均衡、容錯) - 好庫文摘
在resource目錄下新建zk_consumer.xml,鏈接zookeeper
<!-- 提供方應用信息,用於計算依賴關係 --> <dubbo:application name="hello_world_provider" owner="jcj" /> <dubbo:registry address="zookeeper://182.254.xx.xx:2181" /> <!-- 生成遠程服務代理,能夠和本地bean同樣使用其接口 --> <dubbo:reference id="helloService" interface="com.dubbo.demo.IHelloWorld" />
運行各相應的xml文件,注意生產者與消費者的前後啓動順序,能夠在消費者的控制檯看到相應的預期輸出,測試經過。
當zookeeper註冊中心連不上時dubbo的線程時,因爲ZKClient默認的超時時間是Integer.MAX_VALUE,幾乎等於無限等待。由於系統有一些定時任務會比較頻繁地開啓新線程鏈接dubbo,因此致使的結果是tomcat一下子線程池就滿了,其它的不依賴dubbo的功能也被阻塞沒法使用。
解決方案:dubbo鏈接zookeeper註冊中心由於斷網致使線程無限等待問題
dubbo:是管理中間層的工具,在業務層到數據倉庫間有很是多服務的接入和服務提供者須要調度,dubbo提供一個框架解決這個問題。
注意這裏的dubbo只是一個框架,至於你架子上放什麼是徹底取決於你的,就像一個汽車骨架,你須要配你的輪子引擎。這個框架中要完成調度必需要有一個分佈式的註冊中心,儲存全部服務的元數據,你能夠用zk,也能夠用別的,例如: