From df17201b9c80a40c0a7c70d995a3f67eec8cdb2e Mon Sep 17 00:00:00 2001 From: winLsy <18332763730@163.com> Date: Mon, 29 Jan 2018 22:51:42 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=B3=A8=E5=86=8C=E4=B8=AD?= =?UTF-8?q?=E5=BF=83=E8=8E=B7=E5=8F=96=E6=B3=A8=E5=86=8C=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E7=9A=84restful=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../micro/fast/common/CommonApplication.java | 2 - .../micro/fast/gateway/config/WebConfig.java | 2 +- .../server/EurekaServerApplication.java | 2 + .../controller/RestfulEurekaController.java | 298 ++++++++++++++++++ .../server2/EurekaServer2Application.java | 2 + ms/upms/README.md | 5 +- .../upms/controller/UpmsUserController.java | 1 - ms/upms/src/main/resources/bootstrap.yml | 1 + 8 files changed, 308 insertions(+), 5 deletions(-) create mode 100644 ms/register-center1/src/main/java/com/micro/fast/eureka/server/controller/RestfulEurekaController.java diff --git a/boot-starter/boot-starter-ssm/src/main/java/com/micro/fast/common/CommonApplication.java b/boot-starter/boot-starter-ssm/src/main/java/com/micro/fast/common/CommonApplication.java index 59f9e8a..8167cb3 100644 --- a/boot-starter/boot-starter-ssm/src/main/java/com/micro/fast/common/CommonApplication.java +++ b/boot-starter/boot-starter-ssm/src/main/java/com/micro/fast/common/CommonApplication.java @@ -1,7 +1,5 @@ package com.micro.fast.common; -import com.micro.fast.common.config.param.MybatisParamConfig; -import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; diff --git a/ms/gateway/src/main/java/com/micro/fast/gateway/config/WebConfig.java b/ms/gateway/src/main/java/com/micro/fast/gateway/config/WebConfig.java index d82e8d5..dbda521 100644 --- a/ms/gateway/src/main/java/com/micro/fast/gateway/config/WebConfig.java +++ b/ms/gateway/src/main/java/com/micro/fast/gateway/config/WebConfig.java @@ -25,7 +25,7 @@ public class WebConfig{ //允许cookie跨域,在cookie跨域的时候,服务端进行设置,浏览器端也要进行显式设置是否发送。 // corsConfiguration.setAllowCredentials(true); //能给这个服务器发起请求的url,当这个值设置为*的时候,cookie就不能随着请求进行发送了。因为cookie必须是同源的。 - corsConfiguration.addAllowedOrigin("http://fthipw.natappfree.cc"); + corsConfiguration.addAllowedOrigin("*"); //允许的请求头为全部 corsConfiguration.addAllowedHeader("*"); //允许的请求类型 diff --git a/ms/register-center1/src/main/java/com/micro/fast/eureka/server/EurekaServerApplication.java b/ms/register-center1/src/main/java/com/micro/fast/eureka/server/EurekaServerApplication.java index 9fd57c9..cbe7194 100644 --- a/ms/register-center1/src/main/java/com/micro/fast/eureka/server/EurekaServerApplication.java +++ b/ms/register-center1/src/main/java/com/micro/fast/eureka/server/EurekaServerApplication.java @@ -4,6 +4,7 @@ package com.micro.fast.eureka.server; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; +import springfox.documentation.swagger2.annotations.EnableSwagger2; /** * 注册中心启动类 @@ -13,6 +14,7 @@ import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; */ @SpringBootApplication @EnableEurekaServer //开启注册中心相关服务,默认配置注册中心会注册自己 +@EnableSwagger2 public class EurekaServerApplication { /** * 注册中心方法 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 new file mode 100644 index 0000000..5023354 --- /dev/null +++ b/ms/register-center1/src/main/java/com/micro/fast/eureka/server/controller/RestfulEurekaController.java @@ -0,0 +1,298 @@ +package com.micro.fast.eureka.server.controller; + +import com.netflix.appinfo.AmazonInfo; +import com.netflix.appinfo.ApplicationInfoManager; +import com.netflix.appinfo.DataCenterInfo; +import com.netflix.appinfo.InstanceInfo; +import com.netflix.config.ConfigurationManager; +import com.netflix.discovery.shared.Application; +import com.netflix.discovery.shared.Pair; +import com.netflix.eureka.EurekaServerContext; +import com.netflix.eureka.EurekaServerContextHolder; +import com.netflix.eureka.cluster.PeerEurekaNode; +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 org.apache.http.HttpStatus; +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 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}"}) +public class RestfulEurekaController { + + + @Value("${eureka.restful.path:/restful/eureka}") + private String restfulPath = ""; + /** + * 实例管理对象 + */ + private ApplicationInfoManager applicationInfoManager; + + public RestfulEurekaController(ApplicationInfoManager applicationInfoManager) { + this.applicationInfoManager = applicationInfoManager; + } + + /** + * 获取详细信息 + * @param request + * @return + */ + @GetMapping + @ResponseBody + public Map status(HttpServletRequest request, HttpServletResponse response) { + Map map = new HashMap<>(); + populateBase(request, map); + populateApps(map); + StatusInfo statusInfo; + try { + statusInfo = new StatusResource().getStatusInfo(); + } + 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<>(); + populateBase(request, map); + PeerAwareInstanceRegistryImpl registry = (PeerAwareInstanceRegistryImpl) getRegistry(); + ArrayList> lastNCanceled = new ArrayList<>(); + List> list = registry.getLastNCanceledInstances(); + for (Pair entry : list) { + lastNCanceled.add(registeredInstance(entry.second(), entry.first())); + } + map.put("lastNCanceled", lastNCanceled); + list = registry.getLastNRegisteredInstances(); + ArrayList> lastNRegistered = new ArrayList<>(); + for (Pair entry : list) { + lastNRegistered.add(registeredInstance(entry.second(), entry.first())); + } + map.put("lastNRegistered", lastNRegistered); + return map; + } + + private Map registeredInstance(String id, long date) { + HashMap map = new HashMap<>(); + map.put("id", id); + map.put("date", new Date(date)); + return map; + } + + 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); + } + + private void populateHeader(Map model) { + model.put("currentTime", StatusResource.getCurrentTimeAsString()); + model.put("upTime", StatusInfo.getUpTime()); + model.put("environment", ConfigurationManager.getDeploymentContext() + .getDeploymentEnvironment()); + model.put("datacenter", ConfigurationManager.getDeploymentContext() + .getDeploymentDatacenter()); + PeerAwareInstanceRegistry registry = getRegistry(); + model.put("registry", registry); + model.put("isBelowRenewThresold", registry.isBelowRenewThresold() == 1); + DataCenterInfo info = applicationInfoManager.getInfo().getDataCenterInfo(); + if (info.getName() == DataCenterInfo.Name.Amazon) { + AmazonInfo amazonInfo = (AmazonInfo) info; + model.put("amazonInfo", amazonInfo); + model.put("amiId", amazonInfo.get(AmazonInfo.MetaDataKey.amiId)); + model.put("availabilityZone", + amazonInfo.get(AmazonInfo.MetaDataKey.availabilityZone)); + model.put("instanceId", amazonInfo.get(AmazonInfo.MetaDataKey.instanceId)); + } + } + + private PeerAwareInstanceRegistry getRegistry() { + return getServerContext().getRegistry(); + } + + private EurekaServerContext getServerContext() { + return EurekaServerContextHolder.getInstance().getServerContext(); + } + + private void populateNavbar(HttpServletRequest request, Map model) { + Map replicas = new LinkedHashMap<>(); + List list = getServerContext().getPeerEurekaNodes().getPeerNodesView(); + for (PeerEurekaNode node : list) { + try { + URI uri = new URI(node.getServiceUrl()); + String href = scrubBasicAuth(node.getServiceUrl()); + replicas.put(uri.getHost(), href); + } + catch (Exception ex) { + // ignore? + } + } + model.put("replicas", replicas.entrySet()); + } + + private void populateApps(Map model) { + List sortedApplications = getRegistry().getSortedApplications(); + ArrayList> apps = new ArrayList<>(); + for (Application app : sortedApplications) { + LinkedHashMap appData = new LinkedHashMap<>(); + apps.add(appData); + appData.put("name", app.getName()); + Map amiCounts = new HashMap<>(); + Map>> instancesByStatus = new HashMap<>(); + Map zoneCounts = new HashMap<>(); + for (InstanceInfo info : app.getInstances()) { + String id = info.getId(); + String url = info.getStatusPageUrl(); + InstanceInfo.InstanceStatus status = info.getStatus(); + String ami = "n/a"; + String zone = ""; + if (info.getDataCenterInfo().getName() == DataCenterInfo.Name.Amazon) { + AmazonInfo dcInfo = (AmazonInfo) info.getDataCenterInfo(); + ami = dcInfo.get(AmazonInfo.MetaDataKey.amiId); + zone = dcInfo.get(AmazonInfo.MetaDataKey.availabilityZone); + } + Integer count = amiCounts.get(ami); + if (count != null) { + amiCounts.put(ami, count + 1); + } + else { + amiCounts.put(ami, 1); + } + count = zoneCounts.get(zone); + if (count != null) { + zoneCounts.put(zone, count + 1); + } + else { + zoneCounts.put(zone, 1); + } + List> list = instancesByStatus.get(status); + if (list == null) { + list = new ArrayList<>(); + instancesByStatus.put(status, list); + } + list.add(new Pair<>(id, url)); + } + appData.put("amiCounts", amiCounts.entrySet()); + appData.put("zoneCounts", zoneCounts.entrySet()); + ArrayList> instanceInfos = new ArrayList<>(); + appData.put("instanceInfos", instanceInfos); + for (Iterator>>> iter = instancesByStatus + .entrySet().iterator(); iter.hasNext();) { + Map.Entry>> entry = iter + .next(); + List> value = entry.getValue(); + InstanceInfo.InstanceStatus status = entry.getKey(); + LinkedHashMap instanceData = new LinkedHashMap<>(); + instanceInfos.add(instanceData); + instanceData.put("status", entry.getKey()); + 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); + instance.put("id", p.first()); + String url = p.second(); + 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); + } + + private void populateInstanceInfo(Map model, StatusInfo statusInfo) { + InstanceInfo instanceInfo = statusInfo.getInstanceInfo(); + Map instanceMap = new HashMap<>(); + instanceMap.put("ipAddr", instanceInfo.getIPAddr()); + instanceMap.put("status", instanceInfo.getStatus().toString()); + if (instanceInfo.getDataCenterInfo().getName() == DataCenterInfo.Name.Amazon) { + AmazonInfo info = (AmazonInfo) instanceInfo.getDataCenterInfo(); + instanceMap.put("availability-zone", + info.get(AmazonInfo.MetaDataKey.availabilityZone)); + instanceMap.put("public-ipv4", info.get(AmazonInfo.MetaDataKey.publicIpv4)); + instanceMap.put("instance-id", info.get(AmazonInfo.MetaDataKey.instanceId)); + instanceMap.put("public-hostname", + info.get(AmazonInfo.MetaDataKey.publicHostname)); + instanceMap.put("ami-id", info.get(AmazonInfo.MetaDataKey.amiId)); + instanceMap.put("instance-type", + info.get(AmazonInfo.MetaDataKey.instanceType)); + } + model.put("instanceInfo", instanceMap); + } + + protected void filterReplicas(Map model, StatusInfo statusInfo) { + Map applicationStats = statusInfo.getApplicationStats(); + 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("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+","; + } + } + return filteredUrls.substring(0,filteredUrls.length()-1); + } +} + diff --git a/ms/register-center2/src/main/java/com/micro/fast/eureka/server2/EurekaServer2Application.java b/ms/register-center2/src/main/java/com/micro/fast/eureka/server2/EurekaServer2Application.java index 7295ed0..1510b12 100644 --- a/ms/register-center2/src/main/java/com/micro/fast/eureka/server2/EurekaServer2Application.java +++ b/ms/register-center2/src/main/java/com/micro/fast/eureka/server2/EurekaServer2Application.java @@ -3,6 +3,7 @@ package com.micro.fast.eureka.server2; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; +import springfox.documentation.swagger2.annotations.EnableSwagger2; /** * 注册中心启动类 @@ -12,6 +13,7 @@ import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; */ @SpringBootApplication @EnableEurekaServer //开启注册中心的相关服务 +@EnableSwagger2 public class EurekaServer2Application { /** * 注册中心启动方法 diff --git a/ms/upms/README.md b/ms/upms/README.md index 3e99a06..7f81173 100644 --- a/ms/upms/README.md +++ b/ms/upms/README.md @@ -8,4 +8,7 @@ ## 服务消费,服务熔断,服务降级,线程隔离 ## 服务熔断,降级情况的统计 监控界面访问地址`/hystrix`,监控数据的获取地址`hystrix.stream` -## 服务调用的监控数据生成 \ No newline at end of file +## 服务调用的监控数据生成 + +`@PostConstruct`注解修饰的方法会在tomcat加载servlet之前运行 +`@PreConstruct`注解修饰的方法会在tomcat卸载servlet的时候运行 \ No newline at end of file diff --git a/ms/upms/src/main/java/com/micro/fast/upms/controller/UpmsUserController.java b/ms/upms/src/main/java/com/micro/fast/upms/controller/UpmsUserController.java index f365587..636ae04 100644 --- a/ms/upms/src/main/java/com/micro/fast/upms/controller/UpmsUserController.java +++ b/ms/upms/src/main/java/com/micro/fast/upms/controller/UpmsUserController.java @@ -63,7 +63,6 @@ public class UpmsUserController { if (upmsUser.getLocked() == 1){ return ServerResponse.errorMsg("账户被锁定"); } - upmsUser.setPassword(null); return ServerResponse.successData(upmsUser); } } diff --git a/ms/upms/src/main/resources/bootstrap.yml b/ms/upms/src/main/resources/bootstrap.yml index d679d77..a2feefa 100644 --- a/ms/upms/src/main/resources/bootstrap.yml +++ b/ms/upms/src/main/resources/bootstrap.yml @@ -19,6 +19,7 @@ eureka: # 配置熔断监控的集群名称 metadata-map: cluster: ms-upms + instance-id: www.upms.com