基於spring及zookeeper的dubbo工程搭建
一、生產者搭建
新建一個maven工程,勾選Create a simple project
Packaging方式選擇jar包的方式。
修改pom.xml文件:
<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.shaw</groupId> <artifactId>provider</artifactId> <version>1.0.0</version> <properties> <spring.version>4.3.2.RELEASE</spring.version> </properties> <dependencies> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.5.3</version> <exclusions> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.github.sgroschupf</groupId> <artifactId>zkclient</artifactId> <version>0.1</version> </dependency> <!-- spring相關 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</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-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</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-tx</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jms</artifactId> <version>${spring.version}</version> </dependency> </dependencies> </project>
按照如圖的方式,創建相關目錄文件
ProviderService.java
package com.shaw.service; public interface ProviderService { public void sayHello(); }
ProviderServiceImpl.java
package com.shaw.service.impl; import com.shaw.service.ProviderService; public class ProviderServiceImpl implements ProviderService{ @Override public void sayHello() { System.out.println("Hello!I am Provider!"); } }
TestProviderService.java
package com.shaw.service; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestProviderService { public static void main(String[] args) { ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext(new String[]{"application.xml"}); context.start(); System.out.println("生產者服務已經註冊成功!"); try { System.in.read();//讓此程序一直跑,表示一直提供服務 } catch (Exception e) { e.printStackTrace(); } } }
application.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 "> <!-- 具體的實現bean --> <bean id="providerService" class="com.shaw.service.impl.ProviderServiceImpl" /> <!-- 提供方應用信息,用於計算依賴關系 --> <dubbo:application name="provider" /> <!-- 使用zookeeper註冊中心暴露服務地址 --> <dubbo:registry address="zookeeper://127.0.0.1:2181" /> <!-- 用dubbo協議在20880端口暴露服務 --> <dubbo:protocol name="dubbo" port="29014" /> <!-- 聲明需要暴露的服務接口 --> <dubbo:service interface="com.shaw.service.ProviderService" ref="providerService" /> </beans>
按照如下步驟測試生產者:
1、啟動zookeeper
2、啟動tomcat 【1、2兩點的相關搭建可以參考博主之前的博文《zookeeper環境及dubbo-admin管理平臺搭建》】
3、右鍵TestProviderService類。
地址欄輸入:http://localhost:8080/dubbo-admin-2.5.4/ 賬戶密碼為root/root。輸入服務名稱:com.shaw.service.ProviderService
至此,生產者搭建完成並提供服務了。
二、消費者搭建
按照搭建生產者的過程重新搭建一個consumer的工程:
工程目錄如下:
TestConsumerService.java
package com.shaw.consumer; import java.io.IOException; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.shaw.service.ProviderService; public class TestConsumerService { public static void main(String[] args) { ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext(new String[]{"application.xml"}); context.start(); ProviderService testService = (ProviderService) context.getBean("testProviderService"); testService.sayHello(); try { System.in.read(); } catch (IOException e) { e.printStackTrace(); } } }
application.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="consumer" /> <!-- 使用multicast廣播註冊中心暴露發現服務地址 --> <dubbo:registry protocol="zookeeper" address="zookeeper://127.0.0.1:2181" /> <!-- 生成遠程服務代理,可以和本地bean一樣使用demoService --> <dubbo:reference id="testProviderService" interface="com.shaw.service.ProviderService" /> </beans>
消費者測試:
繼續生產者的測試步驟不同的是最後在TestConsumerService類右鍵。
控制臺輸入了生產者打印出來的信息:
同時登錄:http://localhost:8080/dubbo-admin-2.5.4/ 也可以查看相關消費者的服務信息如圖:
三、相關dubbo配置信息
3.1 dubbo常用配置
<dubbo:service/> 服務配置,用於暴露一個服務,定義服務的元信息,一個服務可以用多個協議暴露,一個服務也可以註冊到多個註冊中心。 <dubbo:service ref="demoService" interface="com.unj.dubbotest.provider.DemoService" />
<dubbo:reference/> 引用服務配置,用於創建一個遠程服務代理,一個引用可以指向多個註冊中心。 <dubbo:reference id="demoService" interface="com.unj.dubbotest.provider.DemoService" />
<dubbo:protocol/> 協議配置,用於配置提供服務的協議信息,協議由提供方指定,消費方被動接受。 <dubbo:protocol name="dubbo" port="20880" />
<dubbo:application/> 應用配置,用於配置當前應用信息,不管該應用是提供者還是消費者。 <dubbo:application name="xixi_provider" /> <dubbo:application name="hehe_consumer" />
<dubbo:registry/> 註冊中心配置,用於配置連接註冊中心相關信息。
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
<dubbo:module/> 模塊配置,用於配置當前模塊信息,可選。 <dubbo:monitor/> 監控中心配置,用於配置連接監控中心相關信息,可選。 <dubbo:provider/> 提供方的缺省值,當ProtocolConfig和ServiceConfig某屬性沒有配置時,采用此缺省值,可選。 <dubbo:consumer/> 消費方缺省配置,當ReferenceConfig某屬性沒有配置時,采用此缺省值,可選。 <dubbo:method/> 方法配置,用於ServiceConfig和ReferenceConfig指定方法級的配置信息。 <dubbo:argument/> 用於指定方法參數配置。
3.2 服務調用超時設置
上圖中以timeout為例,顯示了配置的查找順序,其它retries, loadbalance, actives也類似。
方法級優先,接口級次之,全局配置再次之。
如果級別一樣,則消費方優先,提供方次之。
其中,服務提供方配置,通過URL經由註冊中心傳遞給消費方。
建議由服務提供方設置超時,因為一個方法需要執行多長時間,服務提供方更清楚,如果一個消費方同時引用多個服務,就不需要關心每個服務的超時設置。
理論上ReferenceConfig的非服務標識配置,在ConsumerConfig,ServiceConfig, ProviderConfig均可以缺省配置。
3.3 啟動時檢查
Dubbo缺省會在啟動時檢查依賴的服務是否可用,不可用時會拋出異常,阻止Spring初始化完成,以便上線時,能及早發現問題,默認check=true。
如果你的Spring容器是懶加載的,或者通過API編程延遲引用服務,請關閉check,否則服務臨時不可用時,會拋出異常,拿到null引用,如果check=false,總是會返回引用,當服務恢復時,能自動連上。
可以通過check="false"關閉檢查,比如,測試時,有些服務不關心,或者出現了循環依賴,必須有一方先啟動。
1、關閉某個服務的啟動時檢查:(沒有提供者時報錯) <dubbo:reference interface="com.foo.BarService" check="false" /> 2、關閉所有服務的啟動時檢查:(沒有提供者時報錯) 寫在定義服務消費者一方 <dubbo:consumer check="false" /> 3、關閉註冊中心啟動時檢查:(註冊訂閱失敗時報錯) <dubbo:registry check="false" />
引用缺省是延遲初始化的,只有引用被註入到其它Bean,或被getBean()獲取,才會初始化。
如果需要饑餓加載,即沒有人引用也立即生成動態代理,可以配置:
<dubbo:reference interface="com.foo.BarService" init="true" />
3.4 訂閱
1、問題
為方便開發測試,經常會在線下共用一個所有服務可用的註冊中心,這時,如果一個正在開發中的服務提供者註冊,可能會影響消費者不能正常運行。
2、解決方案
可以讓服務提供者開發方,只訂閱服務(開發的服務可能依賴其它服務),而不註冊正在開發的服務,通過直連測試正在開發的服務。
禁用註冊配置: <dubbo:registry address="10.20.153.10:9090" register="false" /> 或者: <dubbo:registry address="10.20.153.10:9090?register=false" />
3.5 回聲測試(測試服務是否可用)
回聲測試用於檢測服務是否可用,回聲測試按照正常請求流程執行,能夠測試整個調用是否通暢,可用於監控。
所有服務自動實現EchoService接口,只需將任意服務引用強制轉型為EchoService,即可使用。
<dubbo:reference id="memberService" interface="com.xxx.MemberService" />
MemberService memberService = ctx.getBean("memberService"); // 遠程服務引用 EchoService echoService = (EchoService) memberService; // 強制轉型為EchoService String status = echoService.$echo("OK"); // 回聲測試可用性 assert(status.equals("OK"))
3.6 延遲連接
延遲連接,用於減少長連接數,當有調用發起時,再創建長連接。
只對使用長連接的dubbo協議生效。
<dubbo:protocol name="dubbo" lazy="true" />
3.7 令牌驗證
防止消費者繞過註冊中心訪問提供者,在註冊中心控制權限,以決定要不要下發令牌給消費者,註冊中心可靈活改變授權方式,而不需修改或升級提供者
1、全局設置開啟令牌驗證: <!--隨機token令牌,使用UUID生成--> <dubbo:provider interface="com.foo.BarService" token="true" /> <!--固定token令牌,相當於密碼--> <dubbo:provider interface="com.foo.BarService" token="123456" /> 2、服務級別設置開啟令牌驗證: <!--隨機token令牌,使用UUID生成--> <dubbo:service interface="com.foo.BarService" token="true" /> <!--固定token令牌,相當於密碼--> <dubbo:service interface="com.foo.BarService" token="123456" /> 3、協議級別設置開啟令牌驗證: <!--隨機token令牌,使用UUID生成--> <dubbo:protocol name="dubbo" token="true" /> <!--固定token令牌,相當於密碼--> <dubbo:protocol name="dubbo" token="123456" />
3.8 日誌適配
缺省自動查找:log4j、slf4j、jcl、jdk
可以通過以下方式配置日誌輸出策略:dubbo:application logger="log4j"/>
訪問日誌:
如果你想記錄每一次請求信息,可開啟訪問日誌,類似於apache的訪問日誌。此日誌量比較大,請註意磁盤容量。
將訪問日誌輸出到當前應用的log4j日誌: <dubbo:protocol accesslog="true" /> 將訪問日誌輸出到指定文件: <dubbo:protocol accesslog="http://10.20.160.198/wiki/display/dubbo/foo/bar.log" />
3.9 配置Dubbo緩存文件
配置方法如下:
<dubbo:registryfile=”${user.home}/output/dubbo.cache” />
註意:
文件的路徑,應用可以根據需要調整,保證這個文件不會在發布過程中被清除。如果有多個應用進程註意不要使用同一個文件,避免內容被覆蓋。
這個文件會緩存:
註冊中心的列表
服務提供者列表
有了這項配置後,當應用重啟過程中,Dubbo註冊中心不可用時則應用會從這個緩存文件讀取服務提供者列表的信息,進一步保證應用可靠性。
本文代碼下載:dubbo-provider-consumer
基於spring及zookeeper的dubbo工程搭建