Dubbox 是一个分布式服务框架,其前身是阿里巴巴开源项目Dubbo ,被国内电商及互联网项目中使用,后期阿里巴巴停止了该项目的维护,当当网便在Dubbo基础上进行优化,并继续维护,为了与原有的Dubbo区分,故将其命名为Dubbox。
Dubbox 致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。简单的说,dubbox就是个服务框架,如果没有分布式的需求,其实是不需要用的,只有在分布式的时候,才有dubbox这样的分布式服务框架的需求,并且本质上是个服务调用的东东,说白了就是个远程服务调用的分布式框架。
Provider: 暴露服务的服务提供方。
Consumer: 调用远程服务的服务消费方。
Registry: 服务注册与发现的注册中心。
Monitor: 统计服务的调用次调和调用时间的监控中心。
Container: 服务运行容器。
官方推荐使用 ZooKeeper 注册中心。注册中心负责服务地址的注册与查找,相当于目录服务,服务提供者和消费者只在启动时与注册中心交互,注册中心不转发请求,压力较小。
ZooKeeper 是 Apacahe Hadoop 的子项目,是一个树型的目录服务,支持变更推送,适合作为Dubbox 服务的注册中心,工业强度较高,可用于生产环境。
由于ZooKeeper是依赖于Java普通的,所以要安装对应版本的jdk。ZooKeeper可以安装到Windows平台下,也可以安装到Linux上。下边是对应两个平台的安装教程:
由于本人是使用的阿里云云服务器ECS来安装ZooKeeper的,这里记录下怎么通过SSH远程连接云服务器以及怎么安装ZooKeeper。
~/.ssh
目录下云服务器ECS
-> 网络和安全
-> 密钥对
id_rsa.pub
文件。具体的操作流程可以参考下这篇文章:使用SSH密钥对远程登录阿里云云服务器
安装ZooKeeper前需要先安装jdk,阿里云有镜像市场,可以很方便地直接更换系统盘,选择公共镜像进行安装,常见的有LAMP镜像或者LNMP镜像。我安装的是LNMP镜像。
tar -zxvf zookeeper-3.4.6.tar.gz
该命令会在当前目录下生成一个压缩包的同名文件(无后缀名),然后将压缩包解压到该目录下。
3. 进入 zookeeper-3.4.6 目录,创建 data 文件夹
cd zookeeper-3.4.6
mkdir data
该文件夹用来存放ZooKeeper注册相关的数据。
4. 进入conf目录 ,把 zoo_sample.cfg 改名为 zoo.cfg(也可以直接复制zoo_sample.cfg这个文件并命名为zoo.cfg)
cd conf
mv zoo_sample.cfg zoo.cfg
因为Linux系统并没有命名专用的命令,所以使用mv这个移动文件的命令来进行重命名。如果是想要复制并命名一个文件,可以用下边的命令:cp zoo_sample.cfg zoo.cfg
5. 打开zoo.cfg , 修改 data 属性:dataDir=/root/zookeeper-3.4.6/data
这里的data指向我们刚刚创建的data文件夹,具体目录根据实际情况填写。在Linux里一般通过vi/vim进行修改文件,如下:
vim zoo.cfg
和vim相关的一些基本操作可以看下这篇文章:Linux笔记-怎么退出vi/vim编辑器
进入bin目录,输入以下命令:
./zkServer.sh start
结束命令是:
./zkServer.sh stop
查看状态的命令是:
./zkServer.sh status
在Maven的中央仓库中可以查找到Dubbo的最终版本是2.5.3 , 阿里巴巴解散了Dubbo团队后由当当网继续维护此项目,并改名为 Dubbox,虽然坐标没有改变,版本也更新了,但是并没有将Dubbox提交到中央仓库上,所以我们需要将Dubbox手动安装到本地仓库:
先将jar包放到某个目录下,接着打开cmd输入下边的命令,这里要注意-Dfile
的值要根据你的jar目录来填写:
mvn install:install-file -Dfile=d:\dubbo-2.8.4.jar -DgroupId=com.alibaba -DartifactId=dubbo -Dversion=2.8.4 -Dpackaging=jar
安装完毕后会看到BUILD SUCCESS
的提示。
dtd文件的在线地址: http://code.alibabatech.com/schema/dubbo/dubbo.xsd
Dubbox的jar包和离线的dtd文件和本Demo项目的源码打包在一块,可以在文章最后去下载。
下边是Eclipse中的配置方式:
Window -> Preferences -> XML -> XML Catalog -> Add… -> File System… -> 选中dtd文件 -> Key type选择Schema location -> 接着把Key的值改为http://code.alibabatech.com/schema/dubbo/dubbo.xsd -> 最后点确定
这样Eclipse就能对Dubbox进行自动提示了。
本Demo工程一共分为两部分,一部分是服务提供方dubboxdemo-service项目,一部分是服务消费方dubboxdemo-web项目。项目源码在GitHub上有,也可以直接在本文最后去下载。
dubboxdemo-service项目是服务提供方,项目里使用的@Service注解是dubbox框架里的,而不是spring框架的。这里如果导错包会导致服务发布失败而无法被服务消费方所调用。
请修改本项目里的spring配置文件applicationContext-service.xml
里的dubbox的ZooKeeper地址(host:port):
<dubbo:registry address="zookeeper://host:port" timeout="100000" />
dubboxdemo-web项目是服务消费方,同样需要修改配置文件springmvc.xml
里的dubbox的ZooKeeper地址(host:port);另外该项目需要使用到服务提供方的提供的接口,所以需要将dubboxdemo-service里的接口复制过来。之所以直接复制代码,而不是通过导包的方式,我猜想是因为dubbox框架本来就是将提供方和消费方进行解耦的,双方互相不知道对方的存在,统一在注册中心ZooKeeper这里进行注册,以便于交互管理。
在Controller类中,有UserService这个私有变量,该变量不能用@autowired等注解来注入,因为其实现类并不在该项目中,实现类在服务提供方的源码中,所以我们要用dubbo提供的@Reference这个注解来远程注入。
首先需要将部署在云服务器上的ZooKeeper启动,接着启动本地的dubboxdemo-service项目,最后启动dubboxdemo-web项目。
因为我们在pom里配置了Tomcat7的插件,所以启动项目的时候,可以直接在Eclipse里右键该项目,选择Run As
,接着选择Maven build...
,接着在Goals:
里输入tomcat7:run
,接着回车即可启动项目。第一次启动项目的时候需要填写这个配置,以后启动同一个项目只需要直接点击Maven build
就可以了,它会自动沿用之前的配置。
至于关闭服务就简单了,直接点击Eclipse里的控制台Console里的红色方格按钮Terminate
就可以直接关闭项目了。因为启动了两个项目,所以需要两个都关闭掉才行。
在测试的时候遇到个问题,就是虽然云服务器上启动了ZooKeeper,也配置好了安全组策略,我配置的是允许全部协议访问云服务器,因为ZooKeeper用的是ZooKeeper协议。
但是我发现在启动了服务并访问dubboxdemo-web项目的时候,老是报连接超时的异常。在本地测试就没有这个问题,最后发现是因为云服务器上的防火墙导致的。我用的是CentOS 7.4,使用的防火墙是iptables,关闭命令如下:
service iptables stop
启动防火墙命令是service iptables start
,不过我发现防火墙规则里并没有任何内容,暂时也不清楚为什么启动了iptables就会导致ZooKeeper的端口被拦截。
在成功启动ZooKeeper、以及两个项目后,通过访问http://localhost:8082/user/name.do
,会返回一个页面,页面中是一段字符串,在我的项目里是让服务提供方直接返回字符串lewky
,所以我这里的页面上会得到lewky
这个字符串。
之所以这里是访问的8082端口,是因为在dubboxdemo-web项目的pom里设置了8082端口,另外dubboxdemo-service项目的pom里设置的是8081端口。
dubbo本身有个管理系统,可以很直观地看到注册中心中有哪些服务等内容,这个项目叫dubbo-admin
,百度就有,可以将其源码打成war包,然后丢到Tomcat的webapps目录下,接着启动Tomcat即可访问该项目。这个项目的war包我也一起打包到一块了,在下面的链接里可以下载。
说一下这个dubbo-admin,当你启动好Tomcat后,如果是在本地就访问http://localhost:8080/dubbo-admin/
,接着需要你输入账号密码,这个管理系统的账号密码都是root。
可以发现,在我们的服务提供方和服务消费方中使用到了重复的代码:UserService,服务消费方中通过持有UserService该接口,得以通过dubbox框架的@Reference进行远程注入。
这种写法其实并不好,因为两个项目中可能存在UserService代码不一致的情况,不利于维护,一个更好的写法,是将服务提供方和服务消费方共用的接口给提取出来,作为另外一个项目或者jar包来使用,这样就可以避免两端代码不一致的问题,同时也易于维护。因为这只是个简单的Demo,所以就不计较这些地方了,有兴趣的可以自己重新设计。