【Dubbo分布式服务框架】2.基于配置的服务提供者和消费者
一个使用Dubbo的系统架构图如下:可分为以下几个角色:(1)Provider:暴露服务的服务提供方。(2)Consumer:调用远程服务的服务消费方。(3)Registry:服务注册与发现的注册中心。(4)Monitor:统计服务的调用次调和调用时间的监控中心。(5)Container:服务运行容器。其中上面的调用关系为:0.服务容器负责启动,加载,运行服
一个使用Dubbo的系统架构图如下:
可分为以下几个角色:
(1)Provider:暴露服务的服务提供方。
(2)Consumer:调用远程服务的服务消费方。
(3)Registry:服务注册与发现的注册中心。
(4)Monitor:统计服务的调用次调和调用时间的监控中心。
(5)Container:服务运行容器。
其中上面的调用关系为:
0.服务容器负责启动,加载,运行服务提供者。
1.服务提供者在启动时,向注册中心注册自己提供的服务。
2.服务消费者在启动时,向注册中心订阅自己所需的服务。
3.注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
4.服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
5.服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
其实上面的整个流程我们可以转换成日常生活的一个场景:Provider是冷饮提供商,Consumer是购买冷饮的零售商,Registry是冷饮市场的中介,Monitor是工商管理局,而Container是存放冷饮的冷冻库。所以上面的调用关系可以转换为:
0.冷冻库Container用于存放冷饮提供商Provider的产品---冷饮。
1.冷饮提供商Provider在拥有冷冻库的商品后,需要在中介备案,打开销售渠道。
2.冷饮的零售商Consumer需要向中介联系,告知需要的冷饮种类,以帮助寻找合适的厂家订购货源。
3.冷饮市场的中介Registry会将各大冷饮厂商提供的商品列表给冷饮的零售商Consumer看,如果有变动,中介会实时联系厂商。
4.冷饮的零售商Consumer会通过中介Registry提供的厂商列表,选取拿货地最近,路程最短,竞争者最少的厂商购买商品,如果订购失败,就选择其它合适厂商继续订购。
5.冷饮提供商Provider和冷饮的零售商Consumer的每次商业运作,都要告知工商管理局Monitor,有利于政府的监管。
这样解释,大家对于整个Dubbo的架构流程大致有一个思路了吧?我们下面动手去实现Dubbo的基于配置的服务提供者和消费者。
一、服务提供者
首先我们在MyEclipse中创建一个服务提供者的WebProject,名为Dubbo-Web-Provider:



