最近公司项目有用到Dubbo,自己参考Dubbo官网以及网上很多资料,终于对Dubbo有所理解。虽然阿里已经停止对Dubbo的更新(据说是与内部另外一个叫hsf框架功能冲突了),但自己还很感兴趣。以下是自己在学习Dubbo时参考官网的一个demo,其实官网的demo中Dubbo服务注册中心是使用multicast广播,无奈自己的网络不支持multicast广播,所以又顺便学习了一下Zookeeper,用Zookeeper作为注册中心,自己尝试了在Linux系统上与Window下安装了Zookeeper,本例使用了本机(即Windows)Zookeeper作为注册中心,当然也尝试了Linux下的Zookeeper注册中心。文末有附带源码链接。
本文参考自Duboo官网,有关Dubbo的介绍也可参考Duboo官网:http://dubbo.io/Home-zh.htm
Zookeeper的安装可参考另外一篇博客:http://blog.csdn.net/beauxie/article/details/74938690
1.JDK:1.7.0_79;
2.Dubbo:2.5.3;
3.Zookeeper:3.4.6;
4.Spring:3.2.3;
5.开发工具:Eclipse
6.项目构建方式:MAVEN
确保Zookeeper已正常启动。没有采用项目集的形式,而是将提供者和消费者作为两个单独的项目分开。
1.新建一个名为dubbo-demo-provider的java普通maven项目,并导入Eclipse中,结构如下:
项目最终结构如下所示:
2.加入依赖:首先在pom.xml文件中加入Spring、Dubbo等依赖,如下:
<!-- Spring配置 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>3.2.3.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>3.2.3.RELEASE</version> </dependency> <!-- dubbo --> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.5.3</version> <exclusions> <exclusion> <artifactId>spring</artifactId> <groupId>org.springframework</groupId> </exclusion> </exclusions> </dependency> <!-- Zookeeper --> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.6</version> <type>pom</type> </dependency> <dependency> <groupId>com.101tec</groupId> <artifactId>zkclient</artifactId> <version>0.4</version> </dependency>
2.定义服务接口:在service包下新建一个名为DemoService的接口文件,该接口即为暴露出来的服务接口,里面有一个sayHello()方法,代码如下:
package com.beauxie.service; public interface DemoService { String sayHello(String name); } 3.实现服务接口 : DemoService接口的实现类 DemoServiceImpl代码:
package com.beauxie.provider.impl; import java.text.SimpleDateFormat; import java.util.Date; import com.alibaba.dubbo.rpc.RpcContext; import com.beauxie.service.DemoService; public class DemoServiceImpl implements DemoService { public String sayHello(String name) { System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] Hello " + name + ", request from consumer: " + RpcContext.getContext().getRemoteAddress()); return "Hello " + name + ", response form provider: " + RpcContext.getContext().getLocalAddress(); } } 4.配置文件中配置:在src/main/resources目录下新建一个META-INF,再在 META-INF下新建一个spring文件夹,最后在spring下新建一个dubbo-demo-provider.xml文件,dubbo-demo-provider.xml代码如下:
<?xml version="1.0" encoding="UTF-8"?> <!-- - Copyright 1999-2011 Alibaba Group. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --> <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-2.5.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <!-- 提供方应用信息,用于计算依赖关系 --> <dubbo:application name="hello-world-app" /> <!-- 使用multicast广播注册中心暴露服务地址 --> <!-- <dubbo:registry address="multicast://224.5.6.7:1234" /> --> <!-- 使用Linux服务器上的Zookeeper --> <!-- <dubbo:registry address="zookeeper://192.168.125.100:2181" /> --> <!-- 使用本机的Zookeeper(Windows)--> <dubbo:registry address="zookeeper://127.0.0.1:2181" /> <!-- 用dubbo协议在20880端口暴露服务 --> <dubbo:protocol name="dubbo" port="20880" /> <!-- 声明需要暴露的服务接口 --> <dubbo:service interface="com.beauxie.service.DemoService" ref="demoService" /> <!-- 和本地bean一样实现服务 --> <bean id="demoService" class="com.beauxie.provider.impl.DemoServiceImpl" /> </beans> 5.定义个启动类:ProviderMain是一个启动类,里面包含了一个main函数,代码如下:
package com.beauxie.provider.main; import java.io.IOException; import org.springframework.context.support.ClassPathXmlApplicationContext; public class ProviderMain { public static void main(String[] args) throws IOException { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"/META-INF/spring/dubbo-demo-provider.xml"}); context.start(); System.out.println("Service started!"); System.out.println("按任意键退出..."); System.in.read(); // 按任意键退出 } } 6.运行 ProviderMain类,可以看见控制类输出:
、
至此提供者已完成,接下来是消费者。
1.新建一个名为dubbo-demo-consumer的java普通maven项目,并导入Eclipse中,结构如下:
最终项目结构如下图所示:
2.将提供者的服务接口DemoService复制过来,注意路径(全路径)保持一致,接口名一致、方法名一致,代码如下:
package com.beauxie.service; public interface DemoService { String sayHello(String name); } 3.配置文件中配置:在src/main/resources目录下新建一个META-INF,再在 META-INF下新建一个spring文件夹,最后在spring下新建一个dubbo-demo-consumer.xml文件,dubbo-demo-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-2.5.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 --> <dubbo:application name="consumer-of-helloworld-app" /> <!-- 使用multicast广播注册中心暴露发现服务地址 --> <!-- <dubbo:registry address="multicast://224.5.6.7:1234" /> --> <!-- 使用Linux服务器上的Zookeeper --> <!-- <dubbo:registry address="zookeeper://192.168.125.100:2181" /> --> <!-- 使用本机的Zookeeper(Windows)--> <dubbo:registry address="zookeeper://127.0.0.1:2181" /> <!-- 生成远程服务代理,可以和本地bean一样使用demoService --> <dubbo:reference id="demoService" interface="com.beauxie.service.DemoService" /> </beans>4.同样新建一个启动类:ConsumerMain类代码如下:
package com.beauxie.consumer.main; import java.text.SimpleDateFormat; import java.util.Date; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.beauxie.service.DemoService; public class ConsumerMain { public static void main(String[] args) throws Exception { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"/META-INF/spring/dubbo-demo-consumer.xml"}); context.start(); DemoService demoService = (DemoService)context.getBean("demoService"); // 获取远程服务代理 for (int i = 0; i < Integer.MAX_VALUE; i ++) { try { String hello = demoService.sayHello("beauxie" + i);// 执行远程方法 System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + hello);// 显示调用结果 } catch (Exception e) { e.printStackTrace(); } Thread.sleep(2000); } } } 5.启动 ConsumerMain类,看到控制台输出:
同时,提供者端的控制台输出:
至此,项目整合完毕。
1.提供者、消费者、注册中心的关心可借鉴官网的一张图片来说明:
节点角色说明:
Provider: 暴露服务的服务提供方。Consumer: 调用远程服务的服务消费方。Registry: 服务注册与发现的注册中心。Monitor: 统计服务的调用次调和调用时间的监控中心。Container: 服务运行容器。 调用关系说明: 0. 服务容器负责启动,加载,运行服务提供者。1. 服务提供者在启动时,向注册中心注册自己提供的服务。2. 服务消费者在启动时,向注册中心订阅自己所需的服务。3. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。4. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。5. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。 2. 如果自己的网络支持multicast广播,可以尝试采用multicast广播作为注册中心。 3.provider暴露服务接口,隐藏接口的实现,但需要将接口、以及接口所依赖的jar包、类提供给consumer。 4.消费者的接口全路径应当与提供者的接口全路径保持一致,因为,Zookeeper是根据接口的全路径去查找服务的。