引言

zookeeper是一个分布式协调工具,可以实现注册中心功能

CentOS安装zookeeper(docker安装)

下载Zookeeper镜像

  1. docker pull zookeeper:3.6.1

启动容器并添加映射

  1. docker run --privileged=true -d --name zookeeper -p 2181:2181 -d zookeeper:3.6.1

查看容器是否启动

  1. docker ps

启动zookeeper客户端

如果我们要启动zk的客户端,可以使用以下命令:

  1. docker exec -it 容器id zkCli.sh

springcloud整合zookeeper

创建cloud-provider-payment8092

改pom依赖

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <parent>
  6. <artifactId>cloud2020</artifactId>
  7. <groupId>com.sgy.cloud2020</groupId>
  8. <version>1.0-SNAPSHOT</version>
  9. </parent>
  10. <modelVersion>4.0.0</modelVersion>
  11. <artifactId>cloud-provider-payment8092</artifactId>
  12. <dependencies>
  13. <dependency>
  14. <groupId>com.sgy.cloud2020</groupId>
  15. <artifactId>cloud-provider</artifactId>
  16. <version>${project.version}</version>
  17. </dependency>
  18. <!--springcloud整合zookeeper-->
  19. <dependency>
  20. <groupId>org.springframework.cloud</groupId>
  21. <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
  22. </dependency>
  23. <dependency>
  24. <groupId>org.projectlombok</groupId>
  25. <artifactId>lombok</artifactId>
  26. <scope>provided</scope>
  27. </dependency>
  28. </dependencies>
  29. </project>

主启动类

/**
 * Created by AaronShen on 2020/5/27
 */
@SpringBootApplication
// 整合consul和zookeeper都需要这个注解
@EnableDiscoveryClient
public class PaymentMain8092 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8092.class,args);
    }
}

改配置yml

server:
  port: 8092

spring:
  application:
    name: cloud-payment-server
  datasource:
    username: blog
    password: 123456
    url: jdbc:mysql://192.168.200.10:3306/cloud?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&serverTimezone=GMT%2B8
    driver-class-name: com.mysql.cj.jdbc.Driver
    # 使用我们自己的druid数据源
    type: com.alibaba.druid.pool.DruidDataSource

    initialSize: 10 #初始化连接个数
    minIdle: 5    #最小连接个数
    maxActive: 500 #最大连接个数
    maxWait: 60000 #最大等待时间
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true
    #   配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
    filters: stat,wall,log4j
    maxPoolPreparedStatementPerConnectionSize: 20
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

  cloud:
    zookeeper:
      connect-string: 192.168.200.10:2181


mybatis:
  # config-location和configuration不能同时配置,否则会抛出异常
  # 一般只配置configuration即可,会自动找到mybatis全局配置文件
  #  config-location: classpath:mybatis/mybatis-config.xml
  mapper-locations: classpath:mapper/*Mapper.xml
  # 对应实体类的路径,只能指定具体的包,多个配置可以使用英文逗号隔开
  type-aliases-package: com.sgy.payment
  configuration:
    # Mybatis SQL语句控制台打印
    #    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    # 开启驼峰命名规则
    # 在数据库中字段可以采用驼峰命名规则,mybatis会把 下划线去掉并把下划线后面的首字母认为是大写
    map-underscore-to-camel-case: true

logging:
  level:
    # 注意注意注意 一定要修改成自己的包名
    com.sgy: debug
  file:
    path: log/
    name: log/com.sgy.payment-dev.log
    clean-history-on-start: true
  pattern:
    console: "%d{yyyy-MM-dd} [%thread] %-5level %logger{50} ===> %msg%n"
    file: "%d{yyyy-MM-dd} === [%thread] === %-5level === %logger{50} ===> %msg%n"

编写controller

@RestController
@Slf4j
public class PaymentController {
    @Value("${server.port}")
    private String SERVER_PORT;

    @GetMapping(value = "/zk")
    public Object zk() {
        log.info("测试zk , 服务端口号 = {},UUID = {}",SERVER_PORT, UUID.randomUUID().toString());
        return "测试通过";
    }
}

测试

启动

启动报错,让我们一点一点来分析

  • 找到报错所在位置是自己定义的类包名
    • 这是启动类报错,启动类报错,基本可以断定是环境配置有问题

1610803428790.png

  • 接着看
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'baseDaoServiceImpl'

  创建一个baseDaoServiceImpl失败,导致的原因就是在spring容器中没有找到创建baseDaoServiceImpl所继承的类

@Service
public class BaseDaoServiceImpl<T extends BaseEntities,ID,D extends MyMapper<T>>
        implements BaseDaoService<T, ID> {
}

这个类是我自定义的服务层基础类,他是一个泛型,而其中MyMapper是一个接口,继承Mapper<T> , InsertListMapper<T>

/**
 * Created by AaronShen on 2020/5/26
 */
