dubbo的入門使用總結

1.在企業開發過程中我們發現url越來越多,各個節點之間維護起來很困難,依賴關係很模糊,並且每個節點的性能、訪問量、響應時間我們無法評估,這個時候就可以引入dubbo來治理。

在項目中新建一個新建一個名為sumei-order 的pom父工程,

然後在父工程上新建兩個子工程 一 sumei-order-api 用於向外部暴露接口、sumei-order-provider 用於提供api中接口實現,

工程結構如下

sumei-order-api pom文件

<project><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>http://maven.apache.org<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

<project><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>http://maven.apache.org<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 新建兩個實體類

一個為入參(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;}}

定義個接口

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文件中進行對生產者的配置

<beans><application><registry><protocol><bean><service>/<beans>

在resources 中加入 log4j.properties 配置文件如下

log4j.rootLogger=info, stdoutlog4j.appender.stdout=org.apache.log4j.ConsoleAppenderlog4j.appender.stdout.layout=org.apache.log4j.PatternLayoutlog4j.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><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>http://maven.apache.org<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 配置

<beans><application><registry><reference>/<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的搭建成功

二、使用中的問題

1.註冊中心

在配置中將

address="N/A" 不採用註冊中心地址

<registry>

改為

<registry>

protocol="zookeeper" 採用的註冊中心為zookeeper,

address="192.168.31.100,192.168.31.101,192.168.31.102", 表示註冊中心的的地址

2.多個註冊中心

<registry><registry>

比如 一個可以用於測試版本、一個可以用於開發版本

<registry>

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;}}

在消費端調用:

<beans><application><registry><reference>/<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();}}

配置

<reference>

輸出:

狀態碼:200

狀態數據:00000000000000000

配置:

<reference>

輸出

狀態碼:200

狀態數據:11111111111111

4.多協議

dubbo支持 dubbo、RMI、hessian、webservice、http、Thrift 協議

dubbo、RMI 底層為tcp

hessian、webservice、http、Thrift 底層為http

默認是dubbo協議,我們還可以添加個hessian協議

服務提供者配置如下

<beans><application><registry><registry><protocol><protocol><bean><bean> <service> <service>/<beans>

我們制定 id=“orderService” 為hessian協議

啟動的時候我們會看見

hessian://192.168.31.134:8090/com.sumei.order.OrderService2?anyhost=true&application=order-provider&dubbo=2.5.

我們在調用的的時候可以制定協議

<reference>

5.解決循環依賴

場景

這個場景服務怎麼也起不來,原因是消費者在啟動的過程中要檢查服務提供者有沒有用啟動

A 啟動的時候,去檢車b有沒有啟動,b啟動的時候去檢查A有沒有啟動,這樣服務就會起不來了,要起來還需要一個配置

這個是在消費端的配置

<reference>

check="false" 表示啟動的時候不進行檢查

6.只訂閱不註冊

<registry>

表示當前服務只調用其他服務並不會將本地的服務祖冊到其註冊中心上

7.只註冊不訂閱

表示當前只提供服務

<registry>

8.負載均衡

將sumei-order 項目複製一份,然後在用idea開個新窗口打開

然後改下dubbo協議的端口

<protocol>

然後我們用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.異步調用

消費端

<reference>

調用

*/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();}}}/<doresponse>

tencent://AddContact/?fromId=50&fromSubId=1&subcmd=all&uin=2284732365