zookeeper

  • zookeeper选主介绍:
  • 在微服务模块引入相关依赖
  • 1.在服务层创建SelectMaster,作为选主组件,在类上添加@Component注解
  • 2:将SelectMaster中的zookeeper地址连接字符串配置到application.yml配置文件中
  • 注入SelectMaster


zookeeper选主介绍:

Zookeeper 会维护一个具有层次关系的数据结构,它非常类似于一个标准的文件系统,集群各节点争抢注册同一路径地址,谁抢到谁就是master
zookeeper基于目录监听机制来选主,多个客户端节点都可以来对zookeeper上某个目录节点进行监听和注册,但只有其中一个能够注册上,谁能注册上谁就是主节点,主节点会保持着和zookeeper目录节点的长连接,只
要该连接不断,那么该客户端节点就一直是主节点,其他客户端节点都会监听者zookeeper的该目录节点,一旦主节点宕机,会立即从其他客户端节点中选出一个新的主节点,也就是说:如果当前master宕机,会立即选出一个
新的master。

在微服务模块引入相关依赖

<!-- zookeeper 客户端 -->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>2.13.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>2.13.0</version>
        </dependency>
        <dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-configuration-processor</artifactId>
		</dependency>

1.在服务层创建SelectMaster,作为选主组件,在类上添加@Component注解

2:将SelectMaster中的zookeeper地址连接字符串配置到application.yml配置文件中

yexiang:
	preLoad: 1 #预加载时间配置
	selectMasterZookeeper: 192.168.200.129:2181
@Data
				//对应配置文件中的前缀yexiang
@ConfigurationProperties(prefix = "yexiang")
@Component
public class SelectMaster {

    private String selectMasterZookeeper;

    //可以放很多节点
    Map<String, Boolean> masterMap = new HashMap<String, Boolean>();


    /**
     * 选主
     * @param leaderPath  zookeeper目录节点
     */
    public void selectMaster (String leaderPath) {
        CuratorFramework client = CuratorFrameworkFactory.builder().
                connectString(selectMasterZookeeper)
                .sessionTimeoutMs(5000)  //超时时间
                .retryPolicy(new ExponentialBackoffRetry(1000, 3)) //连接不上重试三次
                .build();
        client.start();

        //争抢注册节点
        @SuppressWarnings("resource")
        LeaderSelector selector = new LeaderSelector(client, leaderPath,
                new LeaderSelectorListenerAdapter() {

                    @Override
                    public void takeLeadership(CuratorFramework client) throws Exception {
                        //如果争抢到当前注册节点
                        masterMap.put(leaderPath, true);
                        while (true) {
                            //抢占当前节点
                            TimeUnit.SECONDS.sleep(3);
                        }
                    }
                });
        masterMap.put(leaderPath, false);
        selector.autoRequeue();
        selector.start();
    }

    public boolean checkMaster (String leaderPath) {
        Boolean isMaster = masterMap.get(leaderPath);
        return isMaster == null ? false : isMaster;
    }

}

常量池中添加任意路径,用作微服务在zookeeper上抢注册的地址,谁成功抢到该地址,谁就是主节点,没抢到为从节点,但会继续监视该节点。

public static final String schedule_leaderPath="/chongba/schedule_master";

注入SelectMaster

@Autowired
    private SelectMaster selectMaster;
    //该注解标注的方法在项目启动时执行
    @PostConstruct
    public  void syncData(){
        /**
         * 清除缓存原有数据:编写:clearCache()
         查询所有任务数据:调用 taskMapper.selectAll()
         将任务数据放入缓存:封装Task,调用addTaskToCache(task);
         */
        // 选主----
        selectMaster.selectMaster(Constants.schedule_leaderPath);

        try {
            Thread.sleep(1000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        threadPoolTaskScheduler.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                //只有主节点才能去进行数据的恢复
                boolean master = selectMaster.checkMaster(Constants.schedule_leaderPath);
                if(master){
                    //是主节点
                    threadLogger.info("schedule-service的主节点进行数据恢复---reloadData");
                    reloadData();
                }else {
                    //从节点
                    threadLogger.info("schedule-service的从节点进行备份");
                }
            }
        },TimeUnit.MINUTES.toMillis(systemParams.getPreLoad()));//硬编码
        
    }