dubbo 开发环境环境和单机环境的区别

轻松搭建dubbo环境
轻松搭建dubbo环境
编辑:www.fx114.net
本篇文章主要介绍了"轻松搭建dubbo环境",主要涉及到轻松搭建dubbo环境方面的内容,对于轻松搭建dubbo环境感兴趣的同学可以参考一下。
本文是基于maven的,预先使用,先装maven。
dubbo是一个分布式服务框架,提供一个SOA的解决方案。简单的说,dubbo就像在生产者和消费者中间架起了一座桥梁,使之能透明交互。
本文旨在搭建一个可供使用和测试的dubbo环境,使用了spring框架;使用了zookeeper和dubbo服务。
zookeeper:直接去官方网站下载即可,下载后解压,不需要改任何配置即可使用。
dubbo:直接去阿里巴巴下载即可,下载后解压并放到tomcat的webapps目录下,修改WEB-INF/dubbo.properties中属性如下:
#zookeeper的地址和端口
dubbo.registry.address=zookeeper://127.0.0.1:2181
#登录dubbo管理页面时的root用户和guest用户的密码
dubbo.admin.root.password=root
dubbo.admin.guest.password=guest
如果你清楚生产者-消费者模型,那么将会很容易理解dubbo的使用步骤。
一个生产者-消费者模型的代码实现需要3部分:生产者代码,消费者代码,中间接口。
中间接口:创建一个mavan项目,然后添加一个接口如下:
publicinterface ITest {
public voidsayHello(String message);
生产者代码:
创建一个mavan项目,并引入spring依赖、中间接口依赖、zookeeper依赖及dubbo依赖如下:
&dependency&
&groupId&org.springframework&/groupId&
&artifactId&spring-context&/artifactId&
&version&4.1.6.RELEASE&/version&
&/dependency&
&!--&中间接口,根据你的情况进行修改&--&
&dependency&
&groupId&com.dubbo.demo&/groupId&
&artifactId&DubboIServiceDemo&/artifactId&
&version&0.0.1&/version&
&/dependency&
&dependency&
&groupId&org.apache.zookeeper&/groupId&
&artifactId&zookeeper&/artifactId&
&version&3.4.6&/version&
&/dependency&
&dependency&
&groupId&com.alibaba&/groupId&
&artifactId&dubbo&/artifactId&
&version&2.5.3&/version&
&/dependency&
&!--&连接zookeeper的客户端&--&
&dependency&
&groupId&com.github.sgroschupf&/groupId&
&artifactId&zkclient&/artifactId&
&version&0.1&/version&
&/dependency&
编写中间接口的实现,代码如下,注意这里通过注解的方式将此类标记为了spring服务:
@Service(&springservice&)
public class Test implements ITest {
&* @authorShixy
&*@date&&2016年1月5日
&* @seecom.dubbo.iservice.ITest#sayHello(java.lang.String)
public void sayHello(String message) {
System.out.println(&service say:& +message);
编写spring配置文件,注意需要引入dubbo的schema:
&?xml version=&1.0&encoding=&UTF-8&?&
&beansxmlns=&http://www.springframework.org/schema/beans&
xmlns:xsi=&http://www.w3.org/2001/XMLSchema-instance&xmlns:jee=&http://www.springframework.org/schema/jee&
xmlns:tx=&http://www.springframework.org/schema/tx&xmlns:dubbo=&/schema/dubbo&
xmlns:context=&http://www.springframework.org/schema/context&
xsi:schemaLocation=&http://www.springframework.org/schema/beans
default-lazy-init=&false&&
&bean id=&springservice&class=&com.dubbo.iservice.impl.Test&&
&!--提供方应用名称信息,这个相当于起一个名字,我们dubbo管理页面比较清晰是哪个应用暴露出来的
&dubbo:applicationname=&dubbo_provider&&&/dubbo:application&
&!--使用zookeeper注册中心暴露服务地址
&dubbo:registry address=&zookeeper://127.0.0.1:2181&&&check=&false&subscribe=&false& register=&&&&/dubbo:registry&
&!--要暴露的服务接口 --&
&dubbo:serviceinterface=&com.dubbo.iservice.ITest& ref=&springservice&/&
编写测试类:
public class Demo {
public static void main(String[] args) {
//这里注意spring配置文件的名字和路径
ApplicationContext applicationContext = newClassPathXmlApplicationContext(new String[] {&classpath*:config/applicationContext-commons.xml& });
while(true);
消费者代码:
创建一个mavan项目,并引入spring依赖、中间接口依赖、zookeeper依赖及dubbo依赖,这里和生产者是完全相同的。
编写spring配置文件,注意需要引入dubbo的schema:
&?xml version=&1.0&encoding=&UTF-8&?&
&beansxmlns=&http://www.springframework.org/schema/beans&
xmlns:xsi=&http://www.w3.org/2001/XMLSchema-instance&xmlns:jee=&http://www.springframework.org/schema/jee&
xmlns:tx=&http://www.springframework.org/schema/tx&xmlns:dubbo=&/schema/dubbo&
xmlns:context=&http://www.springframework.org/schema/context&
xsi:schemaLocation=&http://www.springframework.org/schema/beans
default-lazy-init=&false&&
&dubbo:applicationname=&dubbo_consumer&&&/dubbo:application&
&!--使用zookeeper注册中心暴露服务地址
&dubbo:registryaddress=&zookeeper://127.0.0.1:2181&
check=&false&&&/dubbo:registry&
&!--要引用的服务 --&
&dubbo:referenceinterface=&com.dubbo.iservice.ITest&
id=&springservice&&&&/dubbo:reference&
编写测试类:
public class ClientDemo {
public static void main(String[] args) {
//这里注意spring配置文件的名字和路径
ApplicationContext applicationContext = newClassPathXmlApplicationContext(new String[] {&classpath*:config/applicationContext-commons.xml& });
ITest&&&&&&&&test = (ITest) applicationContext.getBean(&springservice&);
test.sayHello(&abcdefg&);
while(true);
开始测试:
1.启动zookeeper。执行zookeeper目录下:bin/zkServer.cmd启动服务
2.启动dubbo服务。启动dubbo所在tomcat(详见本文开头),dubbo启动后,可通过http://127.0.0.1:8080/dubbo-admin来查看dubbo服务状态
3.启动生产者服务。运行生产者测试类Client.java
4.启动消费者服务。运行消费者服务代码ClientDemo.java,此时可以在生产者的控制台看到服务被调用了。
此时整个dubbo测试已经完成。同时我们可以在dubbo的web端看到生产者、消费者的状态以及各个服务的调用情况。
为了方便大家,本测试用例以及需要的工具都可以在这里下载:
zookeeper下载:
dubbo下载(配置文件已修改,可直接解压后放到tomcat中使用):
实例代码下载(包含接口、生产者、消费者):
一、不得利用本站危害国家安全、泄露国家秘密,不得侵犯国家社会集体的和公民的合法权益,不得利用本站制作、复制和传播不法有害信息!
二、互相尊重,对自己的言论和行为负责。
本文标题:
本页链接:dubbo(16)
这个测试环境的搭建基于上一篇的基础上开始的。(补充说明,在那边文章之后又重新编译了2.4.10的源码,这个测试是基于2.4.10版本的)
注册中心的安装
首先先安装一个zookeeper,至于zookeeper的安装这里就不多做介绍了,可自行查找。
监控中心安装
进入dubbo-simple/dubbo-monitor-simple/target目录,可以看到dubbo-monitor-simple-2.4.10-assembly.tar.gz文件。
.4.10-assembly.tar.gz
解压后进入目录,
vim conf/dubbo.properties
修改注册中心的配置,注释掉广播地址,改为zookeeper作为注册中心,
#dubbo.registry.address=multicast:
dubbo.registry.address=zookeeper:
其它参数如有需要可自行修改。(注意:如果是本机测试,将monitor和admin都撞倒一台机器上时,可以将dubbo.jetty.port=8083)
sh bin/start.sh
可启动mointor。访问地址:&(默认为是修改后的值)
管理员控制台安装
进入源码编译目录,进入到dubbo-admin/target,可以看到dubbo-admin-2.4.10这个文件夹。这是web项目,需要运行在web容器下,我这里是运行到tomcat下。这个默认使用zookeeper作为注册中心的,不过配置的本机地址,如果需要修改为其他ip,只需修改WEB-INF/dubbo.properties下的配置地址即可。
dubbo.registry.address=zookeeper:
启动tomcat即可。访问地址:&(根据自己的tomcat配置来访问)
运行provider
进入dubbo-demo/dubbo-demo-provider/target,
.4.10-assembly.tar.gz
修改注册中心的配置地址为zookeeper,如下:
#dubbo.registry.address=multicast:
dubbo.registry.address=zookeeper:
sh bin/start.sh
来启动provider服务。
运行consumer
进入dubbo-demo/dubbo-demo-consumer/target,
.4.10-assembly.tar.gz
修改注册中心的配置地址为zookeeper,如下:
#dubbo.registry.address=multicast:
dubbo.registry.address=zookeeper:
sh bin/start.sh
来启动consumer服务。
转载于:/p/9be765a43f19
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1091178次
积分:13927
积分:13927
排名:第910名
原创:172篇
转载:1100篇
评论:57条
(1)(6)(5)(6)(17)(19)(19)(24)(13)(13)(25)(5)(1)(7)(32)(13)(3)(31)(6)(48)(5)(13)(24)(53)(35)(56)(47)(5)(31)(24)(51)(27)(26)(6)(15)(26)(28)(34)(43)(13)(24)(61)(82)(57)(69)(121)(3)要说这个话题之前先讲讲之所以要做这个的需求。一般选择DUBBO来进行服务管理,都是在分布式应用的前提下,涉及到多个子系统之间的调用,DUBBO所做的事情就是维护各个子系统暴露的接口和自动发现对应接口的远程地址从而实现分布式RPC服务管理。
有了上面前提之后,那么在项目开发和过程中涉及到一个问题,就是接口的联调。如果每个子系统自己维护自己系统的联调环境,那么可能会导致别人调用接口的不稳定,因为环境是系统自己人来维护,可能挂了也可能调整接口没通知相关人员,这对开发接口联调测试是一个问题。那么如何做好这件事情呢?下面提出了STABLE环境的概念,一看字面意思就知道是一个稳定的环境,这个环境是和线上保持同步的,并且不是由开发负责维护,而是有专门的运维人负责维护,这样STABLE环境就相对比较稳定,那么调用这个环境的接口也就比较稳定了(你可能会问,怎么调用这个环境的接口?在项目的dubbo.properties里面把注册中心指向STABLE环境即可)。那么问题来了,STABLE不是开发维护,那么会导致如果一个项目涉及多个子系统变更呢?要说明这个问题,我先来个图先:
上面是整个STABLE环境的调用图,不管是哪个项目,将涉及到改动的子系统迁移出来构造一个子环境,然后最后一个节点切入到stable环境中,这样既保证了接口联调的稳定性,也确保了各个项目的开发并行化。关于STABLE环境的介绍不是本篇的内容,所以不做过多的解释。下面谈谈DUBBO怎么隔离各个子环境的服务。
直连加不发布服务
DUBBO的配置属性里面对消费端提供了不从注册中心发现服务的机制,直接配置远程接口的地址,这样可以保证消费端连接到制定的环境接口。这样消费端是解决了问题,但是服务提供端呢?如上图的B1它即是消费端也是服务提供端,它提供A1所依赖的接口,那么如果B1将它的服务发布到注册中心里面(这里需要提醒,STABLE环境机制里面所有子环境公用一个注册中心),那么势必会导致stable环境里面的A会发现B1提供的服务?势必会导致stable环境的不稳定(stable环境的机制是stable环境只能进不能出,就是不能调用外部其他子环境的服务)?所以B1不能发布服务到注册中心,dubbo也提供了相关的配置属性来支持这一点。下面我例举出通过哪些配置可以实现这种方案:
服务消费端:
DUBBO在消费端提供了一个url的属性来指定某个服务端的地址
&!--lang:xml--&
&dubbo:reference interface=&com.alibaba.dubbo.demo.HelloWorldService& check=&false& id=&helloWorldService&/&
默认的方式是从注册中心发现接口为com.alibaba.dubbo.demo.HelloWorldService的服务,但是如果需要直连,可以在dubbo.properties下面配置dubbo.reference.helloWorldService.url=dubbo://ip:port/com.alibaba.dubbo.demo.HelloWorldService可以通过配置dubbo.reference.url=dubbo://ip:port/来让某个消费者系统的服务都指向制定的服务器地址(关于配置信息可以参考)
服务提供端:
只需要在dubbo.properties里面添加dubbo.registry.register=false即表示当前系统的服务不发布到注册中心。
这种方式服务发布和服务消费就和注册中心没一点关系了,个人感觉这是一个退步,我们用dubbo就是它的服务管理,而这种方案是直接将我们打入了原始社会。这样也会导致如果一个项目设计的子系统很多,那么搭建一个项目的子环境将会比较头疼,因为你要配置那些直连地址。
注意:这里为什么一直通过配置在dubbo.properties文件中来达到目的?其实dubbo提供了多种配置的渠道(见)。因为是为了达到环境的隔离,最好不用为了切换环境而调整源码,这样容易导致将调整的代码发布到产线,所以排除通过的XML来配置。一般情况下dubbo.properties可以被定义为是存放环境的配置,因为不同的环境注册中心地址不一样,如果将这些地址信息配置在Spring里面,难免会带来失误。所以建议dubbo.properties文件不要放在项目中,而是放在环境的容器里面,通过容器来加载这个文件(比如JBOSS,可以将这个文件放在modules下面),这样对代码会比较稳定。
通过服务分组或者版本号来隔离
熟悉DUBBO的童鞋应该知道DUBBO对每个接口都支持分组和版本号,然后服务消费方指定调用哪个分组或者哪个版本号就可以调用对应的接口。那么通过这个来描述一下怎么通过它们来隔离。在谈这些之前还是先上一个各个子系统和注册中心的关系图:
通过给每个子环境分配一个分组来实现各个子环境在一个组里面,从而实现各个环境的隔离。具体操作如下:
服务消费方
&!--lang:xml--&
&dubbo:reference interface=&com.alibaba.dubbo.demo.HelloWorldService& check=&false& id=&helloWorldService&/&
针对上面的接口只能调用指定的分组,可以在dubbo.properties中添加dubbo.reference.helloWorldService.group=test,那么该接口只会从test分组中发现对应接口的服务了。也可以将所有服务都指向某个分组dubbo.reference.group=test。
服务提供方
&!--lang:xml--&
&dubbo:service interface=&com.alibaba.dubbo.demo.HelloWorldService& id=&helloWorldRemote& ref=&helloWorld&/&
针对上面的接口发布到指定的分组,也是在dubbo.properties中添加dubbo.service.helloWorldRemote.group=test,那么该服务就发布到了test分组,同样也可以将当前系统所有服务发布到指定分组dubbo.service.group=test。
而通过版本号也是类似的方案,只是配置的属性不是group而是version,这里就不赘述了。
这个方案看上去很好,不需要再配置直连的地址了,而是通过分组的方案来实现环境的隔离。但是如果你看过dubbo的官方文档,你可能知道group在dubbo的定义是服务接口有多种实现而进行分组的(version也是类似),不是进行环境上面隔离的,所以虽然dubbo提供了这种功能,但是设计的目的不是做这种事情的,那么就不能这么硬拉过来,不然会导致团队开发理解不一直出现问题。另外这种方案会导致注册中心比较混乱,因为注册中心是所以环境公用的,那么会导致一个注册中心中存在多个环境的接口,也不便于维护。
说了这么多,那么有没有一个比较合理的方案来实现环境的隔离呢?据我了解dubbo的原生并没有提供,需要对dubbo进行小小的改造。下面谈谈这个小小的改造怎么个改造法!
注册中心分组实现隔离
细心的童鞋可能知道dubbo在配置注册中心的时候有group字段,可以通过dubbo.registry.group=test来实现注册中心的分组,但是这有个问题,如果配置了这个,那么当前系统的服务发现和服务注册都会到这个组里面来进行,不能分别对服务发现和服务注册单独配置,也不能对某个接口进行配置。所以沿着这个想法,我对dubbo进行了小小的改造,在dubbo的服务发布和服务消费添加了注册中心分组的概念。既然要对注册中心进行分组配置,那么就需要了解怎么将分组告诉注册中心,以及分组在注册中心是如何体现的,这里我就以Zookeeper注册中心为例,看看它是怎么实现的。
dubbo中zookeeper的注册中心由ZookeeperRegistry类实现的,看看它的构造函数就你就清楚了:
&!--lang:java--&
public ZookeeperRegistry(URL url, ZookeeperTransporter zookeeperTransporter) {
super(url);
if (url.isAnyHost()) {
throw new IllegalStateException(&registry address == null&);
String group = url.getParameter(Constants.GROUP_KEY, DEFAULT_ROOT);
if (! group.startsWith(Constants.PATH_SEPARATOR)) {
group = Constants.PATH_SEPARATOR +
this.root =
zkClient = zookeeperTransporter.connect(url);
zkClient.addStateListener(new StateListener() {
public void stateChanged(int state) {
if (state == RECONNECTED) {
recover();
} catch (Exception e) {
logger.error(e.getMessage(), e);
可以看到注册中心接受的是一个URL对象(dubbo内部和外部同学都是通过URL来实现的),并且从其中获取group参数,如果没有则是默认的dubbo。那么你就不难理解为什么dubbo发布到zookeeper的根节点是dubbo了,这个其实是组名。那么不同组服务,将会在zookeeper不同的根节点下面。
在谈这些之前先看看dubbo中发布服务,关联远程服务和注册中心的关系。
上图是服务引用和注册中心关系图,服务发布也是类似,他发布服务的时候会向制定的注册中心发布服务。基于上面我在这两个类中添加了一个registryGroup属性,由于ReferenceBean和ServiceBean都继承了AbstractInterfaceConfig抽象类,那么在这个抽象类中加入字段registryGroup那么服务消费和服务发布里面都可以读取到该字段,添加完该字段之后,就可以通过dubbo.properties文件配置该属性,在有讲过怎么配置。我这里列举一下对于属性registryGroup怎么来配置:
服务消费端:
在dubbo.properties文件中添加dubbo.reference.registry-group=test那么当前系统的所有服务应用都会从注册中心的test组中去发现服务,当然也可以通过dubbo.reference.beanId.registry-group=test来指定某个服务从test组中发现服务。
服务提供端:
也是在dubbo.properties文件中添加类似的内容,只是将上面的reference改成service即可。
这里是配置,在服务发布和服务发现都读到这个配置之后,怎么体现到注册中心里的分组中呢?因为这里毕竟不是直接配置注册中心的分组(dubbo.registry.group),所以需要调整一下dubbo的代码来将这个属性添加到服务发现和服务注册的注册中心中。这里主要调整了三个类,其中一个是常量类中添加了一个常量。总共对dubbo的代码修改不超过10行。
下面列举一下我的代码调整:
显示添加一个常量,在Constants中添加了public static final String REGISTRY_GROUP_KEY = &registry.group&;主要是为了避免字符串硬编码。
上面有说过AbstractInterfaceConfig类,在该类中添加了一个字段private String registryG并且生成get/set方法,好让dubbo帮我们注入这个属性(见)。
服务消费端代码调整:
对ReferenceConfig(ReferenceBean的父类)的createProxy方法进行了调整,这个方法入参的map是ReferenceBean的所有参数K/V对。对该方法下面一段进行了调整:
&!--lang:java--&
else { // 通过注册中心配置拼装URL
List&URL& us = loadRegistries(false);
if (us != null && us.size() & 0) {
for (URL u : us) {
URL monitorUrl = loadMonitor(u);
if (monitorUrl != null) {
map.put(Constants.MONITOR_KEY, URL.encode(monitorUrl.toFullString()));
u=u.addParameterAndEncoded(Constants.REFER_KEY, StringUtils.toQueryString(map));
if(map.containsKey(Constants.REGISTRY_GROUP_KEY)){
u=u.addParameter(Constants.GROUP_KEY,map.get(Constants.REGISTRY_GROUP_KEY));
urls.add(u);
if (urls == null || urls.size() == 0) {
throw new IllegalStateException(&No such any registry to reference & + interfaceName
+ & on the consumer & + NetUtils.getLocalHost() + & use dubbo version & + Version.getVersion() + &, please config &dubbo:registry address=\&...\& /& to your spring config.&);
就是判断当前类有没有配置registryGroup,如果配置了添加到注册中心的分组属性中,那么这个服务就会从这个分组的注册中心去发现服务了。
服务提供方调整:
这部分是对AbstractInterfaceConfig的方法loadRegistries进行了调整,该方法是加载发布服务的注册中心URL,所以只需要在其返回的URL里面添加group参数即可。具体代码如下:
&!--lang:java--&
protected List&URL& loadRegistries(boolean provider) {
checkRegistry();
List&URL& registryList = new ArrayList&URL&();
if (registries != null && registries.size() & 0) {
for (RegistryConfig config : registries) {
String address = config.getAddress();
if (address == null || address.length() == 0) {
address = Constants.ANYHOST_VALUE;
String sysaddress = System.getProperty(&dubbo.registry.address&);
if (sysaddress != null && sysaddress.length() & 0) {
if (address != null && address.length() & 0
&& ! RegistryConfig.NO_AVAILABLE.equalsIgnoreCase(address)) {
Map&String, String& map = new HashMap&String, String&();
appendParameters(map, application);
appendParameters(map, config);
map.put(&path&, RegistryService.class.getName());
map.put(&dubbo&, Version.getVersion());
map.put(Constants.TIMESTAMP_KEY, String.valueOf(System.currentTimeMillis()));
if (ConfigUtils.getPid() & 0) {
map.put(Constants.PID_KEY, String.valueOf(ConfigUtils.getPid()));
if (! map.containsKey(&protocol&)) {
if (ExtensionLoader.getExtensionLoader(RegistryFactory.class).hasExtension(&remote&)) {
map.put(&protocol&, &remote&);
map.put(&protocol&, &dubbo&);
List&URL& urls = UrlUtils.parseURLs(address, map);
for (URL url : urls) {
url = url.addParameter(Constants.REGISTRY_KEY, url.getProtocol());
url = url.setProtocol(Constants.REGISTRY_PROTOCOL);
if ((provider && url.getParameter(Constants.REGISTER_KEY, true))
|| (! provider && url.getParameter(Constants.SUBSCRIBE_KEY, true))) {
if(!StringUtils.isEmpty(this.getRegistryGroup())){
url=url.addParameter(Constants.GROUP_KEY,this.getRegistryGroup());
registryList.add(url);
return registryL
到此,关于这方案的介绍基本完毕。这种就可以使得每个环境在一个独立的注册中心的分组中,可以很好的维护,并且发布服务不会凌乱,对服务的配置即可以全局设置,也可以对单个服务进行配置。基本上满足了环境隔离的需要。
欢迎大家对这些方案提出自己的观点,进行相互交流。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:12872次
排名:千里之外
转载:20篇
(4)(14)(8)java web dubbo(1)
dubbo由于很多jar包无法下载到而在导入后存在大量错误。这里记录一下解决方案。
& & & & 1、通过maven安装alibaba open parent。地址/alibaba/opensesame。通过mvn install在下载的opensesame路径下进行安装
& & & & 2、修改maven镜像为/alibaba/dubbo/issues/22
   这两部操作做了以后,dubbo源码环境就搭建好了
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:34198次
积分:1034
积分:1034
排名:千里之外
原创:71篇
评论:16条
(7)(6)(10)(8)(17)(4)(1)(5)(5)(8)深入理解Java微服务架构Dubbo系列—— 第二回 搭建dubbo-demo环境
一旦提到某某架构,可能很多人的第一感觉就是:这个东西很复杂,很难实际操作。其实不然,只要获得对的资料,搭建自己的dubbo框架并不是一件难事,不过由于历史原因,很多资料过于老旧,引用的文档也已经被废弃,所以从零搭建自己的Dubbo框架,可能会遇到不少问题,如果不是老司机,很容易翻车中途放弃。
本文的目的就是一步一步带您搭建出一个可用于生产环境的Dubbo代码框架。这个过程,会分三个步骤完成。
阶段一 基于本地调用的dubbo框架
改造官方Demo,精简demo项目,使得工程最后仅包括一个 service-provider,和 service-consumer 。Provider是服务提供者,通过开放Http端口,等待请求到来。Consumer 是服务调用着,通过Http请求调用服务。这个阶段,调用仅仅是本地调用,我们只有一个服务提供者,和一个服务消费者,消费者通过指定本地URL的方式调用提供者。
Created with Rapha?l 2.1.0service-consumerHTTP Local Callservice-provider
阶段二 基于Zookeeper注册中心的dubbo框架
但是dubbo框架不仅仅调用本地服务,它更强大的是,利用注册中心,调用远端服务,同时提供一系列的机制,实现服务发现,负载均衡等。注册中心的实现有很多中,本文采用Zookeeper作为注册中心,注册中心的工作原理大概可以用下面的时序图描述:
Created with Rapha?l 2.1.0consumerconsumerRegistery (ZK)Registery (ZK)providerprovider注册服务查找服务服务调用调用返回
该图只是最简单的情况,真实场景中,会有多个服务提供者,也会有多个消费者,组成交叉式的调用关系。
然后,我们会安装服务监控器,dubbo-monitor-simple, 有了它,所有的服务提供者和消费者的状态,都可以一览无遗。
monitor还有会把调用统计数据,用各种丰富的表格展示出来,真实屌炸天的东西。
好吧,那就开始吧!vcD4NCjxoMiBpZD0="基于本地调用的dubbo代码框架">基于本地调用的dubbo代码框架
1. GitHub 上Clone最新代码:
git clone /alibaba/dubbo.git dubbo
git checkout master
or: git checkout -b dubbo-2.4.0
2. 导入demo工程
2.1拷贝项目
如果按照官方例子,导入所有的工程,并不是很好的方案,在实际生产环境下,我们也不希望维护那么多类库工程。所以这里我只拷贝demo工程到另外一个目录下。
cp -R ./dubbo/dubbo-demo ./
cd dubbo-demo
这里涉及到的目录结构如下 dubbo-demo dubbo-demo-api dubbo-demo-provider dubbo-demo-consumer pom.xml
其中api工程声明了 Service 提供的接口,provider 实现了 api 接口,并对外开放http端口,consumer依赖 api 工程,但是不会直接依赖provider工程。 这种可以让消费者仅仅依赖api工程,而不需要对provider工程的依赖,也是松耦合的经典。
2.2修改POM文件
在这里我们会修改 dubbo-demo 根pom,去掉它的parent设置,让它成为独立的工程,同时配置它所依赖的项目。
简而言之,就是去掉
中的内容,然后修改后的pom头部如下:
com.alibaba
2.5.4-SNAPSHOT
dubbo-demo
${project.artifactId}
修改相关依赖,核心思想就是把dubbo源代码中根pom的相关依赖复制过来,并且最重要的,加上
com.alibaba
通过这样的方式,你已经把dubbo通过maven依赖的方式放在工程里了,完全不需要用引入官方工程的方式做项目依赖。
在Eclispe中(笔者使用的是,STS),File - Import - Exisiting Maven Projects
的方式导入工程。
3. 修复依赖工程不存在的错误
刚刚导入的consumer 和 provider工程可能会有如下错误:
可以在项目依赖中,删除这些项目,其实他们已经不需要了。
4. 导出conf目录
对于consumer 和 provider工程,有一个很重要的文件,dubbo.properties, 默认情况下,dubbo框架会加载这个文件,这个文件打包在
src/main/assembly/conf
需要手动导出这个目录到Classpath,否则程序运行找不到dubbo配置文件。
5. 修改 dubbo.properties
该文件中,定义了注册中心,是一个不生效的地址,所以要把它禁止掉。这个文件的配置十分重要,后续出现的相关配置会再次提到这个文件。
#dubbo.registry.address=multicast://224.5.6.7:1234
#dubbo.registry.address=zookeeper://127.0.0.1:2181
#dubbo.registry.address=redis://127.0.0.1:6379
#dubbo.registry.address=dubbo://127.0.0.1:9090
dubbo.registry.address=N/A
注释掉那些默认的注册地址,把它改成N/A. 在测试环境中,也需要修改这个文件
src/test/resources/dubbo.properties
6. 运行DemoProvider.main
如果工程没有其他问题,可以启动服务。如果成功会在Console中打印
[ 23:14:37] Dubbo service server started!
7. 运行 Consumer.main
在运行支持有一件事,要处理,否则会出现无法找到服务。
打开文件:
src/main/resources/META-INF/spring/dubbo-demo-consumer.xml
会看到一行引用声明:
在Consumer工程中,正是用这样声明的方式定义所需的微服务的,它通过ProxyFactoryBean的方式,封装了内部真正的实现。这个细节后面会深入探讨。
这里的问题是,我们没有启动注册中心,所以会出现服务不能被调用的异常。所以这里,在声明中,指定我们要调用的服务URL,修改成如下:
然后启动:DemoConsumer.main
如果一切顺利,会出现如下输出。
[ 23:14:37] Dubbo service server started!
[08:10:24] Hello world0, request from consumer: /192.168.0.100:62146
[08:10:26] Hello world1, request from consumer: /192.168.0.100:62146
[08:10:28] Hello world2, request from consumer: /192.168.0.100:62146
到这里,一份完全基于本地调用,禁用了注册中心的微服务程序框架就建立起来了。其实在开发环境下,我们完全可以仅仅使用基于本地的调用,在测试环节和生产环节,可以通过替换配置文件的方式采用注册中心的方式部署。 本地调用方式更方便调试。采用注册中心的方式开发,如果采用统一注册中心,程序员A做本地开发,可能会调用其他人的程序,如果每人用不同的注册中心,这样会提高开发成本,毕竟开发过程中,我只希望我的 Consumer 调用我本地的 Provider.
基于注册中心的dubbo代码框架
关于官方给出的三种注册中心安装方法, 本文将使用Zookeeper作为 registry center.
1. 安装 Zookeeper
wget /zookeeper/zookeeper-3.4.9/zookeeper-3.4.9.tar.gz
tar zxvf zookeeper-3.4.9.tar.gz
cd zookeeper-3.4.9/conf
cp zoo_sample.cfg zoo.cfg
vi zoo.cfg
- edit: dataDir=/Users/Vic/data/zookeeper
[~/zookeeper-3.4.9]$ ./bin/zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /Users/Vic/zookeeper-3.4.9/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
2. 配置 Zookeeper 注册中心
修改所有的 dubbo.properties, 之前我们使用 N/A 禁用了注册中心,现在我们使用zookeeper的方式。
dubbo.registry.address=zookeeper://127.0.0.1:2181
#dubbo.registry.address=N/A
再次启动服务,这次Console输出的log有很多不同,说明已经是通过Zookeeper注册中心了。
[14/09/16 09:08:13:013 CST] main
INFO zookeeper.ZooKeeper: Client environment:os.arch=x86_64
[14/09/16 09:08:13:013 CST] main
INFO zookeeper.ZooKeeper: Client environment:os.version=10.11.6
[14/09/16 09:08:13:013 CST] main
INFO zookeeper.ZooKeeper: Client environment:user.name=Vic
[14/09/16 09:08:13:013 CST] main
INFO zookeeper.ZooKeeper: Client environment:user.home=/Users/Vic
[14/09/16 09:08:13:013 CST] main
INFO zookeeper.ZooKeeper: Client environment:user.dir=/Users/Vic/dubbo/dubbo-demo/dubbo-demo-provider
[14/09/16 09:08:13:013 CST] main
INFO zookeeper.ZooKeeper: Initiating client connection, connectString=127.0.0.1:2181 sessionTimeout=30000 watcher=org.I0Itec.zkclient.ZkClient@1c32386d
[14/09/16 09:08:13:013 CST] main-SendThread()
INFO zookeeper.ClientCnxn: Opening socket connection to server /127.0.0.1:2181
[14/09/16 09:08:13:013 CST] main-SendThread(localhost:2181)
INFO zookeeper.ClientCnxn: Socket connection established to localhost/127.0.0.1:2181, initiating session
[14/09/16 09:08:13:013 CST] main-SendThread(localhost:2181)
INFO zookeeper.ClientCnxn: Session establishment complete on server localhost/127.0.0.1:2181, sessionid = 0xa0000, negotiated timeout = 30000
[14/09/16 09:08:13:013 CST] main-EventThread
INFO zkclient.ZkClient: zookeeper state changed (SyncConnected)
[14/09/16 09:08:13:013 CST] main
INFO zookeeper.ZookeeperRegistry:
[DUBBO] Register: dubbo://192.168.0.100:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&dubbo=2.5.3&interface=com.alibaba.dubbo.demo.DemoService&loadbalance=roundrobin&methods=sayHello&owner=william&pid=4539&side=provider&tamp=7, dubbo version: 2.5.3, current host: 127.0.0.1
[14/09/16 09:08:13:013 CST] main
INFO zookeeper.ZookeeperRegistry:
[DUBBO] Subscribe: provider://192.168.0.100:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&category=configurators&check=false&dubbo=2.5.3&interface=com.alibaba.dubbo.demo.DemoService&loadbalance=roundrobin&methods=sayHello&owner=william&pid=4539&side=provider&tamp=7, dubbo version: 2.5.3, current host: 127.0.0.1
[14/09/16 09:08:13:013 CST] main
INFO zookeeper.ZookeeperRegistry:
[DUBBO] Notify urls for subscribe url provider://192.168.0.100:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&category=configurators&check=false&dubbo=2.5.3&interface=com.alibaba.dubbo.demo.DemoService&loadbalance=roundrobin&methods=sayHello&owner=william&pid=4539&side=provider&tamp=7, urls: [empty://192.168.0.100:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&category=configurators&check=false&dubbo=2.5.3&interface=com.alibaba.dubbo.demo.DemoService&loadbalance=roundrobin&methods=sayHello&owner=william&pid=4539&side=provider&tamp=7], dubbo version: 2.5.3, current host: 127.0.0.1
[14/09/16 09:08:13:013 CST] main
INFO container.Main:
[DUBBO] Dubbo SpringContainer started!, dubbo version: 2.5.3, current host: 127.0.0.1
[ 09:08:13] Dubbo service server started!
同样的方式修改consumer工程的 dubbo 配置,然后我们启动consumer的main.
不过在此之前,我们是调用的本地服务,指明了服务的URL,这里我们要把这个指定去掉,通过注册中心找到服务。
所以修改 service 引用如下:
启动DemoConsumer.main
[14/09/16 12:57:03:003 CST] main
INFO zookeeper.ZookeeperRegistry:
[DUBBO] Notify urls for subscribe url provider://10.0.1.46:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&category=configurators&check=false&dubbo=2.5.3&interface=com.alibaba.dubbo.demo.DemoService&loadbalance=roundrobin&methods=sayHello&owner=william&pid=11433&side=provider&tamp=2, urls: [empty://10.0.1.46:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&category=configurators&check=false&dubbo=2.5.3&interface=com.alibaba.dubbo.demo.DemoService&loadbalance=roundrobin&methods=sayHello&owner=william&pid=11433&side=provider&tamp=2], dubbo version: 2.5.3, current host: 127.0.0.1
[14/09/16 12:57:03:003 CST] main
INFO container.Main:
[DUBBO] Dubbo SpringContainer started!, dubbo version: 2.5.3, current host: 127.0.0.1
[ 12:57:03] Dubbo service server started!
[12:57:10] Hello world0, request from consumer: /10.0.1.46:56078
其实,如果对zookeeper的原理少有了解的话,可以进入 zkclient查看当前节点.
ls /dubbo/*.DemoService/providers
[dubbo%3A%2F%2F10.0.1.46%3A20880%2Fcom.alibaba.dubbo.demo.DemoService%3Fanyhost%3Dtrue%26application%3Ddemo-provider%26dubbo%3D2.5.3%26interface%3Dcom.alibaba.dubbo.demo.DemoService%26loadbalance%3Droundrobin%26methods%3DsayHello%26owner%3Dwilliam%26pid%3D11433%26side%3Dprovider%26timestamp%3D2]
其实服务的Provider定义,就是在zookeeper节点的数据上。
3. 配置监控中心
当服务的提供者有很多,而消费者也有很多的时候,管理这些服务会十分棘手,所以官方提供了一个Monitor项目,通过配置,启动后,可以在中,查看服务提供者和消费者的所有状态。
可以使用 mvn 在 dubbo 根目录方式执行 install 的方式生产 dubbo-monitor-simple. 然后解压。
cd ./dubbo-monitor-simple-2.5.3/conf
edit dubbo.properties
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.jetty.port=8088 //配置访问端口
../bin/start.sh
启动后,可以通过 127.0.0.1:8088 直接访问监控中心。
里面也可以查询所有服务调用的状态,并且提供图表的方式
阅读源代码的方式,分析dubbo核心的实现原理。

我要回帖

更多关于 dubbo和zookeeper环境 的文章

 

随机推荐