您好,登錄后才能下訂單哦!
這篇文章主要講解了“怎么用Dubbo+Zookeeper+Spring實現(xiàn)Demo”,文中的講解內(nèi)容簡單清晰,易于學(xué)習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習“怎么用Dubbo+Zookeeper+Spring實現(xiàn)Demo”吧!
Dubbo是一個分布式服務(wù)框架,致力于提供高性能和透明化的RPC遠程服務(wù)調(diào)用方案,以及SOA服務(wù)治理方案。 微服務(wù)使用最廣泛的框架就是SpringCloud跟Dubbo。Dubbo比較專注于服務(wù)治理這塊,而SpringCloud全家桶則提供了微服務(wù)的一整套解決方案
遠程通訊: 提供對多種基于長連接的NIO框架抽象封裝,包括多種線程模型,序列化,以及“請求-響應(yīng)”模式的信息交換方式。
集群容錯: 提供基于接口方法的透明遠程過程調(diào)用,包括多協(xié)議支持,以及軟負載均衡,失敗容錯,地址路由,動態(tài)配置等集群支持。
自動發(fā)現(xiàn): 基于注冊中心目錄服務(wù),使服務(wù)消費方能動態(tài)的查找服務(wù)提供方,使地址透明,使服務(wù)提供方可以平滑增加或減少機器。
透明化的遠程方法調(diào)用,就像調(diào)用本地方法一樣調(diào)用遠程方法,只需簡單配置,沒有任何API侵入。
軟負載均衡及容錯機制,可在內(nèi)網(wǎng)替代F5等硬件負載均衡器,降低成本,減少單點。
服務(wù)自動注冊與發(fā)現(xiàn),不再需要寫死服務(wù)提供方地址,注冊中心基于接口名查詢服務(wù)提供者的IP地址,并且能夠平滑添加或刪除服務(wù)提供者。
Dubbo采用全Spring配置方式,透明化接入應(yīng)用,對應(yīng)用沒有任何API侵入,不管是Provider還是Consumer都可以通過Spring的配置文件進行配置,配置完之后,就可以像使用springbean一樣進行服務(wù)暴露和調(diào)用了,完全看不到dubboapi的存在。Dubbo基于Spring的Schema擴展進行加載。
現(xiàn)在還可以通過 API 的方式進行調(diào)用。
Provider: 暴露服務(wù)的服務(wù)提供方。
Consumer: 調(diào)用遠程服務(wù)的服務(wù)消費方。
Registry: 服務(wù)注冊與發(fā)現(xiàn)的注冊中心。
Monitor: 統(tǒng)計服務(wù)的調(diào)用次調(diào)和調(diào)用時間的監(jiān)控中心。
Container: 服務(wù)運行容器。
架構(gòu)圖
調(diào)用關(guān)系說明:
服務(wù)消費者和提供者,在內(nèi)存中累計調(diào)用次數(shù)和調(diào)用時間,定時每分鐘發(fā)送一次統(tǒng)計數(shù)據(jù)到監(jiān)控中心。
服務(wù)消費者,從提供者地址列表中,基于軟負載均衡算法,選一臺提供者進行調(diào)用,如果調(diào)用失敗,再選另一臺調(diào)用。
注冊中心返回服務(wù)提供者地址列表給消費者,如果有變更,注冊中心將基于長連接推送變更數(shù)據(jù)給消費者。
服務(wù)消費者在啟動時,向注冊中心訂閱自己所需的服務(wù)。
服務(wù)提供者在啟動時,向注冊中心注冊自己提供的服務(wù)。
服務(wù)容器負責啟動,加載,運行服務(wù)提供者。
連通性:連通性說明他們之間都存在著關(guān)系,比如說Provider,Consumer和Registry三者之間都是長連接,而Provider,Consumer向Registry注冊服務(wù)以及訂閱服務(wù)的時間都得向Monitor匯報
健壯性:而健壯性說明具有穩(wěn)定性,比如說注冊中心對等集群中的任意一臺宕掉后,將自動切換到另一臺。就算注冊中心全部宕掉,服務(wù)者和消費者仍可以通過本地緩存進行通訊。
伸縮性:伸縮性就是可以通過增加機器部署實例進行添加新的注冊中心和服務(wù)提供者
升級性:文檔中提到的對未來架構(gòu)的設(shè)想,比起目前框架它的特點是可以實現(xiàn)自動部署服務(wù)的本地代理以及可以通過訪問壓力來自動增減服務(wù)提供者
本demo中用的是Zookeeper 3.4.14版本,用哪個版本都行,記得改下demo中的pom文件里的ZK依賴配置就可以。下載和安裝步驟可以參考以下鏈接:https://blog.csdn.net/tlk20071/article/details/52028945
為什么采用Zookeeper?
本demo中采用Zookeeper作為Dubbo的注冊中心時,ZK是一個樹型的目錄服務(wù),支持變更推送,可以作為集群的管理工具使用??梢约泄芾砼渲梦募?/p>
(1)服務(wù)提供者在初始化啟動時,會在Zookeeper下的Dubbo節(jié)點下的服務(wù)節(jié)點下的providers節(jié)點下的節(jié)點創(chuàng)建一個子節(jié)點并寫入URL,路徑類似為 /dubbo/servicename/providers/ ,該路徑下的所有子節(jié)點均為服務(wù)提供者。此時這些子節(jié)點都為臨時節(jié)點,因為臨時節(jié)點的生命周期與客戶端會話相關(guān),所以一旦提供者所在的機器出現(xiàn)故障導(dǎo)致提供者無法提供服務(wù),該臨時節(jié)點就會自動從Zookeeper刪除。
此時因為服務(wù)者,注冊中心,消費者之間是長連接,注冊中心能感知服務(wù)者宕機,會告知消費者。
而監(jiān)控中心是Dubbo服務(wù)治理體系中重要的一部分,它需要知道所有的服務(wù)提供者和消費者的變化情況 。所以它在啟動時會在服務(wù)節(jié)點上注冊一個watcher來監(jiān)聽子節(jié)點變化,路徑為 /dubbo/servicename/ ,所以它也能感知服務(wù)提供者的宕機。
(2)還有一個特性就是Zookeeper的節(jié)點結(jié)構(gòu)設(shè)計(樹形),它以服務(wù)名和類型,也就是 /dubbo/servicename/類型 作為節(jié)點路徑,符合Dubbo訂閱和通知的需求,保證了以服務(wù)為粒度的變更通知,通知范圍易于控制。所以即使服務(wù)提供者和消費者頻繁變更,對Zookeeper的性能也不會造成多大影響。
創(chuàng)建Maven項目project,然后在工程里面創(chuàng)建三大模塊moudle,分別為: dubbo-api (公共服務(wù)接口) 、 dubbo-consumer(消費者,調(diào)用遠程服務(wù))、 dubbo-provider(提供遠程服務(wù))。
(1)其中需要在整個項目的pom.xml文件中添加相關(guān)依賴:這里需要注意dubbo的版本問題,下面會講到,這里插個眼先。
<?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>com.test</groupId> <artifactId>dubbo_demo</artifactId> <version>1.0-SNAPSHOT</version> <modules> <module>dubbo_consumer</module> <module>dubbo_provider</module> <module>dubbo_api</module> </modules> <packaging>pom</packaging> <name>dubbo_demo Maven Webapp</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.4.RELEASE</version> </dependency> <!-- 添加 日志依賴包 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.24</version> </dependency> <!-- 添加 dubbo 依賴包 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.6.3</version> </dependency> <!-- 添加 zookeeper 相關(guān)依賴包 --> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.14</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>2.8.0</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <version>2.8.0</version> </dependency> <!-- 添加 zkclient 依賴包 --> <dependency> <groupId>com.github.sgroschupf</groupId> <artifactId>zkclient</artifactId> <version>0.1</version> </dependency> </dependencies> <build> <finalName>dubbo_demo</finalName> <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --> <plugins> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>3.1.0</version> </plugin> <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging --> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.1</version> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>3.2.2</version> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>2.5.2</version> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>2.8.2</version> </plugin> </plugins> </pluginManagement> </build> </project>
(2) 創(chuàng)建dubbo_api moudle,在項目中定義服務(wù)接口:該接口需單獨打包,在服務(wù)提供方和消費方共享 在dubbo-api中定義服務(wù)接口DemoService,如下:
package com.test; public interface DemoService { public String sayHello(String name); }
(3)創(chuàng)建dubbo_provider moudle,然后在dubbo_provider中實現(xiàn)上述接口。為什么這里能實現(xiàn)跨moudle調(diào)用接口并且完成接口實現(xiàn),因為在provider的pom.xml文件中添加了dubbo_api作為依賴,故能引入上述接口。如圖
其中接口實現(xiàn)類DemoServiceImpl代碼如下:
import com.test.DemoService; public class DemoServiceImpl implements DemoService { public String sayHello(String name) { return "hello"+name; } }
同時在此moudle下寫一個啟動測試類,便于后面啟動provider:
import org.springframework.context.support.ClassPathXmlApplicationContext; import java.io.IOException; public class ProviderTest { public static void main(String[] args){ ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:dubbo-provider.xml"); applicationContext.start(); System.out.println("Dubbo provider start,啟動服務(wù)提供.."); try { System.in.read(); } catch (IOException e) { e.printStackTrace(); } } }
(4)創(chuàng)建dubbo_consumer moudle,然后在dubbo_consumer中寫一個啟動測試類,便于后面啟動consumer調(diào)用provider提供的服務(wù):
import com.test.DemoService; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.io.IOException; public class ConsumerTest { public static void main(String[] args){ ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:dubbo-consumer.xml"); applicationContext.start(); DemoService demoService = (DemoService) applicationContext.getBean("ddemoService"); System.out.println(demoService.sayHello(" guy")); try { System.in.read(); } catch (IOException e) { e.printStackTrace(); } } }
(5)上述代碼寫好后,好像各個moudle看起來好像沒有聯(lián)系?大家都好奇就是Dubbo是怎么實現(xiàn)服務(wù)的發(fā)布和遠程調(diào)用的吧。接下來是重點,進行provider和consumer的配置
a. 在dubbo_provider的resource中新建dubbo_provider.xml文件,實現(xiàn)dubbo中provider的配置:
首先完成應(yīng)用配置,配置當前提供方應(yīng)用名為dubbo_provider。
然后完成注冊中心配置,將Zookeeper作為注冊中心,設(shè)定其地址。
然后進行協(xié)議配置,用于配置提供服務(wù)的協(xié)議信息,協(xié)議只由provider指定,使用port="20880"作為服務(wù)提供的接口,供consumer調(diào)用。
最后進行服務(wù)配置,用于暴露一個服務(wù)接口,其絕對路徑interface="com.test.DemoService",代號為ref="demoService"
這里還需要為接口實現(xiàn)類配置一個bean,以供在provider的啟動測試類中調(diào)用bean中的方法。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://dubbo.apache.org/schema/dubbo" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"> <!-- 提供方應(yīng)用信息,用于計算依賴關(guān)系 --> <dubbo:application name="dubbo_provider" /> <!-- 使用zookeeper注冊中心暴露服務(wù)地址 --> <dubbo:registry address="zookeeper://127.0.0.1:2181" /> <!-- 用dubbo協(xié)議在20880端口暴露服務(wù) --> <dubbo:protocol name="dubbo" port="20880" /> <!-- 和本地bean一樣實現(xiàn)服務(wù) --> <bean id="demoService" class="DemoServiceImpl" /> <!-- 聲明需要暴露的服務(wù)接口 --> <dubbo:service interface="com.test.DemoService" ref="demoService" /> </beans>
b. 在dubbo_consumer的resource中新建dubbo_consumer.xml文件,實現(xiàn)dubbo中consumer的配置。
首先完成應(yīng)用配置,配置當前消費方應(yīng)用名為dubbo_consumer;
然后完成完成注冊中心配置,將Zookeeper作為注冊中心,設(shè)定其地址。消費方向注冊中心訂閱自己所需的服務(wù);
最后生成遠程服務(wù)代理,調(diào)用到了絕對路徑為interface="com.test.DemoService" 的接口,設(shè)定其代號為id="ddemoService",可以和本地bean一樣使用ddemoService、
(這里可能大家有個問題,為什么這里多了個d,因為為了和dubbo_provider.xml暴露的服務(wù)接口和bean做區(qū)別。說明消費方調(diào)用到此接口服務(wù)后,相當于自己的本地有了這個接口,所以接口名可以和provider的不一樣。相當于我在別人那里拿了一個蘋果,在我這里我就可以不叫他蘋果,我叫他梨也可以,因為這個東西是在我手上(本地),我怎么用本地都清楚,不需要外人(provider)清楚)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://dubbo.apache.org/schema/dubbo" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"> <!-- 消費方應(yīng)用名,用于計算依賴關(guān)系,不是匹配條件,不要與提供方一樣 --> <dubbo:application name="dubbo_consumer" /> <!-- 使用zookeeper注冊中心暴露發(fā)現(xiàn)服務(wù)地址 --> <dubbo:registry protocol="zookeeper" address="zookeeper://127.0.0.1:2181" /> <!-- 生成遠程服務(wù)代理,可以和本地bean一樣使用demoService --> <dubbo:reference id="ddemoService" interface="com.test.DemoService" /> </beans>
(6)項目結(jié)構(gòu)如下,具體可以在文末下載本項目demo。
依次啟動zookeeper(打開bin文件下的zkServer.cmd,并且不要關(guān)閉。如果閃退的會可以用cmd調(diào)用文件名打開)、運行dubbo-provider、運行dubbo-consumer獲得測試結(jié)果如下。
本項目遇到了一個比較奇葩的問題找了我一天,每次在運行provider和consumer的時候都會出現(xiàn)下述問題。
問題:找不到Spring命名空間處理程序。
Offending resource: class path resource [dubbo-consumer.xml]; nested exception is org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Unable to locate Spring NamespaceHandler for XML schema namespace [http://dubbo.apache.org/schema/dubbo]
Offending resource: class path resource [dubbo-consumer.xml]
就是下圖紅框的兩個地址有問題,可是這兩個地址都是可以打開的。
問題所在:最終發(fā)現(xiàn)之前有段時間dubbo被關(guān)閉了一段時間,那段時間dubbo的域名是code.alibabatech.com ,網(wǎng)上找到別人的案例里面配置的都是下面這種地址,結(jié)果發(fā)現(xiàn)這些地址都失效。按道理我現(xiàn)在程序里用最新的應(yīng)該沒錯,為什么還會報錯了。又只能繼續(xù)到處找bug。
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd ">
后來開始懷疑是不是我一開始用的版本比較舊(2.5.X);然后發(fā)現(xiàn)果然如此。問題在于: dubbo-config-spring-2.6.1.jar --> META-INF-->spring.handlers 中的配置還是之前的域名 code.alibabatech.com , 但是這個域名已經(jīng)不可用了,所以用dubbo舊版本的需要注意下這個問題(參考https://blog.csdn.net/huweijun_2012/article/details/80239803)
但是現(xiàn)在2.6.2以上都版本都不出現(xiàn)這個問題了,spring.handlers 中的配置還是之前的域名 包含舊的和新的域名,相當于可以兼容。但是由于code.alibabatech.com 域名已經(jīng)不可用,所以解決辦法只能是在pom.xml文件中修改dubbo的版本,使用至少2.6.2以上版本就不會出現(xiàn)此問題。
感謝各位的閱讀,以上就是“怎么用Dubbo+Zookeeper+Spring實現(xiàn)Demo”的內(nèi)容了,經(jīng)過本文的學(xué)習后,相信大家對怎么用Dubbo+Zookeeper+Spring實現(xiàn)Demo這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。