(项目以springboot进行开启与构建,注册中心采用zookeeper)
一、认识Dubbo
- Dubbo是一款高性能Java RPC框架,具体是什么来路,为什么要使用他可参考他的官方文档,里面包含了所有从介绍到上手使用的细节,本文着重于描述和总结使用springboot+dubbo+zookeeper开发一个实战案例,作为新手的快速起步。
- Dubbo出自阿里巴巴之手,现在开源给了Apache。
- 与其类似框架:springcloud
二、开始上手
2.1必须理解的概念:
2.1.1官方文档内容:
0、服务容器负责启动,加载,运行服务提供者。
1、服务提供者在启动时,向注册中心注册自己提供的服务。
2、服务消费者在启动时,向注册中心订阅自己所需的服务。
3、注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送
4、变更数据给消费者。
5、服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
6、服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
2.2.2流程概括
- 服务提供者provider(相当于以前的service层的实现)单独部署并运行在容器container内(tomcat之类);服务消费者consumer(相当于以前的controller)也单独部署运行,其中会调用service曾的一些服务进行消费,由于两者已进行分离并单独部署需要通过网络来进行调用和通信,我们称这样的调用为远程调用(RPC);
2.2.3疑问解答
-
既然需要相互通信,provider和consumer直接是如何相互知道对方的?
- 两者启动后向注册中心注册,两者通过注册中心registry注册和发现
-
我可以从哪里来检测所有的服务运行情况?
- 通过监控中心monitor来查看和管理。Dubbo2.6.0及之前,自带一个admin来帮助我们查看和管理所有注册在注册中心上的服务应用,在2.6.0以后统一整合为一套新的控制台“dubbo-ops”
-
由于controller和service实际开发已经分离,如何调用解决依赖问题?
- 通过单独构建一个接口项目service打包并在两者中进行依赖引入
-
dubbo支持多种注册中心,为什么一般都采用zookeeper?zk究竟起到什么作用?
- zookeeper作为一款本身支持分布式的、对分布式服务和应用进行协调管理的产品,完美解决了人为在分布式环境中协调和管理服务过程的复杂,本身的分布式还有利于服务的稳定(集群中一半以下节点宕机照样正常使用)。【但是本段解释也有问题,因为dubbo产生的原因是由于以前开发分布式系统采用各种注册中心配置的复杂,dubbo产生就是为了统一这些复杂性,通过简单配置即可完成分布式系统的比如服务注册等操作】
2.2开始demo开发
2.2.1确定目标
- 从前面的理解中,我们应该得到,相比以前做的后端项目(三层架构——控制层、服务层、持久化层)结构需要改变为/也是dubbo推荐的改为如下模式:建立三个项目provider、consumer、service,即:
1、服务消费者consumer项目——相当于以前的controller层做的事情
2、服务提供者provider项目——相当于以前的service层的实现类+dao/mapper持久层做的事情
3、service接口项目——相当于以前service层的接口,用于provider、consumer正常开发的依赖
2.2.2开始开发service接口项目
-
使用idea集成开发环境新建一个不带模板的maven项目(service项目仅用于打包并做另外两个项目的依赖,不用进一步部署,所以直接建立maven项目即可)
-
新建接口UserService,在com.toketec.dubboServiceDemo.service包下:
-
编写接口内容,这里定义一个返回User类型的接口方法getUser()
-
类型缺失?新建User类,在com.toketec.dubboServiceDemo.model包下面【以后一般需要用于项目之间进行传递的实体类(通常都是持久层与数据库打交道的类)也会存放在service接口项目中,provider、consumer项目进行依赖引入就可以一起引用该类型了】
-
注意,dubbo采用二进制进行传输,实体类必须实现序列化接口
-
实体类内定义一些字段和各种get\set\toString...
-
在刚刚的UserService接口中import User类
至此,service接口项目就完成了,下面打包安装即可在其他maven项目中直接引入,(你也可以找到maven本地仓库,找到对应的jar/war包单独复制到其他非maven构建的项目中作为依赖)。
-
打包安装:
安装成功:
2.2.3开发provider提供者项目
·使用idea集成开发环境新建一个springboot项目,带web起步依赖。(注意要等待项目自动构建加载完成,需要联网,如果卡主很久建议退出重新打开idea,重新打开新建的项目,maven可以换成阿里云镜像更快)
-
新建在com.toketec.dubboProviderDemo包下新建包service.impl,并新建实现类UserServiceImpl
-
实现UserService接口
-
缺少依赖?导入我们的接口项目所打包的依赖即可,在provider项目的pom文件的依赖中加入刚刚在service接口项目pom文件中的<groupId>等如下内容:
<dependency> <groupId>com.toketec</groupId> <artifactId>dubbo-serviceDemo</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
-
这里由于我们使用到了dubbo和zoookeeper的内容,我们顺便把他们的依赖也一起加入项目中,dubbo有针对Springboot的起步依赖,所以,我们添加如下内容:【注意,如果我们采用的Springboot是1.x.x版本,那么dubbo要采用1.0.0,若2.x.x那么采用2.0.0】
<dependency> <groupId>com.alibaba.spring.boot</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>2.0.0</version> </dependency> <dependency> <groupId>com.101tec</groupId> <artifactId>zkclient</artifactId> <version>0.10</version> </dependency>
-
添加完依赖,实现接口中的getUser方法,如果有数据库也可以整合并使用数据库内容。为了演示方便,这里我们直接返回一个指定的User对象id=10,age=100,name=小王,未来调用本服务的消费者就会得到这样一个User对象的数据。
-
在以前的ssm项目中,我们会在service的实现类上直接加上@Service注解表示是一个spring的bean,但是由于现在我们要采用的dubbo也有一个@Service注解来进行服务注册,冲突怎么办?好在Spring中@Service、@Controller、@Component等一些注解都本质没有任何区别,只是表面意思不同增加可读性,所以我们可以在本实现类上添加如下注解:
-
接下来进行配置,打开application.properties/yml即Springboot的核心配置文件,添加如下内容:
#本项目容器启动后的端口(tomcat端口) server.port=8080 #本应用的名字命名 spring.dubbo.application.name=dubbo-provider-demo #配置注册中心 #注册中心是真集群,存在多个节点,这样配置(ip和端口改成你自己配置的zookeeper地址和端口你也可以采用其他注册中心) spring.dubbo.application.registries[0].address=zookeeper://10.101.80.101:2181 spring.dubbo.application.registries[0].registry="reg1" spring.dubbo.application.registries[1].address=zookeeper://10.101.80.102:2181 spring.dubbo.application.registries[1].registry="reg2" spring.dubbo.application.registries[2].address=zookeeper://10.101.80.103:2181 spring.dubbo.application.registries[2].registry="reg3" #注册中心只有一个节点做测试的时候 #spring.dubbo.registry=zookeeper://10.101.80.101:2181 #配置service服务扫描所在包,告诉dubbo服务在哪里 spring.dubbo.scan=com.toketec.dubboProviderDemo.service
-
最后,在Springboot的main 方法所在类加上dubbo自动配置注解:
-
运行main方法,启动provider项目:
可以看到三个节点都连上了注册成功,tomcat也成功启动。
-
dubbo2.6提供的admin中可以看到我们注册的服务
2.2.4开发consumer消费者项目
·使用idea集成开发环境新建一个springboot项目,带web起步依赖。(注意要等待项目自动构建加载完成,需要联网,如果卡主很久建议退出重新打开idea,重新打开新建的项目,maven可以换成阿里云镜像更快)
-
在com.toketec.dubboConsumerDemo包中新建包controller,并新建一个UserController类
-
在UserController中写一个getMyUser()方法,要求对外暴露的url为“/getMyUser.do”、需要调用UserService的getUser()方法、同时采用json字符串进行返回(像以前ssm项目一样写,不再赘述)
-
缺少依赖?与上文中描述相同,引入我们的service接口项目的依赖即可,因为用的dubbo和zookeeper,这里顺便全部引入,上文已有描述,这里不再赘述
<dependency> <groupId>com.toketec</groupId> <artifactId>dubbo-serviceDemo</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>com.alibaba.spring.boot</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>2.0.0</version> </dependency> <dependency> <groupId>com.101tec</groupId> <artifactId>zkclient</artifactId> <version>0.10</version> </dependency>
-
如果是以前的ssm单独项目,接下来你可能会使用依赖注入方式注入UserService,但是,现在服务已经分离并单独部署,我们需要通过dubbo提供的方式来进行远程调用。
-
只需将以前的@Autowired注解改成dubbo提供的@Reference(version = "1.0")即可,版本号根据实际需要改变和增减。
-
-
接下来进行配置,打开application.properties/yml即Springboot的核心配置文件,配置的内容和上文配置provider完全一致【注意!server.port代表tomcat的端口,需要改成本机不被占用的端口我这里假设改成9090,否则无法使用,还有应用名也改成不同的,以作区分】,最终如下:
#本项目容器启动后的端口(tomcat端口) server.port=9090 #本应用的名字命名 spring.dubbo.application.name=dubbo-consumer-demo #配置注册中心 #注册中心是真集群,存在多个节点,这样配置(ip和端口改成你自己配置的zookeeper地址和端口你也可以采用其他注册中心) spring.dubbo.application.registries[0].address=zookeeper://10.101.80.101:2181 spring.dubbo.application.registries[0].registry="reg1" spring.dubbo.application.registries[1].address=zookeeper://10.101.80.102:2181 spring.dubbo.application.registries[1].registry="reg2" spring.dubbo.application.registries[2].address=zookeeper://10.101.80.103:2181 spring.dubbo.application.registries[2].registry="reg3" #注册中心只有一个节点做测试的时候 #spring.dubbo.registry=zookeeper://10.101.80.101:2181
-
最后,同样在Springboot的main 方法所在类加上dubbo自动配置注解:
-
运行main方法,启动consumer项目:
2.3开发完成,demo测试
2.3.1浏览器访问localhost:9090/getMyUser.do
(这里的端口就是consumer项目中定义的端口)
成功得到了正确的返回,证明我们的本个案例开发成功!
2.3.2可能踩得坑(来自https://blog.csdn.net/sly5400415/article/details/84953479)
1、实体类没有实现序列化
2、在提供者端使用的service注解是alibaba包的,不是springboot默认的
3、springbootparent最新会有兼容性问题,直接用demo的pom上的版本,成功了再去测试兼容性吧
4、pom中zookeeper的和自己下载的版本不一致
5、zookeeper集群没有搭建完好
6、使用过虚拟机的单位注意了,需要禁用虚拟网卡
7、注解上的version等设置是否一致