1.在企業開發過程當中咱們發現url愈來愈多,各個節點之間維護起來很困難,依賴關係很模糊,而且每一個節點的性能、訪問量、響應時間咱們沒法評估,這個時候就能夠引入dubbo來治理。java
在項目中新建一個新建一個名爲sumei-order 的pom父工程,git
而後在父工程上新建兩個子工程 一 sumei-order-api 用於向外部暴露接口、sumei-order-provider 用於提供api中接口實現,github
工程結構以下web
sumei-order-api pom文件spring
<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"> <parent> <artifactId>sumei-order</artifactId> <groupId>com.sumei</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>sumei-order-api</artifactId> <packaging>jar</packaging> <name>sumei-order-api</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> </dependency> </dependencies> </project>
suimei-order-provdier apache
<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"> <parent> <artifactId>sumei-order</artifactId> <groupId>com.sumei</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>sumei-order-provider</artifactId> <packaging>jar</packaging> <name>sumei-order-provider</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>com.sumei</groupId> <artifactId>sumei-order-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.5.3</version> </dependency> <dependency> <groupId>com.github.sgroschupf</groupId> <artifactId>zkclient</artifactId> <version>0.1</version> </dependency> <dependency> <groupId>com.caucho</groupId> <artifactId>hessian</artifactId> <version>4.0.38</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> </dependency> <dependency> <groupId>org.mortbay.jetty</groupId> <artifactId>jetty</artifactId> <version>6.1.26</version> </dependency> </dependencies> </project>
在sumei-api-order 新建兩個實體類api
一個爲入參(DoRequest) 一個爲出參(DoResponse)架構
package com.sumei.order.request; import java.io.Serializable; public class DoRequest implements Serializable { private static final long serialVersionUID = -101933701419873281L; private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
package com.sumei.order.reponse; import java.io.Serializable; public class DoResponse implements Serializable { private static final long serialVersionUID = 1048196133759063700L; private String code; private Object data; private String msg; public String getCode() { return code; } public void setCode(String code) { this.code = code; } public Object getData() { return data; } public void setData(Object data) { this.data = data; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } }
定義個接口app
package com.sumei.order; import com.sumei.order.reponse.DoResponse; import com.sumei.order.request.DoRequest; public interface OrderService { DoResponse doOrder(DoRequest doRequest); }
在sumei-order-provider 中提供接口實現負載均衡
package com.sumei.order.impl; import com.sumei.order.OrderService; import com.sumei.order.reponse.DoResponse; import com.sumei.order.request.DoRequest; public class OrderServiceImpl implements OrderService { public DoResponse doOrder(DoRequest doRequest) { System.out.println("有人進來了"); DoResponse doResponse=new DoResponse(); doResponse.setCode("200"); doResponse.setData("00000000000000000"); doResponse.setMsg(doRequest.getName()); return doResponse; } }
在sumei-order-provider src目錄下面 新建一個
resources 文件夾,在resources下建一個META-INF文件夾,再在META-INF 新建一個spring 文件夾
在spring文件夾中新建一個 xml文件
在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"> <!-- name爲分佈式中惟一的應用名稱,owner 爲服務的管理者--> <dubbo:application name="order-provider" owner="piaomj" /> <!-- <dubbo:registry protocol="zookeeper" address="192.168.31.100,192.168.31.101,192.168.31.102" />--> <!-- address 爲服務的註冊地址--> <dubbo:registry address="N/A" /> <!--服務默認使用的協議--> <dubbo:protocol port="20880" name="dubbo"/> <!--<dubbo:protocol name="hessian" port="8090" server="jetty" />--> <!-- 聲明一個bean--> <bean class="com.sumei.order.impl.OrderServiceImpl" id="orderService" /> <!--對外部暴露的接口--> <dubbo:service interface="com.sumei.order.OrderService" ref="orderService" /> </beans>
在resources 中加入 log4j.properties 配置文件以下
log4j.rootLogger=info, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
這個時候用main方法啓動dubbo
package com.sumei.order; import com.alibaba.dubbo.container.Main; /** * Hello world! * */ public class App { public static void main( String[] args ){ Main.main(args); } }
會看到
日誌中有Export dubbo service com.sumei.order.OrderService to url dubbo://192.168.31.134:20880/com.sumei.order.OrderService?
其中dubbo://192.168.31.134:20880/com.sumei.order.OrderService 是消費端的直連地址
新建一個名爲suemi-user消費者
pom文件
<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.sumei</groupId> <artifactId>sumei-user</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>sumei-user</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.5.3</version> </dependency> <dependency> <groupId>com.caucho</groupId> <artifactId>hessian</artifactId> <version>4.0.38</version> </dependency> <dependency> <groupId>com.github.sgroschupf</groupId> <artifactId>zkclient</artifactId> <version>0.1</version> </dependency> </dependencies> </project>
user項目要填入api的依賴,爲了途方便直接把api打成jar包直接加入到user依賴
order-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="order-provider" owner="piaomj"/> <dubbo:registry address="N/A" /> <!--<dubbo:protocol name="hessian" port="8090" />--> <dubbo:reference id="orderService" interface="com.sumei.order.OrderService" url="dubbo://192.168.31.134:20880/com.sumei.order.OrderService"/> </beans>
用dubbo調用遠程服務
package com.sumei; import com.sumei.order.OrderService; import com.sumei.order.reponse.DoResponse; import com.sumei.order.request.DoRequest; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.io.IOException; /** * Hello world! * */ public class App { public static void main( String[] args ) throws IOException { ClassPathXmlApplicationContext classPathXmlApplicationContext=new ClassPathXmlApplicationContext("classpath:order-consumer.xml"); OrderService orderService = (OrderService) classPathXmlApplicationContext.getBean("orderService"); DoRequest doRequest=new DoRequest(); doRequest.setName("ppp" ); DoResponse doResponse = orderService.doOrder(doRequest); System.out.println("狀態碼:"+doResponse.getCode()); System.out.println("狀態數據:"+doResponse.getData()); System.in.read(); } }
輸出結果:
調用端輸出結果:
服務端輸出結果:
dubbo 不採用zk的搭建成功
2、使用中的問題
1.註冊中心
在配置中將
address="N/A" 不採用註冊中心地址
<dubbo:registry address="N/A" />
改成
<dubbo:registry protocol="zookeeper" address="192.168.31.100,192.168.31.101,192.168.31.102" />
protocol="zookeeper" 採用的註冊中心爲zookeeper,
address="192.168.31.100,192.168.31.101,192.168.31.102", 表示註冊中心的的地址
2.多個註冊中心
<dubbo:registry id="zk1" protocol="zookeeper" version="1.0" address="192.168.31.100,192.168.31.101,192.168.31.102" /> <dubbo:registry id="zk2" protocol="zookeeper" version="1.0" address="192.168.31.100,192.168.31.101,192.168.31.102" />
好比 一個能夠用於測試版本、一個能夠用於開發版本
<dubbo:registry id="zk1" protocol="zookeeper" version="1.0" address="192.168.31.100,192.168.31.101,192.168.31.102" />
3.多個版本
緣由因爲業務更新,咱們須要從新對業務進行梳理,可是還不能影響老的用戶,這個時候咱們須要進行多個版本的實現
咱們能夠對api中的接口 新加入一個實現類
package com.sumei.order.impl; import com.sumei.order.OrderService; import com.sumei.order.reponse.DoResponse; import com.sumei.order.request.DoRequest; public class Order2ServiceImpl implements OrderService { public DoResponse doOrder(DoRequest doRequest) { System.out.println("有人進來了"); DoResponse doResponse=new DoResponse(); doResponse.setCode("200"); doResponse.setData("11111111111111"); doResponse.setMsg(doRequest.getName()); return doResponse; } }
在消費端調用:
<?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="order-consumer" owner="piaomj"/> <dubbo:registry protocol="zookeeper" address="192.168.31.100,192.168.31.101,192.168.31.102" /> <!--<dubbo:registry address="N/A" />--> <!--<dubbo:protocol name="hessian" port="8090" />--> <dubbo:reference id="orderService" interface="com.sumei.order.OrderService" version="0.0.1"/> </beans>
package com.sumei; import com.sumei.order.OrderService; import com.sumei.order.reponse.DoResponse; import com.sumei.order.request.DoRequest; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.io.IOException; /** * Hello world! * */ public class App { public static void main( String[] args ) throws IOException { ClassPathXmlApplicationContext classPathXmlApplicationContext=new ClassPathXmlApplicationContext("classpath:order-consumer.xml"); OrderService orderService = (OrderService) classPathXmlApplicationContext.getBean("orderService"); DoRequest doRequest=new DoRequest(); doRequest.setName("ppp" ); DoResponse doResponse = orderService.doOrder(doRequest); System.out.println("狀態碼:"+doResponse.getCode()); System.out.println("狀態數據:"+doResponse.getData()); System.in.read(); } }
配置
<dubbo:reference id="orderService" interface="com.sumei.order.OrderService" version="0.0.1"/>
輸出:
狀態碼:200
狀態數據:00000000000000000
配置:
<dubbo:reference id="orderService" interface="com.sumei.order.OrderService" version="0.0.2"/>
輸出
狀態碼:200
狀態數據:11111111111111
4.多協議
dubbo支持 dubbo、RMI、hessian、webservice、http、Thrift 協議
dubbo、RMI 底層爲tcp
hessian、webservice、http、Thrift 底層爲http
默認是dubbo協議,咱們還能夠添加個hessian協議
服務提供者配置以下
<?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"> <!-- name爲分佈式中惟一的應用名稱,owner 爲服務的管理者--> <!-- --> <dubbo:application name="order-provider" owner="piaomj" /> <!-- <dubbo:registry protocol="zookeeper" address="192.168.31.100,192.168.31.101,192.168.31.102" />--> <dubbo:registry id="zk1" protocol="zookeeper" version="1.0" address="192.168.31.100,192.168.31.101,192.168.31.102" /> <dubbo:registry id="zk2" protocol="zookeeper" version="1.0" address="192.168.31.100,192.168.31.101,192.168.31.102" /> <!-- address 爲服務的註冊地址--> <!--<dubbo:registry address="N/A" />--> <!--服務默認使用的協議--> <dubbo:protocol port="20880" name="dubbo"/> <dubbo:protocol name="hessian" port="8090" server="jetty" /> <!-- 聲明一個bean--> <bean class="com.sumei.order.impl.OrderServiceImpl" id="orderService" /> <bean class="com.sumei.order.impl.Order2ServiceImpl" id="order2Service" /> <!--對外部暴露的接口--> <dubbo:service interface="com.sumei.order.OrderService" ref="orderService" registry="zk1" protocol="hessian" version="0.0.1" /> <dubbo:service interface="com.sumei.order.OrderService" ref="order2Service" registry="zk1" version="0.0.2" /> </beans>
咱們制定 id=「orderService」 爲hessian協議
啓動的時候咱們會看見
hessian://192.168.31.134:8090/com.sumei.order.OrderService2?anyhost=true&application=order-provider&dubbo=2.5.
咱們在調用的的時候能夠制定協議
<dubbo:reference id="orderService" interface="com.sumei.order.OrderService" protocol="hessian" version="0.0.1"/>
5.解決循環依賴
場景
這個場景服務怎麼也起不來,緣由是消費者在啓動的過程當中要檢查服務提供者有沒有用啓動
A 啓動的時候,去檢車b有沒有啓動,b啓動的時候去檢查A有沒有啓動,這樣服務就會起不來了,要起來還須要一個配置
這個是在消費端的配置
<dubbo:reference check="false" id="orderService" interface="com.sumei.order.OrderService" protocol="hessian" version="0.0.1"/>
check="false" 表示啓動的時候不進行檢查
6.只訂閱不註冊
<dubbo:registry id="zk1" protocol="zookeeper" version="1.0" address="192.168.31.100,192.168.31.101,192.168.31.102" register="false" />
表示當前服務只調用其餘服務並不會將本地的服務祖冊到其註冊中心上
7.只註冊不訂閱
表示當前只提供服務
<dubbo:registry subscribe="false"/>
8.負載均衡
將sumei-order 項目複製一份,而後在用idea開個新窗口打開
而後改下dubbo協議的端口
<!--服務默認使用的協議--> <dubbo:protocol port="20881" name="dubbo"/>
而後咱們用user調用
package com.sumei.order; import com.alibaba.dubbo.container.Main; /** * Hello world! * */ public class App { public static void main( String[] args ){ Main.main(args); } }
dubbo 可自行進行負載均衡,默認的採用。能夠自行擴展負載均衡策略。
默認採用,Random LoadBalance 隨機、按權重設置隨機機率。
9.異步調用
消費端
<dubbo:reference async="true" id="orderService" interface="com.sumei.order.OrderService" version="0.0.1"/>
調用
*/ public class App { public static void main( String[] args ) throws IOException { ClassPathXmlApplicationContext classPathXmlApplicationContext=new ClassPathXmlApplicationContext("classpath:order-consumer.xml"); OrderService orderService = (OrderService) classPathXmlApplicationContext.getBean("orderService"); DoRequest doRequest=new DoRequest(); DoResponse doResponse = orderService.doOrder(doRequest); Future<DoResponse> future = RpcContext.getContext().getFuture(); doRequest.setName("aaa" ); try { System.out.println(future.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } }