Dubbo框架结合Zookeeper注册中心使用初探

【参考文章】http://www.cnblogs.com/Javame/p/3632473.html  (灰常感谢这篇启蒙文章!!)

文章有错,修改见删除线处。。

一、基本概念

【Dubbo】

Dubbo是一个来源于阿里巴巴的分布式服务框架,本质上是一个服务调用的东西,主要在分布式场景中使用。它是以服务者/消息者的模式在dubbo上注册的。

核心:1)RPC:远程通讯——对长连接的NIO框架进行封装(多线程模型、序列化、“请求-响应”模式的信息交换);

  2)集群容错:基于接口方法的远程过程调用,各种集群支持

  3)基于注册中心目录的服务(这里用到的即是zookeeper),让服务的消费者可以动态地查找到服务提供者,地址透明化,以便服务者可以平滑的增加或者减少节点。

【Zookeeper】

ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、名字服务、分布式同步、组服务等。

ZooKeeper的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。

理解Zookeeper的算法可代入现实生活的“投票选举”。

Zookeeper字面意思是“动物园管理员”,它是一个分布式的服务框架,基于Fast Paxos算法。Zookeeper分布式集群里,主要分为三个角色:

Leader接收所有Follower的提案请求并统一协调发起提案的投票,负责与所有的Follower进行内部的数据交换(同步);

Follower直接为客户端服务并参与提案的投票,同时与Leader进行数据交换(同步); 

Observer直接为客户端服务但并不参与提案的投票,同时也与Leader进行数据交换(同步)。

ZooKeeper的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。

【Dubbo使用背景】

大规模分布式服务的背景需求。之前在大规模分布式服务以前,都是简单使用原生的RMI,简单暴露和引用远程服务,通过配置远程服务的URL地址进行调用,而通过硬件进行负载均衡(负载均衡:负载均衡,英文名称为Load Balance,其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。)

大规模分布式需求下,出现问题:

(1)当服务越来越多时,服务URL配置管理变得非常困难,F5硬件负载均衡器的单点压力也越来越大。——因此此时非常需要一个服务注册中心,动态注册和发现服务,管理服务地址

(2)服务间依赖关系变得错踪复杂,甚至分不清哪个应用要在哪个应用之前启动——需自己整理应用服务之间的依赖关系图

(3)服务调用量加大时,服务的容量限制问题

——Dubbo解决了以上面对的的问题。

二、Dubbo框架架构


【说明】Provider——给外界提供服务的服务方

        Container——服务方运行服务的容器,负责启动、加载运行服务

        Registry——服务注册与服务发现的中心(这里我们用的是zookeeper)

 Monitor——监控中心,用于统计服务的调用次数和调用时间

服务调用过程:

Step1   首先服务方启动时,向注册中心注册自己可提供的服务;

Step2   服务消费者启动时,向注册中心订阅自己所需的相关服务

Step3   注册中心在接收到订阅请求后,返回服务提供方的地址列表给服务消费方,如果有变更,注册中心将基于长连接推送变更数据给消费者。

Step4   服务消费方从提供的地址列表中基于负载均衡算法选择一台服务提供方进行调用,若调用失败,选择另一台

Step5   同时在调用的过程中,服务方和消费者都会在内存中累计调用次数和调用时间,定时将统计数据发送给监控中心。

——那么问题来了,如何使用Dubbo?

三、Dubbo简单使用

Dubbo是一个开源优秀的分布式服务调用框架,幸运地是可以跟Spring MVC无缝整合,而没有任何API侵入。Dubbo基于Spring的Schema扩展进行加载。所以常常在web平台的项目中使用到。

而zookeeper作为Dubbo的服务注册中心,我们首先要安装zookeeper启动注册中心服务。

简单来说,就是在A应用中定义一个接口及其实现类,然后配置对应的配置文件,把实现类打成一个jar包。B应用引用该jar包,并且需定义相同的接口,接口名称和路径必须和A应用对外的接口路径一致。

步骤:创建2个web应用,必须先引入相关jar包(jar包的获取可以先下载一个dubbo-admin-2.5.4.war包,再解压,里面会有相关jar包):

dubbo-2.5.4-SNAPSHOT.jar  

netty-3.2.5.Final.jar  

slf4j-api-1.7.2.jar  

slf4j-log4j12-1.6.2.jar  

slf4j-simple-1.7.2.jar  

zkclient-0.1.jar  

zookeeper-3.3.3.jar

下面开始使用Dubbo的示例:

【服务提供方】

1、先定义A应用(作为服务对外的提供方),定义多个接口(考虑到今后真正投入到项目中使用的时候,肯定不止一个接口,所以我用2个接口来模拟):

接口一:

public interface ServiceDemo {
	String sayHello(String name);
}

接口二:

public interface ServiceDemo2 {
	String print(String name);
}

 还有他们的实现类:

public class ServiceDemoImpl implements ServiceDemo {

	@Override
	public String sayHello(String name) {
		return "hello " + name;
	}
	
}

以及接口二的实现类:

public class ServiceDemoImpl2 implements ServiceDemo2 {

	@Override
	public String print(String name) {
			return "My name is " + name;
	}

}

服务提供方的配置:

