基于Zookeeper集群环境下的master选举

转载请说明出处:https://blog.csdn.net/LiaoHongHB/article/details/84951540

该篇博客需要有上一篇基础:https://blog.csdn.net/LiaoHongHB/article/details/84950486

代码下载地址:https://download.csdn.net/download/liaohonghb/10843687

架构图:

左边是ZooKeeper集群,右边是3台工作服务器。工作服务器启动时,会去ZooKeeper的Servers节点下创建临时节点,并把基本信息写入临时节点。这个过程叫服务注册,系统中的其他服务可以通过获取Servers节点的子节点列表,来了解当前系统哪些服务器可用,这该过程叫做服务发现。接着这些服务器会尝试创建Master临时节点,谁创建成功谁就是Master,其他的两台就作为Slave。所有的Work Server必需关注Master节点的删除事件。通过监听Master节点的删除事件,来了解Master服务器是否宕机(创建临时节点的服务器一旦宕机,它所创建的临时节点即会自动删除)。一旦Master服务器宕机,必需开始新一轮的Master选举。

1、新建zookeeper-master工程,并新建master-client1和master-client2子模块:

2、master-client1:

application.yml:

server:
  port: 5004

registry:
  servers: 192.168.202.128:2181,192.168.202.129:2181,192.168.202.130:2181

 masterservice:

public interface MasterService {

    void master();
}

masterserviceimpl:

@Service
public class MasterServiceImpl implements MasterService, Watcher {

    private static Logger logger = LoggerFactory.getLogger(MasterServiceImpl.class);
    private static CountDownLatch latch = new CountDownLatch(1);
    private ZooKeeper zk;
    private static final int SESSION_TIMEOUT = 15000;

    private ExecutorService executorService = Executors.newFixedThreadPool(3);
    private String masterData = null;

    public MasterServiceImpl() {
    }

    public MasterServiceImpl(String zkServers) {
        try {
            zk = new ZooKeeper(zkServers, SESSION_TIMEOUT, this);
            latch.await();
            logger.debug("connected to zookeeper");
        } catch (Exception ex) {
            logger.error("create zookeeper client failure", ex);
        }
    }

    @Override
    public void master() {
        masterData = "127.0.0.1:5001";
        logger.info("开始监听........");
        Task task = new Task();
        executorService.execute(task);
    }

    @Override
    public void process(WatchedEvent watchedEvent) {
        if (watchedEvent.getState() == Event.KeeperState.SyncConnected)
            latch.countDown();
    }

    private class Task implements Runnable {

        @Override
        public void run() {
            try {
                zk.exists("/master", new Watcher() {
                    @Override
                    public void process(WatchedEvent watchedEvent) {
                        if (watchedEvent.getType() == Event.EventType.NodeDeleted) {
                            logger.info("exists中监听到..." + watchedEvent.getPath() + "...删除了");
                            try {
                                zk.create("/master", masterData.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
                                logger.info("{}成功创建master节点", masterData);
                                logger.info("删除节点/registry/slave/address-0000000013");
                                zk.delete("/registry/slave/address-0000000013", 0);
                            } catch (ZkNodeExistsException e) {
                                logger.info("master节点已经被创建");
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            } catch (KeeperException e) {
                                e.printStackTrace();
                            } finally {
                            }
                        }
                    }
                });
            } catch (KeeperException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

//    private class ZkDataListener implements IZkDataListener {
//
//        @Override
//        public void handleDataChange(String s, Object o) throws Exception {
//        }
//
//        @Override
//        public void handleDataDeleted(String s) throws Exception {
//            //重新选举master
//            logger.info("重新选举master");
//            try {
//                zk.create("/master", masterData.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
//                logger.info("{}成功创建master节点", masterData);
//                zk.delete("/registry/slave/address-0000000007", 0);
//            } catch (ZkNodeExistsException e) {
//                logger.info("master节点已经被创建");
//            } finally {
//            }
//        }
//    }
}

masterconfig:

@Configuration
@ConfigurationProperties(prefix = "registry")
public class MasterConfig {

    private String servers;

    @Bean
    public MasterService masterService() {
        return new MasterServiceImpl(servers);
    }

    public void setServers(String servers) {
        this.servers = servers;
    }
}

weblistener:

@Component
public class WebListener implements ServletContextListener {

    private Logger logger = LoggerFactory.getLogger(getClass());


    @Autowired
    public MasterService masterService;


    @Override
    public void contextInitialized(ServletContextEvent sce) {
        masterService.master();
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {

    }
}

master-client2和master-client1一致,只是在masterserviceimpl中masterData参数以及对应的删除节点修改即可。

3、运行结果:将master节点删除

原来的master节点删除之后,client1和client2都监听了该事件,由于client1先创建master节点,于是client2在创建master节点时就会抛出异常(KeeperErrorCode = NodeExists for /master) ;并且client1创建完master节点之后要将原来的slave下的client1节点信息删除。

猜你喜欢

转载自blog.csdn.net/LiaoHongHB/article/details/84951540