package com.snowcattle.game.service.rpc.client; import com.snowcattle.game.common.config.GameServerDiffConfig; import com.snowcattle.game.common.config.ZooKeeperConfig; import com.snowcattle.game.manager.LocalMananger; import com.snowcattle.game.service.rpc.server.zookeeper.ZooKeeperNodeInfo; import com.snowcattle.game.common.config.GameServerConfigService; import com.snowcattle.game.common.constant.GlobalConstants; import com.snowcattle.game.common.constant.Loggers; import com.snowcattle.game.common.constant.ServiceName; import com.snowcattle.game.service.IService; import com.snowcattle.game.service.rpc.server.zookeeper.ZooKeeperNodeBoEnum; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFrameworkFactory; import org.apache.curator.framework.api.ACLProvider; import org.apache.curator.framework.recipes.cache.ChildData; import org.apache.curator.framework.recipes.cache.TreeCache; import org.apache.curator.framework.recipes.cache.TreeCacheEvent; import org.apache.curator.framework.recipes.cache.TreeCacheListener; import org.apache.curator.retry.RetryNTimes; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.ZooDefs; import org.apache.zookeeper.ZooKeeper; import org.apache.zookeeper.ZooDefs.Perms; import org.apache.zookeeper.data.ACL; import org.apache.zookeeper.data.Id; import org.slf4j.Logger; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Random; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * Created by jiangwenping on 17/3/30. * zookeeper发现服务 */ @Service public class ZookeeperRpcServiceDiscovery implements IService{ private static final Logger logger = Loggers.rpcLogger; private CountDownLatch countDownLatch = new CountDownLatch(1); private volatile Map<ZooKeeperNodeBoEnum, List<ZooKeeperNodeInfo>> nodeMap = new ConcurrentHashMap<>(); private Random random = new Random(); private CuratorFramework client; public void discovery(ZooKeeperNodeBoEnum zooKeeperNodeBoEnum){ if(client == null){ client = creatClient(); } try { setListenter(client,zooKeeperNodeBoEnum); } catch (Exception e) { if(logger.isDebugEnabled()){ logger.debug("CuratorFramework Listenning Exception:"+e.getMessage()); } } } private ZooKeeperNodeInfo chooseService(ZooKeeperNodeBoEnum zooKeeperNodeBoEnum){ ZooKeeperNodeInfo data = null; List<ZooKeeperNodeInfo> nodeList = nodeMap.get(zooKeeperNodeBoEnum); if(nodeList != null) { int size = nodeList.size(); if (size > 0) { if (size == 1) { data = nodeList.get(0); if(logger.isDebugEnabled()) { logger.debug("use only data: ", data); } } else { data = nodeList.get(random.nextInt(size)); if(logger.isDebugEnabled()) { logger.debug("use random data:", data); } } } } return data; } /** * 链接zookeeper * @return */ private ZooKeeper connectServer(){ ZooKeeper zk = null; try { GameServerConfigService gameServerConfigService = LocalMananger.getInstance().getLocalSpringServiceManager().getGameServerConfigService(); ZooKeeperConfig zooKeeperConfig = gameServerConfigService.getZooKeeperConfig(); String registryAdress = zooKeeperConfig.getProperty(GlobalConstants.ZooKeeperConstants.registryAdress); zk = new ZooKeeper(registryAdress, GlobalConstants.ZooKeeperConstants.ZK_SESSION_TIMEOUT, new Watcher() { @Override public void process(WatchedEvent event) { countDownLatch.countDown(); } }); }catch (Exception e){ logger.error(e.toString(), e); } return zk; } public void stop(){ if(client != null){ try { client.close(); }catch (Exception e){ logger.error(e.toString(), e); } } } public List<ZooKeeperNodeInfo> getNodeList(final ZooKeeperNodeBoEnum zooKeeperNodeBoEnum) { return nodeMap.get(zooKeeperNodeBoEnum); } @Override public String getId() { return ServiceName.ZookeeperRpcServiceDiscovery; } @Override public void startup() throws Exception { GameServerConfigService gameServerConfigService = LocalMananger.getInstance().getLocalSpringServiceManager().getGameServerConfigService(); GameServerDiffConfig gameServerDiffConfig = gameServerConfigService.getGameServerDiffConfig(); if(gameServerDiffConfig.isZookeeperFlag()) { try { client = creatClient(); } catch (Exception e) { logger.error("Create CuratorFramework Client Exception:" + e.getMessage()); } ZooKeeperNodeBoEnum[] zooKeeperNodeBoEnums = ZooKeeperNodeBoEnum.values(); for (ZooKeeperNodeBoEnum zooKeeperNodeBoEnum : zooKeeperNodeBoEnums) { discovery(zooKeeperNodeBoEnum); } } } @Override public void shutdown() throws Exception { if(client != null){ try { client.close(); }catch (Exception e){ logger.error(e.toString(), e); } } } private static CuratorFramework creatClient() { ACLProvider aclProvider = new ACLProvider() { private List<ACL> acl; @Override public List<ACL> getDefaultAcl() { if (acl == null) { ArrayList<ACL> acl = ZooDefs.Ids.CREATOR_ALL_ACL; acl.clear(); acl.add(new ACL(Perms.ALL, new Id("auth", "admin:admin"))); this.acl = acl; } return acl; } @Override public List<ACL> getAclForPath(String path) { return acl; } }; //String scheme = "digest"; //byte[] auth = "admin:admin".getBytes(); int connectionTimeoutMs = 5000; //String connectString = "192.168.0.158:2181"; GameServerConfigService gameServerConfigService = LocalMananger.getInstance().getLocalSpringServiceManager().getGameServerConfigService(); ZooKeeperConfig zooKeeperConfig = gameServerConfigService.getZooKeeperConfig(); String registryAdress = zooKeeperConfig.getProperty(GlobalConstants.ZooKeeperConstants.registryAdress); String namespace = ""; CuratorFramework client = CuratorFrameworkFactory.builder() .aclProvider(aclProvider)//.authorization(scheme, auth) .connectionTimeoutMs(connectionTimeoutMs) .connectString(registryAdress)//.namespace(namespace) .retryPolicy(new RetryNTimes(Integer.MAX_VALUE, 1000)).build(); client.start(); return client; } private void setListenter(CuratorFramework client,ZooKeeperNodeBoEnum zooKeeperNodeBoEnum)throws Exception { ExecutorService pool = Executors.newCachedThreadPool(); List<String> childrens = client.getChildren().forPath(zooKeeperNodeBoEnum.getRootPath()); List<ZooKeeperNodeInfo> tempNodeList = new ArrayList<>(); for (String node: childrens){ ZooKeeperNodeInfo zooKeeperNodeInfo = new ZooKeeperNodeInfo(); byte[] bytes = client.getData().forPath(zooKeeperNodeBoEnum.getRootPath()+"/"+node); if(bytes != null) { zooKeeperNodeInfo.deserialize(new String(bytes)); tempNodeList.add(zooKeeperNodeInfo); } } if(logger.isDebugEnabled()) { logger.debug("node data: {}", tempNodeList); } nodeMap.put(zooKeeperNodeBoEnum, tempNodeList); if(logger.isDebugEnabled()) { logger.debug("Service discovery triggered updating connected server node."); } RpcClientConnectService rpcClientConnectService = LocalMananger.getInstance().getLocalSpringServicerAfterManager().getRpcClientConnectService(); rpcClientConnectService.notifyConnect(zooKeeperNodeBoEnum, nodeMap.get(zooKeeperNodeBoEnum)); TreeCache cache = new TreeCache(client, zooKeeperNodeBoEnum.getRootPath()); cache.getListenable().addListener(new TreeCacheListener() { @Override public void childEvent(CuratorFramework client, TreeCacheEvent event) throws Exception { ChildData data = event.getData(); if (data != null) { switch (event.getType()) { case NODE_ADDED: if(logger.isDebugEnabled()) { logger.debug("NODE_ADDED : " + data.getPath() + " 数据:" + new String(data.getData())); } break; case NODE_REMOVED: if(logger.isDebugEnabled()) { logger.debug("NODE_REMOVED : " + data.getPath()+ " 数据:" + new String(data.getData())); } break; case NODE_UPDATED: if(logger.isDebugEnabled()) { logger.debug("NODE_UPDATED : " + data.getPath() + " 数据:" + new String(data.getData())); } break; default: break; } } else { switch (event.getType()) { case CONNECTION_SUSPENDED: if(logger.isDebugEnabled()) { logger.debug("data is null : " + "CONNECTION_SUSPENDED"); } break; case CONNECTION_RECONNECTED: if(logger.isDebugEnabled()) { logger.debug("data is null : " + "CONNECTION_RECONNECTED"); } break; case CONNECTION_LOST: if(logger.isDebugEnabled()) { logger.debug("data is null : " + "CONNECTION_LOST"); } break; default: break; } } } }); // 开始监听 cache.start(); } }