然后我们的Dubbo可以只依赖JDK,不依赖于任何三方库运行,只需配置使用JDK相关实现策略。
我们需要添加的jar包有:
com.alibaba.dubbo.jar(dubbo官方jar包)
log4j.jar(日志输出依赖jar包)
org.javassist.jar(字节码生成jar包)
org.springframework.spring.jar(Spring依赖jar包)
commons-logging.jar(日志输出依赖jar包)
org.jboss.netty.jar(网络传输jar包)
我们将这些jar包放置在Web工程的lib文件夹下,然后“Add To Build Path”添加到编译环境中。
然后我们创建一个原文件夹config,用于存放Spring的配置文件,然后在该文件夹下创建provider.xml配置文件:
在provider.xml配置文件中添加Spring以及Dubbo的Schema扩展:
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
</beans>
然后我们分别定义一个Service服务的接口和实现:
服务接口:
package cn.com.dubbo.service;
public interface SortService {
//升序排序
int[] ascendingSort(int[] arrays);
}
服务实现:
package cn.com.dubbo.service.impl;
import cn.com.dubbo.service.SortService;
public class SortServiceImpl implements SortService{
@Override
public int[] ascendingSort(int[] arrays) {
int temp=0;
//冒泡升序排序
for (int i = 0; i < arrays.length-1; i++) {
for (int j = i+1; j < arrays.length; j++) {
if(arrays[i]>arrays[j]){
temp=arrays[i];
arrays[i]=arrays[j];
arrays[j]=temp;
}
}
}
return arrays;
}
}
该服务提供了一个对int数组升序排序的功能。
我们前面提到过有一个Registry,即服务注册与发现的注册中心,这个注册中心就相当于冷饮厂商和冷饮零售商之间的中介,服务提供者在其上面注册服务,服务消费者在其上面获取服务。
我们这里使用的注册中心为Zookeeper,我们先去使用它,关于它的详细介绍,我会在后面的章节中详细为大家讲解。
下载Zookeeper:
http://www.apache.org/dyn/closer.cgi/zookeeper/
获得压缩文件之后,解压在合适的硬盘中:
修改conf修改zoo_sample.cfg内容,然后修改文件名为zoo.cfg
内容如下:
# The number of milliseconds of each tick 心跳间隔 毫秒每次
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting anacknowledgement
syncLimit=5
# the directory where the snapshot isstored. //镜像数据位置
dataDir=D:\\data\\zookeeper
#日志位置
dataLogDir=D:\\logs\\zookeeper
# the port at which the clients willconnect 客户端连接的端口
clientPort=2181
注意:dataDir 和 dataLogDir 目录不会自动创建,得手动创建才能启动。
然后双击bin文件夹下的zkServer.cmd启动注册中心服务:
启动客户端zkCli.cmd运行查看一下:
这个时候zookeeper已经安装并启动成功了。
这里Zookeeper是在我们本地搭建了一个注册中心,默认端口为2181,即提供的注册中心的具体路劲为:
zookeeper://127.0.0.1:2181
别忘记在工程中添加Zookeeper的jar包:
接下来是Dubbo的配置:
由于Dubbo采用全Spring配置方式,透明化接入应用,对应用没有任何API侵入,只需用Spring加载Dubbo的配置即可,Dubbo基于Spring的Schema扩展进行加载。所以我们对于Dubbo的配置在spring的bean配置文件中即可以实现。
下面我们就在provider.xml中添加Dubbo的配置:
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<!-- 提供方应用信息,用于计算依赖关系 -->
<dubbo:application name="arrays-sort-app" />
<!-- 使用zookeeper注册中心暴露服务地址 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880" />
<!-- 声明需要暴露的服务接口 -->
<dubbo:service interface="cn.com.dubbo.service.SortService" ref="sortService" />
<!-- 和本地bean一样实现服务 -->
<bean id="sortService" class="cn.com.dubbo.service.impl.SortServiceImpl" />
</beans>
如果关于dubbo的配置打叉,出现下面类似的错误:
– cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element ‘dubbo:application’.
则需要添加dubbo.xsd文件声明,具体做法如下:
(1)下载一个dubbo.xsd文件,选择windows->preferrence->xml->xmlcatalog
(2)add->catalog entry ->file system 选择刚刚下载的文件路径
(3)修改key值和配置文件的http://code.alibabatech.com/schema/dubbo/dubbo.xsd相同
(4)保存,在xml文件右键validate,就可以解决了。
注:dubbo.jar解压后也可以找到dubbo.xsd
然后我们编写一个启动类来启动Spring配置:
package cn.com.dubbo.run;
import java.io.IOException;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Provider {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {"provider.xml"});
//远程provider调用
/*ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {"http://192.168.1.102/wiki/display/dubbo/provider.xml"});*/
context.start();
System.in.read(); // 按任意键退出
}
}
至此,我们的服务提供者编写完毕。
二、服务消费者
在MyEclipse中创建一个服务提供者的WebProject,名为Dubbo-Web-Consumer,添加的依赖与服务提供者一样:
我们在消费者的配置文件中添加以下配置:
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
<dubbo:application name="consumer-of-arraysSort-app" />
<!-- 使用zookeeper注册中心暴露发现服务地址 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
<!-- 生成远程服务代理,可以和本地bean一样使用sortService -->
<dubbo:reference id="sortService" interface="cn.com.dubbo.service.SortService" />
</beans>
然后在消费者的启动类Consumer.java中获取配置,然后调用远程服务:
package cn.com.dubbo.run;
import java.io.IOException;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import cn.com.dubbo.service.SortService;
public class Consumer {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {"consumer.xml"});
//远程consumer调用
/*ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {"http://192.168.1.102/wiki/display/dubbo/consumer.xml"});*/
context.start();
SortService sortService = (SortService)context.getBean("sortService"); // 获取远程服务代理
int [] arrays = {234,1,45,22,123};
System.out.println("排序前:");
for (int i = 0; i < arrays.length; i++) {
System.out.println("arrays["+i+"]="+arrays[i]);
}
arrays = sortService.ascendingSort(arrays); // 执行远程方法
//显示调用结果
System.out.println("排序后:");
for (int i = 0; i < arrays.length; i++) {
System.out.println("arrays["+i+"]="+arrays[i]);
}
}
}
注意:这里为了简化工程,我们没有使用Maven去关联服务提供方和消费者,所以我们在消费者的src中创建了sortService的接口:
实际上当我们使用了Maven时,通过Maven依赖就可以获取接口信息了。后面我们会给大家介绍使用Maven实现的工程。
至此我们的消费者也编写完毕。
三、测试
首先运行服务提供者的启动类Provider,此时服务提供者已经将服务注册到注册中心Zookeeper中了:
然后启动服务的消费者,此时消费者会在注册中心寻找需要的名为“sortService”服务实现,然后引入,执行相关的服务逻辑,最终的执行结果为:
我们上面实现了一个最简单的服务提供者和服务消费者,应该为大家以后深入学习Dubbo提供了一个思路。
转载请注明出处:http://blog.csdn.net/acmman/article/details/73036356
更多推荐


所有评论(0)