package com.vip.saturn.job.sharding.listener; import com.vip.saturn.job.sharding.NamespaceShardingManager; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.state.ConnectionState; import org.apache.curator.framework.state.ConnectionStateListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicBoolean; /** * @author hebelala */ public abstract class ShardingConnectionLostListener implements ConnectionStateListener { private static final Logger logger = LoggerFactory.getLogger(ShardingConnectionLostListener.class); private NamespaceShardingManager namespaceShardingManager; private ExecutorService executor; public ShardingConnectionLostListener(NamespaceShardingManager namespaceShardingManager) { this.namespaceShardingManager = namespaceShardingManager; this.executor = Executors.newSingleThreadExecutor(new ThreadFactory() { @Override public Thread newThread(Runnable r) { Thread t = new Thread(r, ShardingConnectionLostListener.this.namespaceShardingManager.getNamespace() + "-NamespaceShardingManager-zk-reconnect-thread"); if (t.isDaemon()) { t.setDaemon(false); } if (t.getPriority() != Thread.NORM_PRIORITY) { t.setPriority(Thread.NORM_PRIORITY); } return t; } }); } private AtomicBoolean connected = new AtomicBoolean(false); private AtomicBoolean stopped = new AtomicBoolean(false); private long getSessionId(CuratorFramework client) { long sessionId; try { sessionId = client.getZookeeperClient().getZooKeeper().getSessionId(); } catch (Exception e) {// NOSONAR return -1; } return sessionId; } public abstract void stop(); public abstract void restart(); @Override public void stateChanged(final CuratorFramework client, final ConnectionState newState) { // 使用single thread executor严格保证ZK事件执行的顺序性,避免并发性问题 if (ConnectionState.SUSPENDED == newState) { connected.set(false); final long sessionId = getSessionId(client); executor.submit(new Runnable() { @Override public void run() { do { try { Thread.sleep(1000); } catch (InterruptedException e) { } if (namespaceShardingManager.isStopped()) { return; } long newSessionId = getSessionId(client); if (sessionId != newSessionId) { logger.info(" {}-NamespaceShardingManager is going to stop for zk lost", namespaceShardingManager.getNamespace()); stop(); stopped.set(true); return; } } while (!namespaceShardingManager.isStopped() && !connected.get()); } }); } else if (ConnectionState.RECONNECTED == newState) { connected.set(true); executor.submit(new Runnable() { @Override public void run() { if (stopped.compareAndSet(true, false)) { logger.info(" {}-NamespaceShardingManager is going to restart for zk reconnected", namespaceShardingManager.getNamespace()); restart(); } } }); } } public void shutdown() { executor.shutdownNow(); } }