diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ZookeeperContext.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ZookeeperContext.java index bbe5f788..76f814b3 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ZookeeperContext.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ZookeeperContext.java @@ -288,7 +288,7 @@ public class ZookeeperContext { } /** - * 监听一个节点 + * 监听一个临时节点 * * @param path * @param listenCallback 回调 diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/ServiceConstants.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/ServiceConstants.java index 9b596b12..7d0fe3dd 100644 --- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/ServiceConstants.java +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/ServiceConstants.java @@ -8,4 +8,9 @@ public class ServiceConstants { * zookeeper存放接口路由信息的根目录 */ public static final String SOP_SERVICE_ROUTE_PATH = "/com.gitee.sop.route"; + + /** + * 服务临时节点 + */ + public static final String SOP_SERVICE_TEMP_PATH = "/com.gitee.sop.service.tmp"; } diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/ZookeeperTool.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/ZookeeperTool.java index dbf4615b..8130d7f8 100644 --- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/ZookeeperTool.java +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/ZookeeperTool.java @@ -9,6 +9,7 @@ import org.apache.commons.lang.math.NumberUtils; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFrameworkFactory; import org.apache.curator.retry.ExponentialBackoffRetry; +import org.apache.zookeeper.CreateMode; import org.springframework.core.env.Environment; import java.io.Closeable; @@ -94,6 +95,23 @@ public class ZookeeperTool implements Closeable { .forPath(path, data.getBytes()); } + /** + * 创建临时序列节点 + * @param path 节点路径 + * @param data 数据 + * @return 返回节点路径 + * @throws Exception + */ + public String createOrUpdateEphemeralSequentialPath(String path, String data) throws Exception { + return getClient().create() + // 如果节点存在则Curator将会使用给出的数据设置这个节点的值 + .orSetData() + // 如果指定节点的父节点不存在,则Curator将会自动级联创建父节点 + .creatingParentContainersIfNeeded() + .withMode(CreateMode.EPHEMERAL_SEQUENTIAL) + .forPath(path, data.getBytes()); + } + /** * 新建或保存节点 * diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceZookeeperApiMetaManager.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceZookeeperApiMetaManager.java index ac11af39..cf2e8fbf 100644 --- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceZookeeperApiMetaManager.java +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceZookeeperApiMetaManager.java @@ -10,7 +10,6 @@ import com.gitee.sop.servercommon.route.ServiceRouteInfo; import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.io.IOUtils; import org.springframework.beans.BeanUtils; import org.springframework.core.env.Environment; import org.springframework.util.DigestUtils; @@ -81,6 +80,7 @@ public class ServiceZookeeperApiMetaManager implements ApiMetaManager { String nodeData = JSON.toJSONString(serviceRouteInfo); log.info("serviceId:{}, zookeeper保存路径:{}", serviceId, savePath); this.zookeeperTool.createPath(savePath, nodeData); + this.zookeeperTool.createPath(serviceRouteInfo.getZookeeperTempServiceIdPath(), ""); } catch (Exception e) { throw new IllegalStateException("zookeeper操作失败"); } @@ -91,8 +91,11 @@ public class ServiceZookeeperApiMetaManager implements ApiMetaManager { try { ServiceRouteInfo serviceRouteInfo = this.buildServiceGatewayInfo(serviceApiInfo); this.uploadServiceRouteInfoToZookeeper(serviceRouteInfo); - } finally { - IOUtils.closeQuietly(zookeeperTool); + // 同时上传一个临时节点 + String tempPath = serviceRouteInfo.getZookeeperTempServiceIdChildPath(); + this.zookeeperTool.createOrUpdateEphemeralSequentialPath(tempPath, JSON.toJSONString(serviceRouteInfo)); + } catch (Exception e) { + log.error("上传一个临时节点失败, serviceApiInfo:{}", serviceApiInfo, e); } } diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/route/ServiceRouteInfo.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/route/ServiceRouteInfo.java index 78c920a9..5041000d 100644 --- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/route/ServiceRouteInfo.java +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/route/ServiceRouteInfo.java @@ -13,6 +13,7 @@ import java.util.List; @Data public class ServiceRouteInfo { private static final String SOP_SERVICE_ROUTE_PATH = ServiceConstants.SOP_SERVICE_ROUTE_PATH; + private static final String SOP_SERVICE_TEMP_PATH = ServiceConstants.SOP_SERVICE_TEMP_PATH; /** 服务名称,对应spring.application.name */ private String serviceId; @@ -39,4 +40,22 @@ public class ServiceRouteInfo { public String getZookeeperPath() { return SOP_SERVICE_ROUTE_PATH + '/' + serviceId; } + + /** + * 返回zookeeper路径 + * @return 返回zookeeper路径 + */ + @JSONField(serialize = false) + public String getZookeeperTempServiceIdPath() { + return SOP_SERVICE_TEMP_PATH + '/' + serviceId; + } + + /** + * 返回zookeeper路径 + * @return 返回zookeeper路径 + */ + @JSONField(serialize = false) + public String getZookeeperTempServiceIdChildPath() { + return getZookeeperTempServiceIdPath() + "/" + serviceId; + } } \ No newline at end of file diff --git a/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/config/OpenServiceConfig.java b/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/config/OpenServiceConfig.java index cbea3472..eb0c299f 100644 --- a/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/config/OpenServiceConfig.java +++ b/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/config/OpenServiceConfig.java @@ -31,7 +31,7 @@ public class OpenServiceConfig extends AlipayServiceConfiguration { /** - * 开启文档 + * 开启文档,本地微服务文档地址:http://localhost:2222/doc.html * http://ip:port/v2/api-docs */ @Configuration diff --git a/sop-gateway/src/test/java/com/gitee/sop/gateway/CuratorTest.java b/sop-gateway/src/test/java/com/gitee/sop/gateway/CuratorTest.java index 9239d009..91ae48b7 100644 --- a/sop-gateway/src/test/java/com/gitee/sop/gateway/CuratorTest.java +++ b/sop-gateway/src/test/java/com/gitee/sop/gateway/CuratorTest.java @@ -31,4 +31,22 @@ public class CuratorTest extends TestCase { } catch (Exception e) { } } + + /** + * 删除临时节点 + */ + public void testDelTemp() { + String tempRoot = "/com.gitee.sop.service.tmp"; + CuratorFramework client = CuratorFrameworkFactory.builder() + .connectString(zookeeperServerAddr) + .retryPolicy(new ExponentialBackoffRetry(1000, 3)) + .build(); + + client.start(); + + try { + client.delete().deletingChildrenIfNeeded().forPath(tempRoot); + } catch (Exception e) { + } + } } diff --git a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/bean/DocInfo.java b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/bean/DocInfo.java index b48b93e5..82e90129 100644 --- a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/bean/DocInfo.java +++ b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/bean/DocInfo.java @@ -1,5 +1,6 @@ package com.gitee.sop.websiteserver.bean; +import com.alibaba.fastjson.annotation.JSONField; import lombok.Data; import java.util.List; @@ -10,5 +11,7 @@ import java.util.List; @Data public class DocInfo { private String title; + @JSONField(serialize = false) + private String serviceId; private List docModuleList; } diff --git a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/bean/WebsiteConstants.java b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/bean/WebsiteConstants.java index 982ab15c..fcb0b7cc 100644 --- a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/bean/WebsiteConstants.java +++ b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/bean/WebsiteConstants.java @@ -8,4 +8,9 @@ public class WebsiteConstants { * zookeeper存放接口路由信息的根目录 */ public static final String SOP_SERVICE_ROUTE_PATH = "/com.gitee.sop.route"; + + /** + * 服务临时节点 + */ + public static final String SOP_SERVICE_TEMP_PATH = "/com.gitee.sop.service.tmp"; } diff --git a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/bean/ZookeeperContext.java b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/bean/ZookeeperContext.java index 94ccc2a9..e2cd6a85 100644 --- a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/bean/ZookeeperContext.java +++ b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/bean/ZookeeperContext.java @@ -5,11 +5,18 @@ import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFrameworkFactory; +import org.apache.curator.framework.recipes.cache.ChildData; +import org.apache.curator.framework.recipes.cache.PathChildrenCache; +import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener; import org.apache.curator.framework.recipes.cache.TreeCache; import org.apache.curator.framework.recipes.cache.TreeCacheListener; import org.apache.curator.retry.ExponentialBackoffRetry; import org.springframework.core.env.Environment; import org.springframework.util.Assert; +import org.springframework.util.CollectionUtils; + +import java.util.List; +import java.util.function.Consumer; /** * @author tanghc @@ -50,6 +57,10 @@ public class ZookeeperContext { return WebsiteConstants.SOP_SERVICE_ROUTE_PATH; } + public static String getServiceTempRootPath() { + return WebsiteConstants.SOP_SERVICE_TEMP_PATH; + } + public static CuratorFramework getClient() { return client; } @@ -58,10 +69,99 @@ public class ZookeeperContext { ZookeeperContext.client = client; } + public static boolean isPathExist(String path) { + try { + return client.checkExists().forPath(path) != null; + } catch (Exception e) { + return false; + } + } + + /** + * 是否有子节点 + * @param parentPath + * @return + * @throws Exception + */ + public static boolean hasChildren(String parentPath) throws Exception { + List children = client.getChildren().forPath(parentPath); + return !CollectionUtils.isEmpty(children); + } + + /** + * 创建path,如果path存在不报错,静默返回path名称 + * + * @param path + * @param data + * @return + * @throws Exception + */ + public static String createPath(String path, String data) throws Exception { + if (isPathExist(path)) { + return path; + } + return getClient().create() + // 如果指定节点的父节点不存在,则Curator将会自动级联创建父节点 + .creatingParentContainersIfNeeded() + .forPath(path, data.getBytes()); + } + + /** + * 获取子节点信息并监听子节点 + * + * @param parentPath 父节点路径 + * @param listConsumer 子节点数据 + * @param listener 监听事件 + * @throws Exception + */ + public static void getChildrenAndListen(String parentPath, Consumer> listConsumer, PathChildrenCacheListener listener) throws Exception { + // 为子节点添加watcher + // PathChildrenCache: 监听数据节点的增删改,可以设置触发的事件 + PathChildrenCache childrenCache = new PathChildrenCache(client, parentPath, true); + + /** + * StartMode: 初始化方式 + * POST_INITIALIZED_EVENT:异步初始化,初始化之后会触发事件 + * NORMAL:异步初始化 + * BUILD_INITIAL_CACHE:同步初始化 + */ + childrenCache.start(PathChildrenCache.StartMode.BUILD_INITIAL_CACHE); + + // 列出子节点数据列表,需要使用BUILD_INITIAL_CACHE同步初始化模式才能获得,异步是获取不到的 + List childDataList = childrenCache.getCurrentData(); + listConsumer.accept(childDataList); + log.info("监听子节点增删改,监听路径:{}", parentPath); + // 监听根节点下面的子节点 + childrenCache.getListenable().addListener(listener); + } + + /** + * 监听子节点的增删改 + * + * @param parentPath 父节点路径 + * @param listener + * @throws Exception + */ + public static void listenChildren(String parentPath, PathChildrenCacheListener listener) throws Exception { + // 为子节点添加watcher + // PathChildrenCache: 监听数据节点的增删改,可以设置触发的事件 + PathChildrenCache childrenCache = new PathChildrenCache(client, parentPath, true); + + /** + * StartMode: 初始化方式 + * POST_INITIALIZED_EVENT:异步初始化,初始化之后会触发事件 + * NORMAL:异步初始化 + * BUILD_INITIAL_CACHE:同步初始化 + */ + childrenCache.start(PathChildrenCache.StartMode.BUILD_INITIAL_CACHE); + // 监听根节点下面的子节点 + childrenCache.getListenable().addListener(listener); + } + /** * 监听子节点,可以自定义层级 * @param parentPath 父节点路径 - * @param maxDepth 层级,从1开始。比如当前监听节点/t1,目录最深为/t1/t2/t3/t4,则maxDepth=3,说明下面3级子目录全 + * @param maxDepth 层级,从1开始。比如当前监听节点/t1,目录最深为/t1/t2/t3/t4,则maxDepth=3,说明下面3级子目录全部监听 * @param listener * @throws Exception */ @@ -73,7 +173,6 @@ public class ZookeeperContext { .build(); treeCache.getListenable().addListener(listener); - //没有开启模式作为入参的方法 treeCache.start(); } diff --git a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/controller/DocController.java b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/controller/DocController.java index 0e020f4b..957a9275 100644 --- a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/controller/DocController.java +++ b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/controller/DocController.java @@ -1,7 +1,6 @@ package com.gitee.sop.websiteserver.controller; import com.gitee.sop.websiteserver.bean.DocInfo; -import com.gitee.sop.websiteserver.bean.DocItem; import com.gitee.sop.websiteserver.manager.DocManager; import com.gitee.sop.websiteserver.vo.DocBaseInfoVO; import com.gitee.sop.websiteserver.vo.DocInfoVO; @@ -59,11 +58,6 @@ public class DocController { return docManager.getByTitle(title); } - @GetMapping("/item/{method}/{version}/") - public DocItem getDocItem(@PathVariable("method") String method, @PathVariable("version") String version) { - return docManager.get(method, version); - } - // 后门地址,可手动更新文档内容,一般情况下用不到 @GetMapping("/reload") diff --git a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocManager.java b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocManager.java index 1deecbe4..8716e269 100644 --- a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocManager.java +++ b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocManager.java @@ -1,7 +1,6 @@ package com.gitee.sop.websiteserver.manager; import com.gitee.sop.websiteserver.bean.DocInfo; -import com.gitee.sop.websiteserver.bean.DocItem; import java.util.Collection; @@ -12,8 +11,6 @@ public interface DocManager { void load(String serviceId); - DocItem get(String method, String version); - DocInfo getByTitle(String title); Collection listAll(); diff --git a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocManagerImpl.java b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocManagerImpl.java index ae030608..925ddd0d 100644 --- a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocManagerImpl.java +++ b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocManagerImpl.java @@ -7,12 +7,12 @@ import com.gitee.sop.registryapi.bean.ServiceInfo; import com.gitee.sop.registryapi.bean.ServiceInstance; import com.gitee.sop.registryapi.service.RegistryService; import com.gitee.sop.websiteserver.bean.DocInfo; -import com.gitee.sop.websiteserver.bean.DocItem; import com.gitee.sop.websiteserver.bean.ZookeeperContext; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.math.NumberUtils; -import org.apache.curator.framework.recipes.cache.TreeCacheEvent; +import org.apache.curator.framework.recipes.cache.ChildData; +import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.env.Environment; @@ -43,21 +43,17 @@ import java.util.stream.Collectors; public class DocManagerImpl implements DocManager { // key:title - Map docDefinitionMap = new HashMap<>(); + private Map docDefinitionMap = new HashMap<>(); - // key: name+version - Map docItemMap = new HashMap<>(); + private RestTemplate restTemplate = new RestTemplate(); + private DocParser swaggerDocParser = new SwaggerDocParser(); - RestTemplate restTemplate = new RestTemplate(); + private DocParser easyopenDocParser = new EasyopenDocParser(); - DocParser swaggerDocParser = new SwaggerDocParser(); + private ExecutorService executorService = Executors.newSingleThreadExecutor(); - DocParser easyopenDocParser = new EasyopenDocParser(); - - ExecutorService executorService = Executors.newSingleThreadExecutor(); - - DelayQueue queue = new DelayQueue<>(); + private DelayQueue queue = new DelayQueue<>(); private String secret = "b749a2ec000f4f29"; @@ -70,14 +66,10 @@ public class DocManagerImpl implements DocManager { @Value("${doc.refresh-seconds:60}") private String refreshSeconds; - private volatile boolean listenInited; - @Override public void load(String serviceId) { try { List serviceInfoList = registryService.listAllService(1, 9999); - log.info("服务列表:{}", serviceInfoList); - serviceInfoList .stream() // 网关没有文档提供,需要排除 @@ -110,6 +102,7 @@ public class DocManagerImpl implements DocManager { JSONObject docRoot = JSON.parseObject(docInfoJson, Feature.OrderedField, Feature.DisableCircularReferenceDetect); DocParser docParser = this.buildDocParser(docRoot); DocInfo docInfo = docParser.parseJson(docRoot); + docInfo.setServiceId(serviceInstance.getServiceId()); docDefinitionMap.put(docInfo.getTitle(), docInfo); } catch (Exception e) { // 这里报错可能是因为有些微服务没有配置swagger文档,导致404访问不到 @@ -134,11 +127,6 @@ public class DocManagerImpl implements DocManager { } } - @Override - public DocItem get(String method, String version) { - return docItemMap.get(method + version); - } - @Override public DocInfo getByTitle(String title) { return docDefinitionMap.get(title); @@ -164,28 +152,73 @@ public class DocManagerImpl implements DocManager { executorService.execute(new Consumer(queue, this)); ZookeeperContext.setEnvironment(environment); - String routeRootPath = ZookeeperContext.getRouteRootPath(); + String serviceTempRootPath = ZookeeperContext.getServiceTempRootPath(); + ZookeeperContext.createPath(serviceTempRootPath, "{}"); // 如果节点内容有变化则自动更新文档 - ZookeeperContext.listenChildren(routeRootPath, 1, (client, event) -> { - if (listenInited) { - long id = System.currentTimeMillis(); + + ZookeeperContext.getChildrenAndListen(serviceTempRootPath, childDataList -> { + for (ChildData childData : childDataList) { + String serviceIdPath = childData.getPath(); + try { + boolean hasChildren = ZookeeperContext.hasChildren(serviceIdPath); + if (hasChildren) { + log.info("加载文档服务器,path:{}", serviceIdPath); + listenServiceIdPath(serviceIdPath); + } + } catch (Exception e) { + log.error("监听路径失败,serviceIdPath:{}", serviceIdPath); + } + } + }, (client, event) -> { + PathChildrenCacheEvent.Type type = event.getType(); + if (type == PathChildrenCacheEvent.Type.CHILD_ADDED) { + String serviceIdPath = event.getData().getPath(); + log.info("新增文档服务器,path:{}", serviceIdPath); + listenServiceIdPath(serviceIdPath); + } + }); + } + + private void listenServiceIdPath(String serviceIdPath) throws Exception { + ZookeeperContext.listenChildren(serviceIdPath, (client, event) -> { + String path = event.getData().getPath(); + PathChildrenCacheEvent.Type type = event.getType(); + log.info("服务节点变更,path:{}, eventType:{}", path, event.getType().name()); + if (type == PathChildrenCacheEvent.Type.CHILD_ADDED + || type == PathChildrenCacheEvent.Type.CHILD_UPDATED) { byte[] data = event.getData().getData(); String serviceInfoJson = new String(data); + if (StringUtils.isEmpty(serviceInfoJson)) { + return; + } ZKServiceInfo serviceInfo = JSON.parseObject(serviceInfoJson, ZKServiceInfo.class); String serviceId = serviceInfo.getServiceId(); - log.info("微服务[{}]推送更新", serviceId); - Msg msg = new Msg(id, 1000 * NumberUtils.toInt(refreshSeconds, 60)); + int delaySeconds = NumberUtils.toInt(refreshSeconds, 60); + log.info("微服务[{}]推送更新,{}秒后加载文档内容", serviceId, delaySeconds); + long id = System.currentTimeMillis(); + Msg msg = new Msg(id, delaySeconds * 1000); msg.serviceId = serviceId; // 延迟20秒执行 queue.offer(msg); - } - TreeCacheEvent.Type type = event.getType(); - if (type == TreeCacheEvent.Type.INITIALIZED) { - listenInited = true; + } else if (event.getType() == PathChildrenCacheEvent.Type.CHILD_REMOVED) { + byte[] data = event.getData().getData(); + String serviceInfoJson = new String(data); + ZKServiceInfo serviceInfo = JSON.parseObject(serviceInfoJson, ZKServiceInfo.class); + String serviceId = serviceInfo.getServiceId(); + boolean hasChildren = ZookeeperContext.hasChildren(serviceIdPath); + // 如果没有子节点就删除 + if (!hasChildren) { + log.info("服务节点已删除,删除对应文档信息,path:{}", event.getData().getPath()); + removeDoc(serviceId); + } } }); } + public void removeDoc(String serviceId) { + docDefinitionMap.entrySet().removeIf(entry -> serviceId.equalsIgnoreCase(entry.getValue().getServiceId())); + } + static class Msg implements Delayed { private long id; private long delay; @@ -202,8 +235,7 @@ public class DocManagerImpl implements DocManager { @Override public int compareTo(Delayed delayed) { Msg msg = (Msg) delayed; - return Long.valueOf(this.id) > Long.valueOf(msg.id) ? 1 - : (Long.valueOf(this.id) < Long.valueOf(msg.id) ? -1 : 0); + return Long.compare(this.id, msg.id); } // 延迟任务是否到时就是按照这个方法判断如果返回的是负数则说明到期否则还没到期