Dubbo(一) -- 初体验
Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,是阿里巴巴SOA服务化治理方案的核心框架。
一、Dubbo出现的背景
随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进;
1.当服务越来越多时,服务URL配置管理变得非常困难,F5硬件负载均衡器的单点压力也越来越大。
2.当进一步发展,服务间依赖关系变得错踪复杂,甚至分不清哪个应用要在哪个应用之前启动,架构师都不能完整的描述应用的架构关系。
3.接着,服务的调用量越来越大,服务的容量问题就暴露出来,这个服务需要多少机器支撑?什么时候该加机器?
二、Dubbo架构
1.节点角色说明:
Provider: 暴露服务的服务提供方。
Consumer: 调用远程服务的服务消费方。
Registry: 服务注册与发现的注册中心。
Monitor: 统计服务的调用次调和调用时间的监控中心。
Container: 服务运行容器。
2.调用关系说明:
0. 服务容器负责启动,加载,运行服务提供者
1. 服务提供者在启动时,向注册中心注册自己提供的服务。
2. 服务消费者在启动时,向注册中心订阅自己所需的服务。
3. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
4. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
5. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
三、Dubbo后台部署管理
1.源码下载
1. 访问www.github.com 网站
2. 搜索dubbo服务框架
3. 搜索到git的地址:https://github.com/alibaba/dubbo.git
4. 通过git客户端clone代码
5. Dubbo源码导入到Eclipse遇到的问题:http://www.cnblogs.com/xbq8080/p/6792375.html
2.dubbo控制台部署
方式一:
启动dubbo源码中的dubbo-admin模块:
1. 找到dubbo-admin 模块
2. 修改dubbo.properties的配置,包括注册中心的配置,以下是zookeeper的示例
dubbo.registry.address=zookeeper://101.200.129.112:2181;zookeeper://101.200.129.112:2182;zookeeper://101.200.129.112:2183
dubbo.admin.root.password=root
dubbo.admin.guest.password=guest
3. 部署到web容器中,启动服务即可,启动服务需要很久一段时间。
4.服务启动成功后,登录到控制台
5.查看zookeeper中的节点: ls /,发现产生了dubbo节点
方式二:
直接下载dubbot.war,修改修改dubbo.properties的配置(和方式一修改方式一样),放到tomcat中启动,下载地址:http://download.csdn.net/download/u010821757/10030525
方式二更加简单方便,而且支持JDK1.8。
四、实例:Hello World
架构如下所示:
1.建立三个maven工程,分别是 provider,api,consumer。
直接在Eclipse中建立、或者直接使用Maven索架来生成。
这里在Eclipse中分别新建三个项目,当然也可以不新建三个项目,分为三个模块也可以:
1).新建DubboApiDemo项目
2).新建DubboProviderDemo 项目
3).新建DubboConsumerDemo项目
2.Api工程,此工程用于提供接口服务
1)新建 IHelloWorld 接口:
package com.dubbo.demo.api; /** * 提供接口服务 * @author xbq */ public interface IHelloWorld { // 接口 public String sayHello(String name); }
2) 使用maven工具打包到Maven私服,即Maven install
成功后,会成成一个jar包,如下图所示:
3.Provider工程,生产者
1)pom.xml
1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 2 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 3 <modelVersion>4.0.0</modelVersion> 4 5 <groupId>com.dubbo.demo.provider</groupId> 6 <artifactId>DubboPrividerDemo</artifactId> 7 <version>0.0.1-SNAPSHOT</version> 8 <packaging>jar</packaging> 9 10 <name>DubboPrividerDemo</name> 11 <url>http://maven.apache.org</url> 12 13 <properties> 14 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 15 </properties> 16 17 <dependencies> 18 <dependency> 19 <groupId>junit</groupId> 20 <artifactId>junit</artifactId> 21 <version>4.10</version> 22 <scope>test</scope> 23 </dependency> 24 25 <dependency> <!-- 刚刚打包的api jar,在这里引用 --> 26 <groupId>com.dubbo.demo.api</groupId> 27 <artifactId>DubboApiDemo</artifactId> 28 <version>0.0.1-SNAPSHOT</version> 29 </dependency> 30 <dependency> 31 <groupId>com.alibaba</groupId> 32 <artifactId>dubbo</artifactId> 33 <version>2.5.3</version> 34 </dependency> 35 <dependency> 36 <groupId>org.slf4j</groupId> 37 <artifactId>slf4j-api</artifactId> 38 <version>1.7.21</version> 39 </dependency> 40 <dependency> 41 <groupId>org.slf4j</groupId> 42 <artifactId>slf4j-log4j12</artifactId> 43 <version>1.7.16</version> 44 </dependency> 45 <dependency> 46 <groupId>org.apache.zookeeper</groupId> 47 <artifactId>zookeeper</artifactId> 48 <version>3.4.6</version> 49 </dependency> 50 <dependency> 51 <groupId>com.github.sgroschupf</groupId> 52 <artifactId>zkclient</artifactId> 53 <version>0.1</version> 54 </dependency> 55 <dependency> 56 <groupId>org.mortbay.jetty</groupId> 57 <artifactId>jetty</artifactId> 58 <version>7.0.0.pre5</version> 59 </dependency> 60 <dependency> 61 <groupId>javax.servlet</groupId> 62 <artifactId>servlet-api</artifactId> 63 <version>2.5</version> 64 </dependency> 65 </dependencies> 66 </project>
2)provider.xml(自己定义的)
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans.xsd 7 http://code.alibabatech.com/schema/dubbo 8 http://code.alibabatech.com/schema/dubbo/dubbo.xsd 9 "> 10 <!-- 提供方应用信息,用于计算依赖关系 --> 11 <dubbo:application name="hello-world-provider"/> 12 13 <!-- 使用zookeeper注册中心暴露服务地址 --> 14 <dubbo:registry address="zookeeper://192.168.242.130:2181?backup=192.168.242.130:2182,192.168.242.130:2183" id="zk"/> 15 16 <!-- 用dubbo协议在20880端口暴露服务 --> 17 <dubbo:protocol name="dubbo" port="20880"/> 18 19 <!-- 具体的bean实现 --> 20 <bean id="helloWorldService" class="com.dubbo.demo.provider.HelloWorldServiceImpl" /> 21 22 <!-- 声明需要暴露的服务接口 --> 23 <dubbo:service interface="com.dubbo.demo.api.IHelloWorld" ref="helloWorldService" protocol="dubbo" registry="zk"/> 24 </beans>
dubbo:registry 标签一些属性的说明:
1)register是否向此注册中心注册服务,如果设为false,将只订阅,不注册。
2)check注册中心不存在时,是否报错。
3)subscribe是否向此注册中心订阅服务,如果设为false,将只注册,不订阅。
4)timeout注册中心请求超时时间(毫秒)。
5)address可以Zookeeper集群配置,地址可以多个以分号隔开等。
dubbo:service标签的一些属性说明:
1)interface服务接口的路径
2)ref引用对应的实现类的Bean的ID
3)registry向指定注册中心注册,在多个注册中心时使用,值为<dubbo:registry>的id属性,多个注册中心ID用逗号分隔,如果不想将该服务注册到任何registry,可将值设为N/A
4)register 默认true ,该协议的服务是否注册到注册中心。
3)实现接口
1 package com.dubbo.demo.provider; 2 3 import com.dubbo.demo.api.IHelloWorld; 4 5 /** 6 * 实现接口 7 * @author xbq 8 * 可以调用 IHelloWorld ,是因为 引入了的 api项目的依赖 9 */ 10 public class HelloWorldServiceImpl implements IHelloWorld{ 11 12 @Override 13 public String sayHello(String name) { 14 return "Hello World!" + name; 15 } 16 17 }
4)启动生产者服务
1 package com.dubbo.demo.provider; 2 3 import java.io.IOException; 4 import org.springframework.context.support.ClassPathXmlApplicationContext; 5 /** 6 * 启动生产者服务 7 * @author xbq 8 */ 9 public class Main { 10 11 public static void main(String[] args) { 12 // 引用xml文件 13 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("provider.xml"); 14 context.start(); 15 16 try { 17 // 为保证服务一直开着,利用输入流的阻塞来模拟 18 System.in.read(); 19 } catch (IOException e) { 20 e.printStackTrace(); 21 } 22 } 23 }
4.Consumer工程,消费者
1)pom.xml
1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 2 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 3 <modelVersion>4.0.0</modelVersion> 4 5 <groupId>com.dubbo.demo.consumer</groupId> 6 <artifactId>DubboConsumerDemo</artifactId> 7 <version>0.0.1-SNAPSHOT</version> 8 <packaging>jar</packaging> 9 10 <name>DubboConsumerDemo</name> 11 <url>http://maven.apache.org</url> 12 13 <properties> 14 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 15 </properties> 16 17 <dependencies> 18 <dependency> 19 <groupId>junit</groupId> 20 <artifactId>junit</artifactId> 21 <version>4.10</version> 22 <scope>test</scope> 23 </dependency> 24 <dependency> 25 <groupId>com.alibaba</groupId> 26 <artifactId>dubbo</artifactId> 27 <version>2.5.3</version> 28 </dependency> 29 <dependency> <!-- 刚刚打包的api jar,在这里引用 --> 30 <groupId>com.dubbo.demo.api</groupId> 31 <artifactId>DubboApiDemo</artifactId> 32 <version>0.0.1-SNAPSHOT</version> 33 </dependency> 34 <dependency> 35 <groupId>org.apache.zookeeper</groupId> 36 <artifactId>zookeeper</artifactId> 37 <version>3.4.6</version> 38 </dependency> 39 <dependency> 40 <groupId>com.github.sgroschupf</groupId> 41 <artifactId>zkclient</artifactId> 42 <version>0.1</version> 43 </dependency> 44 </dependencies> 45 </project>
2)consumer.xml(自己定义的)
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans 5 http://www.springframework.org/schema/beans/spring-beans.xsd 6 http://code.alibabatech.com/schema/dubbo 7 http://code.alibabatech.com/schema/dubbo/dubbo.xsd 8 "> 9 <!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 --> 10 <dubbo:application name="hello-world-consumer"/> 11 12 <!-- 使用zookeeper注册中心暴露服务地址 --> 13 <dubbo:registry address="zookeeper://192.168.242.130:2181?backup=192.168.242.130:2182,192.168.242.130:2183" id="zk"/> 14 15 <!-- 用dubbo协议在20880端口暴露服务 --> 16 <dubbo:protocol name="dubbo" port="20881"/> 17 18 <!-- 生成远程服务代理,可以像使用本地bean一样使用demoService --> 19 <dubbo:reference interface="com.dubbo.demo.api.IHelloWorld" id="helloService" protocol="dubbo" registry="zk" /> 20 </beans>
dubbo:reference 的一些属性的说明:
1)interface调用的服务接口
2)check 启动时检查提供者是否存在,true报错,false忽略
3)registry 从指定注册中心注册获取服务列表,在多个注册中心时使用,值为<dubbo:registry>的id属性,多个注册中心ID用逗号分隔
4)loadbalance 负载均衡策略,可选值:random,roundrobin,leastactive,分别表示:随机,轮循,最少活跃调用
3)启动消费者服务
1 package com.dubbo.demo.consumer; 2 3 import java.io.IOException; 4 import org.springframework.context.support.ClassPathXmlApplicationContext; 5 import com.dubbo.demo.api.IHelloWorld; 6 7 /** 8 * 启动消费者服务 9 * @author xbq 10 */ 11 public class Main { 12 13 public static void main(String[] args) { 14 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("consumer.xml"); 15 context.start(); 16 17 IHelloWorld helloWorld = (IHelloWorld)context.getBean("helloService"); 18 String str = helloWorld.sayHello("Joe"); 19 System.out.println(str); 20 21 try { 22 // 为保证服务一直开着,利用输入流的阻塞来模拟 23 System.in.read(); 24 } catch (IOException e) { 25 e.printStackTrace(); 26 } 27 } 28 }
五、启动生产者和消费者
1.启动生产者,执行生产者的 main方法
2.查看dubbo控制台开启的服务,可以看到发布的生产者是正常状态,下图:
3.查看zookeeper中dubbo节点下的节点: ls /dubbo
4.启动消费者,执行消费者的main方法
5.查看Eclipse控制台打印的消息,则说明接口调用成功:
6.查看dubbo控制台中的应用,既有生产者,又有消费者,如下图:
六、源码下载
dubbo接口:http://git.oschina.net/xbq168/DubboApiDemo
dubbo生产者:http://git.oschina.net/xbq168/DubboPrividerDemo
dubbo消费者:http://git.oschina.net/xbq168/DubboConsumerDemo