新年第一篇博文, 接着和大家分享 springcloud 相关内容; 本次主要内容是使用 cloud 结合 zookeeper 作为注册中心来搭建服务调用, 前面几篇文章有涉及到另外的 eureka 作为注册中心, 有兴趣的朋友会回顾下上几篇文章.
springcloud 版本说明
docker 快速启动一个 zookeeper 服务
zk-server 服务提供者
zk-client 服务消费者
启动多个 zk-server 服务提供者
Git 源码地址:
springcloud 版本说明
由于市面上其版本比较多, 版本不一可能造成了读者尝试时版本问题, 所以这里指明当前作者写文章时使用的 cloud 版本
springboot 版本:
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>2.0.7.RELEASE</version>
- <relativePath/> <!-- lookup parent from repository -->
- </parent>
springcloud 版本:
- <properties>
- <java.version>1.8</java.version>
- <spring-cloud.version>Finchley.SR2</spring-cloud.version>
- </properties>
docker 快速启动一个 zookeeper 服务
就我个人而言通常使用 docker 来运行启动一些第三方的服务, 这里也用她来启动 zk, 首先 pull 镜像:
- docker pull zookeeper
- docker run --name zookeeper -p 2081:2181 -d zookeeper
- docker logs dd51008f9f8f
一般采用默认镜像的配置即可启动, 这里来看下启动后 logs 日志的部分截图:
能够看到镜像启动时读取了内置的 zoo.cfg 配置文件, 并且 zookeeper 当前版本是 3.4, 我们使用可视化工具 ZooInspector 连接 zookeeper, 能够直观的看到如下默认节点信息:
目前看我们只有一个 node 节点, 试想一下如果用 zk 作为注册中心, 这里应该会有至少两个大节点, 一个服务提供这节点, 一个消费者注册的节点, 下面会通过程序来创建.
zk-server 服务提供者
在 zk-server 工程中, 这里先创建 zk 的服务提供者节点, 在 pom 工程中需要如下配置:
- <!--zk-->
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
- </dependency>
- <!--zk 工具包 -->
- <dependency>
- <groupId>org.apache.zookeeper</groupId>
- <artifactId>zookeeper</artifactId>
- <version>3.4.13</version>
- <exclusions>
- <exclusion>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-log4j12</artifactId>
- </exclusion>
- <exclusion>
- <groupId>log4j</groupId>
- <artifactId>log4j</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
上面 pom 分了两步, 第一个是 springcloud 使用 zk 做服务注册发现用的, 第二个相当于连接 zk 服务的客户端包; 然后在程序启动入口出增加注解 @EnableDiscoveryClient
值得注意的是这里指定了 zk 服务的版本号 3.4.13, 就目前个人遇到的情况看, 连接 zk 的客户端尽量和 zk 服务端版本保持一致, 避免造成版本问题; 作为一个服务提供端 (server), 我们还需要有一个暴露出去的接口服务, 我这里定义如下接口:
- @RestController
- public class UserController {
- @Value("${server.port}")
- private int port;
- @GetMapping("/list")
- public List<MoUser> getList() {
- return new ArrayList<MoUser>() {
- {
- add(new MoUser(1, "shenniu001_" + port));
- add(new MoUser(2, "shenniu002_" + port));
- add(new MoUser(3, "shenniu003_" + port));
- }
- };
- }
- }
通过接口把服务启动的端口返回出去, 来达到区分不同接口的作用. 有了接口代码后, 还剩下连接 zk 服务的一些列配置, application.YAML 中的配置信息如:
- spring:
- application:
- name: zk-server
- cloud:
- zookeeper:
- connect-string: localhost:2081
- discovery:
- register: true
- enabled: true
- instance-id: 1
- root: /shenniu
- server:
- port: 6061
参数的简单说明:
connect-string: 连接 zk 服务的连接串
register: 是否启动服务注册
instance-id: zk 唯一 id 的标识
root: zk 根节点名称, 默认 / services
有了如上的配置, 我们就能够启动 zk-server 程序了; 首先访问暴露的接口正常:
然后再查看可视化视图工具 ZooInsector 有如下新增信息:
这个时候能够说明 zk-server 服务往 zk 服务端注册成功了, zk 服务端节点上包含了 zk-server 服务的一些基本信息, 如: ip, 端口, 名称; 这些是服务注册与发现的基本信息
zk-client 服务消费者
在 zk-client 工程中, 服务消费者的 pom 配置与生产者很像, 这里为了方便用了 feign 来访问服务端, 如下 pom 配置:
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-feign</artifactId>
- <version>1.4.6.RELEASE</version>
- </dependency>
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
- </dependency>
- <dependency>
- <groupId>org.apache.zookeeper</groupId>
- <artifactId>zookeeper</artifactId>
- <version>3.4.13</version>
- <exclusions>
- <exclusion>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-log4j12</artifactId>
- </exclusion>
- <exclusion>
- <groupId>log4j</groupId>
- <artifactId>log4j</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
同样需要执行具体的 zk 服务端的版本, 以及排除冲突的 log 包; 因为用了 feign 工具来访问, 所以需要在程序入口出增加如下注解:
- @SpringBootApplication
- @EnableDiscoveryClient
- @EnableFeignClients
- public class ZkClientApplication {
- public static void main(String[] args) {
- SpringApplication.run(ZkClientApplication.class, args);
- }
- }
然后创建一个 service 层并创建接口 IUserService, 通过 @FeignClient 注解的实现访问服务提供者的接口:
- @Service
- @FeignClient("zk-server")
- public interface IUserService {
- @GetMapping("/list")
- List<MoUser> getList();
- }
zk-client 端我想把服务提供端 zk-server 返回的信息直接输出到浏览器上, 如下代码:
- @RestController
- public class UserController {
- @Autowired
- protected IUserService userService;
- @GetMapping("/list")
- public List<MoUser> getList() {
- return userService.getList();
- }
- }
来到这里, 剩余的就是在 application.YAML 中配置连接 zk 服务端的配置:
- spring:
- application:
- name: zk-client
- cloud:
- zookeeper:
- connect-string: localhost:2081
- discovery:
- register: true
- enabled: true
- instance-id: 1
- root: /shenniu
- server:
- port: 7061
如果细心能够发现 zk-client 和 zk-server 的 zk 服务配置信息基本一致, 其实不管是服务提供者还是服务消费者, 都是作为 zk 服务的客户端来使用, 并且都把自己的服务访问信息上传注册给 zookeeper 注册中心的; 启动 zk-client 项目, 访问接口能够成功响应出 zk-server 接口返回的信息:
启动多个 zk-server 服务提供者
上面一个 zk-server(服务提供者), 一个 zk-client(服务消费者) 在实际场景中很少见, 一般服务提供者都是部署在多台机子或虚拟机中 (当然 zk 服务集群不在本次考虑范围), 因此这里通过 idea 启动多个不同端口的 zk-server 来实验下并测试 feign 的负载均衡是否可用.
分别启动 6061,6062,6063 的 zk-server 端口服务, 这里我注释了 instance-id: 1 节点, 采用自动生成的 id:
然后在浏览器中访问 zk-client, 刷新多次看下接口返回信息, 能够看到轮询效果:
来源: https://www.cnblogs.com/wangrudong003/p/10362387.html