1. 概述
1.1 分布式服务框架的两种组合
- Dubbo(轻量级RPC框架)+Zookeper(服务注册中心)。
- Spring Cloud Netflix Eureka(REST调用,是Spring Cloud的服务注册中心)
1.2 Dubbo概述
Dubbo时Alibaba开源的分布式服务调用框架(RPC-Remote Procedure Call),它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦(或者最大程度地松耦合)。从服务模型的角度来看,Dubbo采用的是一种非常简单的模型,要么是提供方Provider提供服务,要么是Consumer消费方拿到注册中心里Provider的地址列表去消费服务。
Container是Dubbo的服务容器。容器启动时,加载并运行服务提供方Provider。Provider在启动过程中,会将自己能提供的服务信息注册到服务注册中心Registry(也就是Zookeeper)中。而服务消费者Consumer在启动过程中会向注册中心订阅需要的服务,注册中心会将Consumer需要的服务所在的地址列表返回(这个列表是动态更新的,也就是说如果服务发生变更,注册中心会基于长连接把变更推送给Consumer)。Conusmer需要对应服务时,就轮询(或其他负载均衡机制)地址列表去远程调用某一个Provider。如果发生失败,就调用地址列表中同服务的其他提供者,直到调用成功。Monitor是Dubbo的监控中心,Provider和Consumer的行为(如调用次数、调用时间)定时被发送给Monitor。
2. 整合Dubbo到Spring Boot工程中使用
2.1 搭建服务注册中心Zookeeper
- 使用Docker下载Zookeeper
#下载zookeeper docker pull registry.docker-cn.com/zookeeper #检查 docker images
- 使用Docker运行Zookeeper
#zookeeper官方在docker hub上明确说明镜像已经暴露了2181(ZooKeeper客户端连接端口)、2888(Follower端口)、3888(选举端口) docker run --name myzookeeper --restart always -d registry.docker-cn.com/zookeeper #检查 docker ps
2.2 整合Dubbo到Spring Boot工程中使用
-
这个实验因为要使用Dubbo的RPC功能,需要创建两个工程:服务提供者Provider和服务消费者Consumer(可以用一个Empty Project,把它们作为Model组织起来,便于查看)。
-
使用Spring Initializer创建2个子工程(一个Provider,一个Consumer),都先引入Web模块(仅为了方便测试)。
-
服务提供者Provider进行四步操作发布服务:
(1)在服务提供者Proider工程的pom.xml中引入Dubbo启动器依赖:<dependency> <groupId>com.alibaba.boot</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>0.1.0</version> </dependency>
Dubbo要操作Zookeeper,再引入Zookeeper的客户端工具依赖:
<dependency> <groupId>com.github.sgroschupf</groupId> <artifactId>zkclient</artifactId> <version>0.1</version> </dependency>
(2)在服务提供者Provider工程的主配置文件中进行Dubbo相关配置。
#当前应用的名字 dubbo.application.name=provider-ticket #服务注册中心的位置 dubbo.registry.address=zookeeper://xxx.xxx.xxx.xxx:2181 #将哪个包下的什么东西进行注册(这样写,是将me.zj.ticket.service包下的所有服务注册) dubbo.scan.base-packages=me.zj.ticket.service
(3)给dubbo.scan.base-packages配置的包下要注册的服务实现类xxxServiceImpl(也就是说需要声明接口xxxService)标注@Component和@Service,注意这个@Service注解来自com.alibaba.dubbo.config.annotation包。
import com.alibaba.dubbo.config.annotation.Service; @Service @org.springframework.stereotype.Service public class TickServiceImpl implements TicketService { @Override public String getTicket() { return "《测试RPC调用》"; } }
(4)启动这个服务提供者Provider工程。
-
服务消费者Consumer进行五步远程调用指定服务:
(1)在服务消费者Consumer工程的pom.xml中引入Dubbo启动器依赖和zkclient依赖。
(2)在服务消费者Consumer工程的主配置文件中进行Dubbo相关配置。dubbo.application.name=consumer-user #一定是和提供方同一个服务注册中心地址,要能找到 dubbo.registry.address=zookeeper://xxx.xxx.xxx.xxx:2181
(3)引用服务核心步骤一:在服务消费放Consumer工程中放一份一模一样的服务提供方Provider中标注@Service的实现类的接口(注意:包结构必须是一样的,因为在服务发布时,在服务注册中心里就是按照接口的全限类名注册的,那使用的时候也要按照全限类名匹配使用)。
【正好通过这个问题说明了,将工程中所有的api打成jar包再引用进每个工程是多么必要】(4)引用服务核心步骤二:在服务消费者Consumer工程的服务类ConsumerService中,使用@Reference(com.alibaba.dubbo.config.annotation)标注服务提供方ProviderService的接口引用(面向接口,通过上一步已经可以在工程中使用了),就可以在自己定义的方法中远程调用其实现类ProviderServiceImpl的方法。
import com.alibaba.dubbo.config.annotation.Reference; import me.zj.ticket.service.TicketService; import org.springframework.stereotype.Service; @Service public class UserService { @Reference TicketService ticketService; public void sayHello(){ System.out.println("调用成功:"+ticketService.getTicket()); } }
(5)启动这个服务消费者Consumer工程测试远程调用是否通路。