前言
入职前向师兄提问了应该学习点啥,师兄说应该学习一下dubbo,就有了这篇博客记录一下dubbo的简单使用。
dubbo整体架构看上去其实还算是比较简单的:
其中的provider和consumer其实就是一个一个服务,无非是一个提供服务,另外一个进行服务的调用。
而Registry可以使用redis,也可以使用zookeeper(推荐),Monitor是一个可有可无的存在,用来查看服务调用次数之类的,方便运维进行维护。
环境搭建
首先先需要测试一下dubbo作为一款高性能RPC框架,就在idea里面搭建了两个项目,一个是服务的提供者,另外一个是服务的调用者(消费者),springboot或者是普通的maven项目均可。这里首先用普通的spring项目作为案例。
服务提供者
一个是user-service-provider,能够提供服务,核心代码如下:
1 2 3 4 5 6 7 8 9 10
| public class UserServiceImpl implements UserService { @Override public List<UserAddress> getUserAddressList(String userId) { UserAddress userAddress1 = new UserAddress(1, "地址1", "userId1", "陈先生", "13312345678", "1"); UserAddress userAddress2 = new UserAddress(1, "地址2", "userId2", "陈女士", "13387654321", "2");
return Arrays.asList(userAddress1, userAddress2); } }
|
这里省略了利用ORM框架去数据库进行查询的过程,改为直接创建出对象并且进行返回。相关的实体类UserAddress如下:
1 2 3 4 5 6 7 8 9 10
| @Data @AllArgsConstructor public class UserAddress implements Serializable { private Integer id; private String userAddress; private String userId; private String consignee; private String phoneNumber; private String isDefault; }
|
服务调用者
1 2 3 4 5 6 7 8 9 10
| public class OrderServiceImpl implements OrderService {
UserService userService;
@Override public void initOrder(String userId) { List<UserAddress> userAddressList = userService.getUserAddressList("1"); } }
|
消费者显然就简单多了,它只需要调用对应的方法就可以了。
整合实体类和service
显然,在上面的项目中,想要使用UserService,必须要这个类(接口)本身就存在于对应的模块中,而如果让这些实体类和service(以及对应的实现)都在一个模块下,那么就又回到了最最原始的All in one阶段了,这显然违背了RPC框架的原则。

所以实际中一般都是创建一个模块(项目),这个模块保存所有的实体类和service(接口)等需要被别的模块依赖的东西,然后别的模块依赖它就可以了。
具体的实现都是放在对应的包里面的,而这个通用的模块仅仅存放接口声明。
dubbo介入
有了上面三个模块之后,简单的逻辑应该理清楚了,那么就可以按照dubbo推荐的流程开始了。
register
把服务提供者给注册(暴露)到注册中心中。
注册中心我用brew安装的zookeeper,而这个zookeeper默认占用8080端口(会和dubbo-admin冲突),可以在zoo.cfg中进行修改。
显然首先需要有dubbo的依赖,其次因为之后要使用zookeeper作为注册中心,所以需要对应的依赖去操作zookeeper。
1 2 3 4 5 6 7 8 9 10 11 12 13
| <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.6.2</version> </dependency>
<dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>2.12.0</version> </dependency>
|
依赖解决了之后,当然需要指定一下对应的注册中心地址、向外暴露的端口以及对应的协议(第4步invoke使用)、向外暴露的接口以及该接口对应的实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <?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://dubbo.apache.org/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo https://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<dubbo:application name="user-service-provider"/>
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<dubbo:protocol name="dubbo" port="20880"/>
<dubbo:service interface="cn.clp.service.UserService" ref="userService"/>
<bean id="userService" class="cn.clp.service.impl.UserServiceImpl"/> </beans>
|
然后正常启动spring项目就可以了。就可以在dubbo-admin中看到这个服务提供商了。
subscribe
消费者需要向注册中心进行依赖,那么相关的依赖也是不可少的。
消费者的逻辑就更简单的,只需要注册中心的地址、自己的名字以及自己希望调用的服务的名字即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <?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://dubbo.apache.org/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo https://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<dubbo:application name="order-service-consumer"/>
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<dubbo:reference id="userService" interface="cn.clp.service.UserService"/> </beans>
|
到这里,就相当于已经在容器中增加了UserService,并且这个最终的调用是通过dubbo为我们生成代理来进行真实调用的。
最后在进行相关的spring配置(包扫描)即可。
notify
这个是自动的,不需要写对应的代码
invoke
这个其实在第一步register和第二步subsrcibe的时候,因为已经配置了相关的调用,所以这一步其实已经完成了。
监控中心(可选)
2.7版本的dubbo的监控中心在文档中说,监控中心已经被整合到了dubbo-admin中,所以只需要安装对应的管理着控制台即可。
整合springboot
再使用springboot来进行一次整合,记录一下流程。
其实反而在整合springboot的时候遇到了很多奇奇怪怪的bug,这里记录下。
第一个就是dubbo和zookeeper客户端冲突的问题,会导致下面的错误:
1
| java.lang.ClassNotFoundException: org.apache.curator.framework.recipes.cache.TreeCacheListener
|
这其实就是dubbo和zookeeper客户端冲突的问题,我在springboot里面用curator的时候是自己去mvnrepo中找的,这个版本之间有冲突,这里提供一个没有冲突的解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <properties> <java.version>1.8</java.version> <dubbo.version>2.7.8</dubbo.version> <zookeeper.version>2.12.0</zookeeper.version> </properties>
<dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>2.7.8</version> </dependency>
<dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>${zookeeper.version}</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <version>${zookeeper.version}</version> </dependency>
|
改造消费者
消费者我把它改成了网页显示json数据,这样每当用户访问一次,就会进行一次RPC调用,并且直接把数据显示在网页中。
之前的consumer.xml里面的属性就可以直接写到application.properties里面去了。这里唯一会有疑惑的就是,这个UserService要怎么写呢?