public interface MyMapper<T>  extends Mapper<T> , InsertListMapper<T> {
}

  然后我们必须让MyMapper的子类被扫描到spring容器中,因此,在我新创建的工程中,我需要引入一个dao层文件并且添加@Mapper,让springboot扫描到Mapper<T>

@Mapper
public interface PaymentDao extends MyMapper<Payment> {
}

版本冲突问题

  如果出现zookeeper版本冲突,centos中安装的zookeeper版本跟项目中使用的客户端版本不一致,你需要排除spring-cloud-starter-zookeeper-discovery已有的zookeeper,然后重新引入zookeeper客户端

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.5.6</version>
</dependency>

  此处注意需要排除spring-cloud-zookeeper中自带的zookeeper版本,保持与服务端版本一致,否则连接步成功。

使用zk客户端查看服务注册

[zk: localhost:2181(CONNECTED) 6] ls /
[services, zookeeper]

[zk: localhost:2181(CONNECTED) 7] ls /services
[cloud-payment-server] 这就是注册的服务名称

[zk: localhost:2181(CONNECTED) 8] ls /services/cloud-payment-server
[d990d789-e0b8-441c-99bc-95986c057dca]

[zk: localhost:2181(CONNECTED) 10] ls /services/cloud-payment-server/d990d789-e0b8-441c-99bc-95986c057dca
[]

[zk: localhost:2181(CONNECTED) 11] get /services/cloud-payment-server/d990d789-e0b8-441c-99bc-95986c057dca
{"name":"cloud-payment-server","id":"d990d789-e0b8-441c-99bc-95986c057dca","address":"localhost","port":8092,"sslPort":null,"payload":{"@class":"org.springframework.cloud.zookeeper.discovery.ZookeeperInstance","id":"application-1","name":"cloud-payment-server","metadata":{}},"registrationTimeUTC":1590578412812,"serviceType":"DYNAMIC","uriSpec":{"parts":[{"value":"scheme","variable":true},{"value":"://","variable":false},{"value":"address","variable":true},{"value":":","variable":false},{"value":"port","variable":true}]}}

json格式化结果

1610803428825.png

zookeeper服务节点是持久节点还是临时节点

结论

是临时节点

探索过程

  • 我们现在关掉支付服务节点
  • 然后使用zk客户端,查看节点是否存在,发现服务节点已经被去掉了
[zk: localhost:2181(CONNECTED) 13] ls /services/cloud-payment-server
[d990d789-e0b8-441c-99bc-95986c057dca]
[zk: localhost:2181(CONNECTED) 14] ls /services/cloud-payment-server
[]
  • 重启支付节点
    • 服务节点又回来了
    • 流水号是一个新值
[zk: localhost:2181(CONNECTED) 15] ls /services/cloud-payment-server
[]
[zk: localhost:2181(CONNECTED) 16] ls /services/cloud-payment-server
[93d772c8-8117-476a-8a6e-59020bac4cfc]
  • 因此服务节点是一个临时节点