SpringBoot整合Dubbo+ZooKeeper——实现发布并访问远程服务
前言
什么是Dubbo?——开源分布式服务框架
Dubbo(读音[ˈdʌbəʊ])是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和Spring框架无缝集成。
Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。
什么是ZooKeeper?
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。
ZooKeeper的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。
ZooKeeper包含一个简单的原语集,提供Java和C的接口。
ZooKeeper代码版本中,提供了分布式独享锁、选举、队列的接口,代码在$zookeeper_home\src\recipes。其中分布锁和队列有Java和C两个版本,选举只有Java版本。
正文
一、下载Zookeeper
推荐去apache官网 zookeeper,各种版本都有,可以自己选择下载,本人用的是3.4.14这个版本
二、安装Zookeeper
下载解压后即可使用,将其放在自己喜欢的目录下就行
三、启动Zookeeper
启动zookeeper只需去安装目录下的bin目录里面,找到zkServer.cmd这个文件,双击即可启动
可能出现的问题1)黑窗口闪退
解决方案:
打开配置文件
2)双击启动,弹出命令行窗口之后,控制台报错
拷贝文件,修改文件名
修改后,此时目录下就已经有之前控制台报错说不存在的文件了
此时再去双击zkServer.cmd文件启动就不报错了
那么到此为止Zookeeper的下载、安装、启动都已经没有问题了,接下来就是去新建项目开始测试了
四、打开IDEA新建一个空项目
五、创建provider-server 和 consumer-server两个子模块
六、引入五个dubbo 和 zookeeper相关的jar包
1 <!-- 5个依赖jar包 --> 2 <!-- 引入Dubbo + zookeeper --> 3 <!-- https://mvnrepository.com/artifact/org.apache.dubbo/dubbo-spring-boot-starter --> 4 <dependency> 5 <groupId>org.apache.dubbo</groupId> 6 <artifactId>dubbo-spring-boot-starter</artifactId> 7 <version>2.7.3</version> 8 </dependency> 9 10 <!-- zkclient --> 11 <!-- https://mvnrepository.com/artifact/com.github.sgroschupf/zkclient --> 12 <dependency> 13 <groupId>com.github.sgroschupf</groupId> 14 <artifactId>zkclient</artifactId> 15 <version>0.1</version> 16 </dependency> 17 18 <!-- 日志冲突 --> 19 <!-- 引入zookeeper --> 20 <dependency> 21 <groupId>org.apache.curator</groupId> 22 <artifactId>curator-framework</artifactId> 23 <version>2.12.0</version> 24 </dependency> 25 <dependency> 26 <groupId>org.apache.curator</groupId> 27 <artifactId>curator-recipes</artifactId> 28 <version>2.12.0</version> 29 </dependency> 30 <dependency> 31 <groupId>org.apache.zookeeper</groupId> 32 <artifactId>zookeeper</artifactId> 33 <version>3.4.14</version> 34 <!-- 排除这个slf4j-log4j12 --> 35 <exclusions> 36 <exclusion> 37 <groupId>org.slf4j</groupId> 38 <artifactId>slf4j-log4j12</artifactId> 39 </exclusion> 40 </exclusions> 41 </dependency>
七、编写两个模块的配置文件
1)provider-server
1 # 配置项目的服务端口 2 server.port=8002 3 # 配置zookeeper 4 # 配置服务名 5 dubbo.application.name=provider-server 6 # 配置要发布到的注册中心地址 7 dubbo.registry.address=zookeeper://127.0.0.1:2181 8 # 配置要发布的服务包 9 dubbo.scan.base-packages=com.lzp.service
2)consumer-server
# 配置项目的服务端口 server.port=8001 # 消费者去哪里拿服务需要暴露自己的名字 dubbo.application.name=consumer-server # 配置注册中心的地址 dubbo.registry.address=zookeeper://127.0.0.1:2181
八、编写服务接口
provider-server项目提供了一个HelloService接口以及实现类
接口
1 package com.lzp.service; 2 3 // 对外提供的服务 4 public interface HelloService { 5 6 String sayHello(String name); 7 8 }
实现类
1 package com.lzp.service; 2 3 import org.apache.dubbo.config.annotation.Service; 4 import org.springframework.stereotype.Component; 5 6 /** 7 * @Author LZP 8 * @Date 2021/6/14 14:49 9 * @Version 1.0 10 */ 11 @Service // 发布服务:可以被扫描,项目启动之后就会被注册到注册中心去 12 @Component // 使用了Dubbo之后尽量不要用Service 13 public class HelloServiceImpl implements HelloService{ 14 @Override 15 public String sayHello(String name) { 16 return "Hello" + name; 17 } 18 }
补充说明
现在提供服务的一方已经将服务注册到注册中心zookeeper去了,接下来就是我们的调用方去注册中心调用提供方提供的服务接口了
九、场景:当consumer-server处理业务层的时候需要调用provider-server提供的服务时,这时就可以通过Dubbo这个开源Java RPC框架去实现远程过程调用
consumer-server的业务类。这里只举其中一个业务
UserService接口
1 package com.lzp.service; 2 3 // 用户业务接口层 4 public interface UserService { 5 6 String meet(String name); 7 8 }
UserServiceImpl类
1 package com.lzp.service; 2 3 import org.apache.dubbo.config.annotation.Reference; 4 import org.springframework.stereotype.Service; 5 6 /** 7 * @Author LZP 8 * @Date 2021/6/14 16:49 9 * @Version 1.0 10 */ 11 @Service 12 public class UserServiceImpl implements UserService{ 13 14 // 想要拿到provider-server提供的服务,要去注册中心拿到服务 15 @Reference // 引用,Pom坐标,可以定义类路径完全相同的接口 16 private HelloService helloService; 17 18 @Override 19 public String meet(String name) { 20 return helloService.sayHello(name); 21 } 22 }
此时就出现了一个问题,我们怎么拿到对方的接口呢?这里提供了一个解决方案:引用,Pom坐标,可以定义类路径完全相同的接口
HelloService接口
1 package com.lzp.service; 2 3 // 对应provider-server的一个已经注册到zookeeper注册中心的服务接口 4 public interface HelloService { 5 6 String sayHello(String name); 7 8 }
十、编写一个UserController类去测试
UserController类
1 package com.lzp.controller; 2 3 import com.lzp.service.UserService; 4 import org.springframework.beans.factory.annotation.Autowired; 5 import org.springframework.web.bind.annotation.GetMapping; 6 import org.springframework.web.bind.annotation.PathVariable; 7 import org.springframework.web.bind.annotation.RestController; 8 9 /** 10 * @Author LZP 11 * @Date 2021/6/14 19:54 12 * @Version 1.0 13 */ 14 @RestController 15 public class UserController { 16 17 @Autowired 18 private UserService userService; 19 20 @GetMapping("/meet/{name}") // 这里地址栏传参采用了RestFul风格 21 public String meet(@PathVariable String name) { 22 return userService.meet(name); 23 } 24 25 }
通过浏览器去直接请求地址 ==> localhost:8001/meet/LZP
注意:这里请求的是consumer-server项目,它的端口是8001