(github地址:https://github.com/jiangcaijun/dubbo)html
这里输入引用文本Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以服务者与消费者的方式在dubbo上注册java
dubbo的架构图,以下(图片来源于internet)git
Provider: 暴露服务的服务提供方。 Consumer: 调用远程服务的服务消费方。 Registry: 服务注册与发现的注册中心。 Monitor: 统计服务的调用次调和调用时间的监控中心。 Container: 服务运行容器。github
调用关系说明:算法
- 服务容器负责启动,加载,运行服务提供者。
- 服务提供者在启动时,向注册中心注册本身提供的服务。
- 服务消费者在启动时,向注册中心订阅本身所需的服务。
- 注册中心返回服务提供者地址列表给消费者,若是有变动,注册中心将基于长链接推送变动数据给消费者。
- 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,若是调用失败,再选另外一台调用。
- 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
参考自:Dubbo与Zookeeper、SpringMVC整合和使用(负载均衡、容错) - 好库文摘spring
新建三个项目,均用maven进行管理,基于JDK1.7。实现点对点的生产与消费。apache
新建该项目,其pom以下api
<groupId>com.dubbo.demo</groupId> <artifactId>dubbo-api</artifactId> <version>1.0-SNAPSHOT</version>
新建一个接口,生产者将会负责该接口的实现,消费者将会调用该接口tomcat
package com.dubbo.demo; public interface IHelloWorld { public String sayHello(String name); public Object doSomeThing(); }
接着,利用maven install将其发布至本地仓库中,生产者与消费者将均会在pom.xml中引入该依赖。架构
其项目结构如图:
新建该项目,其pom以下。
<groupId>com.dubbo.demo.provider</groupId> <artifactId>dubbo-provider</artifactId> <version>1.0-SNAPSHOT</version> <properties> <slf4j.version>1.7.21</slf4j.version> </properties> <dependencies> <dependency> <groupId>com.dubbo.demo</groupId> <artifactId>dubbo-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.5.3</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${slf4j.version}</version> </dependency> </dependencies>
该生产者引入了dubbo-api (注册中心)和dubbo的依赖,同时为了方便调试,还添加了日志相关依赖。
实现dubbo-api (注册中心)的接口
package com.dubbo.demo.provider; import com.dubbo.demo.IHelloWorld; public class HelloWorldServiceImpl implements IHelloWorld { public String sayHello(String name) { return "Hello World " + name + ", I come from dubbo-api " ; } public Object doSomeThing() { return "i am doSomeThing, I come from dubbo-api " ; } }
在resource目录下新建配p2p_provider.xml,暴露IHelloWorld接口
<?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="hello_world_provider" owner="jcj" /> <!--表示咱们的服务注册到哪一个位置--> <dubbo:registry address="N/A"></dubbo:registry> <!-- 用dubbo协议在20880端口暴露服务 --> <dubbo:protocol name="dubbo" port="20880"></dubbo:protocol> <!-- 具体的实现bean --> <bean id="helloService" class="com.dubbo.demo.provider.HelloWorldServiceImpl" /> <!-- 声明须要暴露的服务接口 --> <dubbo:service interface="com.dubbo.demo.IHelloWorld" ref="helloService" /> </beans>
同时新建一个dubboTest方法,用来启动dubbo-provider (生产者)。
public class dubboTest { public static void main(String []args) throws IOException { ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext(new String("provider.xml")); classPathXmlApplicationContext.start(); System.in.read(); } }
其项目结构如图(图中红圈表明其引入了dubbo-api(注册中心)的依赖):
其pom和dubbo-provider (生产者)相似,均须要引入dubbo-api (注册中心)和dubbo的依赖。
在resource目录下新建p2p_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="hello_world_provider" owner="jcj" /> <!--表示咱们的服务注册到哪一个位置--> <dubbo:registry address="N/A"></dubbo:registry> <!-- 声明须要暴露的服务接口 --> <dubbo:reference interface="com.dubbo.demo.IHelloWorld" url="dubbo://127.0.0.1:20880/com.dubbo.demo.IHelloWorld" id="helloService"></dubbo:reference> </beans>
与dubbo-provider (生产者)的p2p_provider.xml比较,均声明须要暴露的服务接口,即暴露了dubbo-api(注册中心)的接口方法。
新建一个测试方法dubboConsumerTest
import com.dubbo.demo.IHelloWorld; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.io.IOException; public class dubboConsumerTest { public static void main(String []args) throws IOException { ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext(new String("p2p_consumer.xml")); IHelloWorld iHelloWorld = (IHelloWorld)classPathXmlApplicationContext.getBean("helloService"); String result = iHelloWorld.sayHello("哈哈哈"); System.out.println("dubboConsumerTest.main: " + result); Object object = iHelloWorld.doSomeThing(); System.out.println("dubboConsumerTest.main: " + object.toString()); } }
其项目结构如图(图中红圈表明其引入了dubbo-api(注册中心)的依赖):
先启动dubbo-provider (生产者)的dubboTest方法,此时服务开始提供; 此时生产者控制台输出以下:
[ com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol ] - [ INFO ] [DUBBO] disconected from /192.168.58.1:54584,url:dubbo://192.168.58.1:20880/com.dubbo.demo.IHelloWorld?anyhost=true&application=hello_world_provider&channel.readonly.sent=true&codec=dubbo&dubbo=2.5.3&heartbeat=60000&interface=com.dubbo.demo.IHelloWorld&methods=doSomeThing,sayHello&owner=jcj&pid=15740&revision=1.0-SNAPSHOT&side=provider×tamp=1498555464131, dubbo version: 2.5.3, current host: 127.0.0.1
再启动dubbo-consumer (消费者)的dubboConsumerTest,尝试调用该方法。 此时消费者控制台输出:
Refer dubbo service com.dubbo.demo.IHelloWorld from url dubbo://127.0.0.1:20880/com.dubbo.demo.IHelloWorld?application=hello_world_provider&dubbo=2.5.3&interface=com.dubbo.demo.IHelloWorld&methods=doSomeThing,sayHello&owner=jcj&pid=8296&revision=1.0-SNAPSHOT&side=consumer×tamp=1498555502597, dubbo version: 2.5.3, current host: 192.168.58.1 dubboConsumerTest.main: Hello World 哈哈哈, I come from dubbo-api dubboConsumerTest.main: i am doSomeThing, I come from dubbo-api
证实测试经过。
在pom.xml中添加zookeeper相关依赖,dubbo-consumer (消费者)也须要添加
<!--zookeeper apache--> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.6</version> </dependency> <!--zkclient--> <dependency> <groupId>com.github.sgroschupf</groupId> <artifactId>zkclient</artifactId> <version>0.1</version> </dependency>
在resource目录下新建zk_provider.xml,链接zookeeper
<!-- 提供方应用信息,用于计算依赖关系 --> <dubbo:application name="hello_world_provider" owner="jcj" /> <!-- 使用zookeeper注册中心暴露服务地址--> <dubbo:registry address="zookeeper://182.254.xx.xx:2181" check="false" subscribe="false" register="" /> <!-- 用dubbo协议在20880端口暴露服务 --> <dubbo:protocol name="dubbo" port="20880"></dubbo:protocol> <!-- 声明须要暴露的服务接口 --> <dubbo:service interface="com.dubbo.demo.IHelloWorld" ref="helloService" /> <!-- 具体的实现bean --> <bean id="helloService" class="com.dubbo.demo.provider.HelloWorldServiceImpl" />
dubbo:registry 标签一些属性的说明:
dubbo:service标签的一些属性说明:
以上,引用自:Dubbo与Zookeeper、SpringMVC整合和使用(负载均衡、容错) - 好库文摘
在resource目录下新建zk_consumer.xml,链接zookeeper
<!-- 提供方应用信息,用于计算依赖关系 --> <dubbo:application name="hello_world_provider" owner="jcj" /> <dubbo:registry address="zookeeper://182.254.xx.xx:2181" /> <!-- 生成远程服务代理,能够和本地bean同样使用其接口 --> <dubbo:reference id="helloService" interface="com.dubbo.demo.IHelloWorld" />
运行各相应的xml文件,注意生产者与消费者的前后启动顺序,能够在消费者的控制台看到相应的预期输出,测试经过。
当zookeeper注册中心连不上时dubbo的线程时,因为ZKClient默认的超时时间是Integer.MAX_VALUE,几乎等于无限等待。由于系统有一些定时任务会比较频繁地开启新线程链接dubbo,因此致使的结果是tomcat一下子线程池就满了,其它的不依赖dubbo的功能也被阻塞没法使用。
解决方案:dubbo链接zookeeper注册中心由于断网致使线程无限等待问题
dubbo:是管理中间层的工具,在业务层到数据仓库间有很是多服务的接入和服务提供者须要调度,dubbo提供一个框架解决这个问题。
注意这里的dubbo只是一个框架,至于你架子上放什么是彻底取决于你的,就像一个汽车骨架,你须要配你的轮子引擎。这个框架中要完成调度必需要有一个分布式的注册中心,储存全部服务的元数据,你能够用zk,也能够用别的,例如: