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