<?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 ">
        
    <bean id="demoService" class="com.xxx.demo.dubbo.ServiceDemoImpl" />
    <bean id="demoService2" class="com.xxx.demo.dubbo.ServiceDemoImpl2" />
    
    <!-- 提供方应用信息 -->
   <dubbo:application name="service_provider" />
 
	<!-- 用zookeeper注册中心暴露服务地址 -->
	<dubbo:registry address="zookeeper://127.0.0.1:2181" subscribe="false"/>
	
	<!-- 用dubbo协议在指定端口暴露服务 -->
	<dubbo:protocol name="dubbo" port="20880" /> 
	
	<!-- 声明需要暴露的(多个)服务接口 -->
	<dubbo:service interface="com.xxx.demo.dubbo.ServiceDemo" ref="demoService" />
	<dubbo:service interface="com.xxx.demo.dubbo.ServiceDemo2" ref="demoService2" />
</beans>

再将这多个实现类(注意是实现类,【应为接口并非实现类!!!!】这里为2个)单独打成1个(注意是1个)jar包(选中这多个实现类,【是接口】右键->Export->JAR file->Next(只勾选Export Java source files and resources)->命名->Next导出),这里命名为dubbo-test.jar。

【服务消费方】

2、定义B应用(服务消费方),分别并且定义与A应用路径相同的接口(这里就不再把代码显示出来了因为跟上面接口的定义一模一样),这里的接口也与服务提供方一致。【有错!正确的是把服务提供端的接口打成jar包(并非实现类打成jar包),把这个jar包给服务的消费端即可。服务的实现类应该对消费端隐藏!这里即为ServiceDemo和ServiceDemo2,并且他们的包名路径应该与A应用的对外提供的接口包名路径一致。

【注意】除了上述所说的jar包外,在B应用中另外加入刚才由A应用提供的jar包dubbo-test.jar

服务消费方的配置(这里IP为127.0.0.1是因为服务方就在我本机)

<?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="service_consumer" />  
	<!-- 用zookeeper注册中心暴露服务地址 -->
	<dubbo:registry address="zookeeper://127.0.0.1:2181" />
   
	<!-- 生成远程服务代理,以便在本地可以使用远程曝露的(多个)接口服务-->
	<dubbo:reference interface="com.xxx.demo.dubbo.ServiceDemo" id="caller"/>
	<dubbo:reference interface="com.xxx.demo.dubbo.ServiceDemo2" id="caller2"/>
</beans>

然后我又尝试了在另外一台机器建立服务消费方(Jar包导入、接口定义什么的跟上述操作一样),其配置为(这里的IP就必须写服务提供方所在机器的ip地址了,即为我电脑的ip):

<?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="service_consumer" />  
	<!-- 用zookeeper注册中心暴露服务地址 -->
	<dubbo:registry address="zookeeper://192.168.0.105:2181" />
   
	<!-- 生成远程服务代理,以便在本地可以使用远程曝露的多个接口服务-->
	<dubbo:reference interface="com.xxx.demo.dubbo.ServiceDemo" id="caller"/>
	<dubbo:reference interface="com.xxx.demo.dubbo.ServiceDemo2" id="caller2"/>
</beans>

【Zookeeper注册中心启动】

3、启动zookeeper服务注册中心,进入zookeeper安装路径/bin,双击zkServer.cmd命令即可开启。

【服务测试部分】

在A应用(工程)中启动服务提供方(向Zookeepr注册服务):

public class Provider {
	public static void main(String[] args) throws Exception {
		 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
				 new String[] {"context-dubbo-provider.xml"});  
	     context.start();  
	     System.in.read();//用于模拟服务一直开着
	}
}

接着,分别在本机和另外一台机器启动服务消费方(从Zookeepr订阅服务)

public class Consumer {
	public static void main(String[] args) throws Exception {
		FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext(
				 new String[] {
						 "webRoot/WEB-INF/conf/spring/sys/context-dubbo-consumer.xml"});  
		context.start();
		ServiceDemo demo = (ServiceDemo) context.getBean("caller");
		String hello = demo.sayHello("Lily");
		System.out.println("After call the remote (sayHello): " + hello);
		
		System.out.println("================");
		
		ServiceDemo2 demo2 = (ServiceDemo2) context.getBean("caller2");
		System.out.println(demo2.print("Tom"));
		
		System.in.read();
	}

}

之后在本机和另外一台机器(2个服务消费方)分别可以得到如下的打印结果:

After call the remote (sayHello): hello Lily

======================

My name is Tom

说明了A应用对外提供的多个接口服务都被远程调用成功了!

======================

遇到的异常:

No provider available for the service xxxxx   出现该异常原因之一很可能是因为服务的消费方没有导入服务提供方提供的jar包(jar包封装的是实现类而不是接口!),当然也有可能是其他原因造成。。

四、Dubbo管理控制

好吧。。因为之前参考网上的文章都有这部分,所以自己也做了一下。。。

将下载好的war包,我下的是dubbo-admin-2.5.4-SNAPSHOT.war(dubbo服务管理的war包)

将tomcat安装文件下的webapps/ROOT的东西删除(建议先备份),再把上述war包解压后的全部文件拷贝至ROOT下,而且tomcat使用的jdk的版本不要太高,控制在jdk1.7或以下最佳。启动tomcat成功后,在浏览器地址栏输入http://loclahost:8080,此时会弹出一个要求你输入用户名密码的会话框,都填入root,即可得到dubbo管理界面:

进入管理界面即可看到服务者、消费者、服务被调用的统计情况等等,这里为节省篇幅,只看看消费者的截图(因为有2台机器都访问了A应用提供的对外的接口,所以有2列数据):



 

综上:简单理解来说,Dubbo和Zookeeper的结合使用达到了远程调用的效果。Dubbo是一个分布式服务框架(尤其在RPC性能方面体现较好),而Zookeeper是作为Dubbo的服务注册中心而使用的。

猜你喜欢

转载自raising.iteye.com/blog/2220065