From b07cca09220cf23371b2fa1a7b783d228deec587 Mon Sep 17 00:00:00 2001 From: winLsy <18332763730@163.com> Date: Tue, 30 Jan 2018 22:37:56 +0800 Subject: [PATCH] =?UTF-8?q?=E8=8E=B7=E5=8F=96=E6=89=80=E6=9C=89=E7=9A=84?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E5=AE=9E=E4=BE=8B=E7=9A=84=E7=AE=80=E5=8D=95?= =?UTF-8?q?=E4=BF=A1=E6=81=AF,=E6=A0=B9=E6=8D=AE=E4=B8=BB=E6=9C=BA?= =?UTF-8?q?=E5=90=8D=E8=8E=B7=E5=8F=96=E6=9F=90=E4=B8=AA=E5=AE=9E=E4=BE=8B?= =?UTF-8?q?=E7=9A=84=E4=BF=A1=E6=81=AF,=E6=A0=B9=E6=8D=AEappId=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E5=AE=9E=E4=BE=8B=EF=BC=8C=E5=8F=AF=E8=83=BD=E6=9C=89?= =?UTF-8?q?=E5=A4=9A=E4=B8=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ms/register-center1/README.md | 5 +- ms/register-center1/pom.xml | 6 + .../controller/RestfulEurekaController.java | 170 ++++++++++++------ 3 files changed, 121 insertions(+), 60 deletions(-) diff --git a/ms/register-center1/README.md b/ms/register-center1/README.md index 0a16ef9..7f5515d 100644 --- a/ms/register-center1/README.md +++ b/ms/register-center1/README.md @@ -1,4 +1,7 @@ # 高可用注册中心 相同的hostname的注册中心eureka会认为是这些euraka在同一台物理机上,这些eureka会一共存储 一份注册者的信息,而不是每个注册中心存储一份。所以在同一台机器上模拟高可用注册中心的时候 -必须修改hosts文件,注册中心使用不同的hostname \ No newline at end of file +必须修改hosts文件,注册中心使用不同的hostname + +#### 增加了注册实例查询的restful接口 +默认的base路径是`/restful/eureka` \ No newline at end of file diff --git a/ms/register-center1/pom.xml b/ms/register-center1/pom.xml index 730a1a9..4bc764b 100644 --- a/ms/register-center1/pom.xml +++ b/ms/register-center1/pom.xml @@ -41,6 +41,12 @@ org.springframework.boot spring-boot-starter-security + + + com.micro.fast + boot-starter-common + ${micro.fast.version} + org.springframework.boot diff --git a/ms/register-center1/src/main/java/com/micro/fast/eureka/server/controller/RestfulEurekaController.java b/ms/register-center1/src/main/java/com/micro/fast/eureka/server/controller/RestfulEurekaController.java index 5023354..5663e7f 100644 --- a/ms/register-center1/src/main/java/com/micro/fast/eureka/server/controller/RestfulEurekaController.java +++ b/ms/register-center1/src/main/java/com/micro/fast/eureka/server/controller/RestfulEurekaController.java @@ -1,5 +1,6 @@ package com.micro.fast.eureka.server.controller; +import com.micro.fast.boot.starter.common.response.ServerResponse; import com.netflix.appinfo.AmazonInfo; import com.netflix.appinfo.ApplicationInfoManager; import com.netflix.appinfo.DataCenterInfo; @@ -14,28 +15,33 @@ import com.netflix.eureka.registry.PeerAwareInstanceRegistry; import com.netflix.eureka.registry.PeerAwareInstanceRegistryImpl; import com.netflix.eureka.resources.StatusResource; import com.netflix.eureka.util.StatusInfo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.apache.commons.lang.StringUtils; import org.apache.http.HttpStatus; +import org.mortbay.jetty.Server; import org.springframework.beans.factory.annotation.Value; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.net.URI; import java.util.*; + /** * restful操作eureka的接口 + * * @author lsy */ @RestController @RequestMapping({"${eureka.restful.path:/restful/eureka}"}) +@Api(description = "注册中心的restful接口") public class RestfulEurekaController { @Value("${eureka.restful.path:/restful/eureka}") - private String restfulPath = ""; + private String restfulPath = "/restful/eureka"; + /** * 实例管理对象 */ @@ -45,11 +51,64 @@ public class RestfulEurekaController { this.applicationInfoManager = applicationInfoManager; } - /** - * 获取详细信息 - * @param request - * @return - */ + @GetMapping("/apps") + @ApiOperation("获取所有的服务实例的简单信息") + public ServerResponse apps(HttpServletRequest request, HttpServletResponse response) { + Map map = new HashMap<>(); + //获取所有服务的信息 + populateApps(map); + return ServerResponse.successMsgData("获取所有实例成功", map); + } + + @GetMapping("/apps/{instanceId}") + @ApiOperation("根据主机名获取某个实例的信息") + public ServerResponse getInstance(@PathVariable("instanceId") String instanceId) { + InstanceInfo instanceInfo = null; + if (StringUtils.isNotBlank(instanceId)){ + List sortedApplications = getRegistry().getSortedApplications(); + boolean isBreak = false; + for (Application sortedApplication : sortedApplications) { + List instances = sortedApplication.getInstances(); + for (InstanceInfo instance : instances) { + String hostName = instance.getHostName(); + if (hostName.startsWith(instanceId)){ + instanceInfo = instance; + isBreak = true; + break; + } + } + if (isBreak){ + break; + } + } + }else { + return ServerResponse.errorMsg("instanceId不能为空"); + } + + return ServerResponse.successMsgData("根据主机名获取实例信息成功", instanceInfo); + } + @GetMapping("/apps/{appId}") + @ApiOperation("根据appId查询实例,可能有多个") + public ServerResponse getInstancesByAppId(@PathVariable("appId") String appId) { + Set instanceInfos = new HashSet<>(10); + if (StringUtils.isNotBlank(appId)){ + List sortedApplications = getRegistry().getSortedApplications(); + for (Application sortedApplication : sortedApplications) { + List instances = sortedApplication.getInstances(); + for (InstanceInfo instance : instances) { + if (appId.equals(instance.getAppName())){ + instanceInfos.add(instance); + } + } + + } + }else { + return ServerResponse.errorMsg("instanceId不能为空"); + } + + return ServerResponse.successMsgData("根据主机名获取实例信息成功", instanceInfos); + } + @GetMapping @ResponseBody public Map status(HttpServletRequest request, HttpServletResponse response) { @@ -58,26 +117,27 @@ public class RestfulEurekaController { populateApps(map); StatusInfo statusInfo; try { + //获取当前注册中心的本身的相信信息 statusInfo = new StatusResource().getStatusInfo(); - } - catch (Exception e) { + } catch (Exception e) { + //获取当前注册中心的本身的相信信息 statusInfo = StatusInfo.Builder.newBuilder().isHealthy(false).build(); } map.put("statusInfo", statusInfo); populateInstanceInfo(map, statusInfo); filterReplicas(map, statusInfo); - response.setStatus(HttpStatus.SC_OK); return map; } /** * 获取最后注册的实例 + * * @param request * @return */ @GetMapping("/lastn") public Map lastn(HttpServletRequest request) { - Map map = new HashMap<>(); + Map map = new HashMap<>(); populateBase(request, map); PeerAwareInstanceRegistryImpl registry = (PeerAwareInstanceRegistryImpl) getRegistry(); ArrayList> lastNCanceled = new ArrayList<>(); @@ -103,14 +163,15 @@ public class RestfulEurekaController { } protected void populateBase(HttpServletRequest request, Map model) { - model.put("time", new Date()); - model.put("basePath", "/"); - model.put("restfulPath", this.restfulPath.equals("/") ? "" - : this.restfulPath); populateHeader(model); populateNavbar(request, model); } + /** + * 添加注册中心基础信息 + * + * @param model + */ private void populateHeader(Map model) { model.put("currentTime", StatusResource.getCurrentTimeAsString()); model.put("upTime", StatusInfo.getUpTime()); @@ -148,16 +209,22 @@ public class RestfulEurekaController { URI uri = new URI(node.getServiceUrl()); String href = scrubBasicAuth(node.getServiceUrl()); replicas.put(uri.getHost(), href); - } - catch (Exception ex) { + } catch (Exception ex) { // ignore? } } model.put("replicas", replicas.entrySet()); } + /** + * 填所有实例的简单信息 + * + * @param model + */ private void populateApps(Map model) { + //获取实例的详细信息 List sortedApplications = getRegistry().getSortedApplications(); + //封装成简单的信息 ArrayList> apps = new ArrayList<>(); for (Application app : sortedApplications) { LinkedHashMap appData = new LinkedHashMap<>(); @@ -180,15 +247,13 @@ public class RestfulEurekaController { Integer count = amiCounts.get(ami); if (count != null) { amiCounts.put(ami, count + 1); - } - else { + } else { amiCounts.put(ami, 1); } count = zoneCounts.get(zone); if (count != null) { zoneCounts.put(zone, count + 1); - } - else { + } else { zoneCounts.put(zone, 1); } List> list = instancesByStatus.get(status); @@ -203,7 +268,7 @@ public class RestfulEurekaController { ArrayList> instanceInfos = new ArrayList<>(); appData.put("instanceInfos", instanceInfos); for (Iterator>>> iter = instancesByStatus - .entrySet().iterator(); iter.hasNext();) { + .entrySet().iterator(); iter.hasNext(); ) { Map.Entry>> entry = iter .next(); List> value = entry.getValue(); @@ -214,18 +279,6 @@ public class RestfulEurekaController { ArrayList> instances = new ArrayList<>(); instanceData.put("instances", instances); instanceData.put("isNotUp", status != InstanceInfo.InstanceStatus.UP); - - // TODO - - /* - * if(status != InstanceInfo.InstanceStatus.UP){ - * buf.append(""); } - * buf.append("").append(status - * .name()).append(" (").append(value.size()).append(") - "); - * if(status != InstanceInfo.InstanceStatus.UP){ - * buf.append(""); } - */ - for (Pair p : value) { LinkedHashMap instance = new LinkedHashMap<>(); instances.add(instance); @@ -234,20 +287,19 @@ public class RestfulEurekaController { instance.put("url", url); boolean isHref = url != null && url.startsWith("http"); instance.put("isHref", isHref); - /* - * String id = p.first(); String url = p.second(); if(url != null && - * url.startsWith("http")){ - * buf.append(""); }else { url = - * null; } buf.append(id); if(url != null){ buf.append(""); } - * buf.append(", "); - */ + } } - // out.println("" + buf.toString() + ""); } model.put("apps", apps); } + /** + * 填充当前注册中心的信息 + * + * @param model + * @param statusInfo + */ private void populateInstanceInfo(Map model, StatusInfo statusInfo) { InstanceInfo instanceInfo = statusInfo.getInstanceInfo(); Map instanceMap = new HashMap<>(); @@ -270,29 +322,29 @@ public class RestfulEurekaController { protected void filterReplicas(Map model, StatusInfo statusInfo) { Map applicationStats = statusInfo.getApplicationStats(); - if(applicationStats.get("registered-replicas").contains("@")){ + if (applicationStats.get("registered-replicas").contains("@")) { applicationStats.put("registered-replicas", scrubBasicAuth(applicationStats.get("registered-replicas"))); } - if(applicationStats.get("unavailable-replicas").contains("@")){ - applicationStats.put("unavailable-replicas",scrubBasicAuth(applicationStats.get("unavailable-replicas"))); + if (applicationStats.get("unavailable-replicas").contains("@")) { + applicationStats.put("unavailable-replicas", scrubBasicAuth(applicationStats.get("unavailable-replicas"))); } - if(applicationStats.get("available-replicas").contains("@")){ - applicationStats.put("available-replicas",scrubBasicAuth(applicationStats.get("available-replicas"))); + if (applicationStats.get("available-replicas").contains("@")) { + applicationStats.put("available-replicas", scrubBasicAuth(applicationStats.get("available-replicas"))); } model.put("applicationStats", applicationStats); } - private String scrubBasicAuth(String urlList){ - String[] urls=urlList.split(","); - String filteredUrls=""; - for(String u : urls){ - if(u.contains("@")){ - filteredUrls+=u.substring(0,u.indexOf("//")+2)+u.substring(u.indexOf("@")+1,u.length())+","; - }else{ - filteredUrls+=u+","; + private String scrubBasicAuth(String urlList) { + String[] urls = urlList.split(","); + String filteredUrls = ""; + for (String u : urls) { + if (u.contains("@")) { + filteredUrls += u.substring(0, u.indexOf("//") + 2) + u.substring(u.indexOf("@") + 1, u.length()) + ","; + } else { + filteredUrls += u + ","; } } - return filteredUrls.substring(0,filteredUrls.length()-1); + return filteredUrls.substring(0, filteredUrls.length() - 1); } }