摘要
为了高可用通产我们一个服务会部署多节点。但是有时我们希望对某些操作要求单线程处理,此时可以通过主备服务形式实现。正常情况下主节点服务处理,当主节点宕机后备用节点相关服务继续处理。
需求
资源中心会将资源文件相关操作分发至各个项目节点,资源的操作包括添加、分享、删除、和谐、恢复。资源中心向mq发布消息,各个项目节点通过订阅mq消息处理对应资源。各项目节点HA部署双节点。此时有可能出现其中一个节点正在处理资源的上传操作,由于涉及到文件IO,此操作比较慢,同时另一个节点接收到了删除的mq消息,执行对应的资源删除操作。为了避免这种情况,要求对消息的操作必须是顺序的。
解决方案
项目的两个节点在启动完成后抢注zookeeper同时订阅zk的节点disconnect事件,抢注成功的节点成为主节点通知执行启动操作,抢注失败的节点为从节点不做操作。当主节点宕机后,从节点会接收到disconnect消息,从而执行启动操作。
实现
- 服务启动后抢注zk
@Override public void run(ApplicationArguments args) throws Exception { if(enable){ zookeeperWatcher.connect(); if(!zookeeperWatcher.exists()){ zookeeperWatcher.create(); }else{ log.info("节点已被抢注,不再发布节点抢注成功事件!!!"); } }else{ log.info("不启用,默认发布抢注成功事件"); SpringContextUtil.getApplicationContext().publishEvent(new MainStandbyRunnerEvent(true)); } }
- 通过publishEvent+listener将主备启动与主备解耦
抢注zk节点成功发布启动事件SpringContextUtil.getApplicationContext()