前言
项目框架:
spring cloud框架,网关使用的gateway,注册中心使用的eureka,服务间调用使用的feign,配置中心使用的apollo,spring cloud版本使用的Greenwich.SR5,spring boot使用的2.1.14.RELEASE版本
后来公司要求把项目接入prometheus+grafana监控,监控数据统一从consul注册中心地址上获取,prometheus和grafana已经由运维搭建并把对应服务接入到prometheus,所以我需要做的就是按照运维要求的格式把服务注册到consul注册中心上去
过程
开始我以为直接把eureka注册中心替换成consul就行了,然后eureka注册中心就不用了,但是最后注册完之后,发现服务间调用有问题,然后就又在consul注册中心和eureka各注册了一份服务,但是最后发现注册的方法还不一样,最后让公司同事给我发了一下他已经注册好的使用的工具类【没有重写consul注册中心的register方法,采用直接向consul注册中心地址发送一个http请求,http请求携带要注册到consul上的数据直接注册的,这样是更简便的方法,另外可以减少项目架构升级带来的兼容影响,并且可以少依赖一个spring cloud的consul的依赖】
依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--Prometheus配置-->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<version>1.1.3</version>
</dependency>
工具类
package com.wanshun.wsf.common.config;
import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import javax.annotation.PostConstruct;
import java.io.IOException;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
@Configuration
@ConditionalOnProperty(prefix = PrometheusConsulRegister.PROMETHEUS_CONSUL_CONF, value = "enable")
@ConfigurationProperties(prefix = PrometheusConsulRegister.PROMETHEUS_CONSUL_CONF)
public class PrometheusConsulRegister {
public static final String PROMETHEUS_CONSUL_CONF = "prometheus.consul";
private final Logger logger = LoggerFactory.getLogger(PrometheusConsulRegister.class);
@Autowired
private Environment environment;
/**
* consul注册路径
*/
private String registerUrl = "/v1/agent/service/register";
/**
* consul地址
*/
private String address;
/**
* consul端口
*/
private Integer port;
/**
* consul标签
*/
private List<String> tags;
/**
* meta健康检查地址
*/
private String healthUrl = "/actuator/health";
/**
* 健康检查间隔
*/
private String interval = "30s";
/**
* meta项目名
*/
private String metaProject;
/**
* meta应用名
*/
private String metaAppName;
/**
* meta导出器
*/
private String metaExporter;
/**
* meta项目类型
*/
private String metaCategory;
/**
* 指标路径
*/
private String metaUrl = "/actuator/prometheus";
@PostConstruct
public void init() {
//参数校验
verificationConfig();
CloseableHttpClient httpClient = null;
CloseableHttpResponse response = null;
try {
HttpUriRequest httpUriRequest = initRegisterHttpRequest();
httpClient = HttpClientBuilder.create().build();
response = httpClient.execute(httpUriRequest);
int statusCode = response.getStatusLine().getStatusCode();
logger.info(" Prometheus-Consul 监控注册 | STATUS = {}", statusCode);
if (200 == statusCode) {
logger.info(" Prometheus-Consul 监控注册成功...");
return;
}
logger.error(" Prometheus-Consul 监控注册失败 | ENTITY = {}", EntityUtils.toString(response.getEntity()));
throw new RuntimeException(" Prometheus-Consul 监控注册失败...");
} catch (Exception e) {
logger.error(" Prometheus-Consul 监控注册出现异常... ");
throw new RuntimeException(e);
} finally {
try {
if (httpClient != null) {
httpClient.close();
}
if (response != null) {
response.close();
}
} catch (IOException ioException) {
logger.error("流关闭失败.", ioException);
}
}
}
private HttpUriRequest initRegisterHttpRequest() throws Exception {
String httpUrl = getHttpUrl(address, port, "", registerUrl);
HttpPut httpPut = new HttpPut(httpUrl);
String param = JSON.toJSONString(getParam());
logger.info(" Prometheus-Consul 监控注册: {}", registerUrl);
logger.info(" Request param: {}", param);
httpPut.setEntity(new StringEntity(param, "UTF-8"));
return httpPut;
}
private RegisterParam getParam() throws Exception {
InetAddress inetAddress = Inet4Address.getLocalHost();
String hostname = inetAddress.getHostName();
String host = inetAddress.getHostAddress();
Integer metaPort = Integer.parseInt(environment.getProperty("server.port"));
String contextPath = environment.getProperty("server.servlet.context-path", "");
RegisterParam registerParam = new RegisterParam();
registerParam.setId(new StringBuffer(metaAppName).append(" [").append(hostname).append("]").append("-[").append(host).append("]").toString());
registerParam.setName(metaAppName);
registerParam.setAddress(host);
registerParam.setPort(metaPort);
registerParam.setMeta(new Meta(metaProject, metaCategory, metaExporter, hostname, metaAppName, contextPath + metaUrl));
registerParam.setTags(tags);
String metaHttpUrl = getHttpUrl(host, metaPort, contextPath, healthUrl);
registerParam.getChecks().add(new Check(metaHttpUrl, interval));
return registerParam;
}
private String getHttpUrl(String host, Object metaPort, String contextPath, String url) {
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("http://").append(host).append(":").append(metaPort).append(contextPath).append(url);
return stringBuffer.toString();
}
private void verificationConfig() {
if (StringUtils.isBlank(address)) {
throw new RuntimeException("缺少配置 [prometheus.consul.address]");
}
if (null == port) {
throw new RuntimeException("缺少配置 [prometheus.consul.port]");
}
if (tags.isEmpty()) {
throw new RuntimeException("缺少配置 [prometheus.consul.tags]");
}
if (StringUtils.isBlank(metaProject)) {
throw new RuntimeException("缺少配置 [prometheus.consul.meta.project]");
}
if (StringUtils.isBlank(metaAppName)) {
throw new RuntimeException("缺少配置 [prometheus.consul.meta.appName]");
}
if (StringUtils.isBlank(metaExporter)) {
throw new RuntimeException("缺少配置 [prometheus.consul.meta.exporter]");
}
if (StringUtils.isBlank(metaCategory)) {
throw new RuntimeException("缺少配置 [prometheus.consul.meta.category]");
}
}
class RegisterParam {
private String id;
private String name;
private String address;
private Integer port;
private List<String> tags = new ArrayList<>();
private Meta meta;
private List<Check> checks = new ArrayList<>();
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
public List<String> getTags() {
return tags;
}
public void setTags(List<String> tags) {
this.tags = tags;
}
public Meta getMeta() {
return meta;
}
public void setMeta(Meta meta) {
this.meta = meta;
}
public List<Check> getChecks() {
return checks;
}
public void setChecks(List<Check> checks) {
this.checks = checks;
}
}
class Meta {
private String project;
private String category;
private String exporter;
private String hostname;
private String appname;
private String metric;
public Meta(String project, String category, String exporter, String hostname, String appname, String metric) {
this.project = project;
this.category = category;
this.exporter = exporter;
this.hostname = hostname;
this.appname = appname;
this.metric = metric;
}
public String getProject() {
return project;
}
public void setProject(String project) {
this.project = project;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public String getExporter() {
return exporter;
}
public void setExporter(String exporter) {
this.exporter = exporter;
}
public String getHostname() {
return hostname;
}
public void setHostname(String hostname) {
this.hostname = hostname;
}
public String getAppname() {
return appname;
}
public void setAppname(String appname) {
this.appname = appname;
}
public String getMetric() {
return metric;
}
public void setMetric(String metric) {
this.metric = metric;
}
}
class Check {
private String http;
private String interval;
public Check(String http, String interval) {
this.http = http;
this.interval = interval;
}
public String getHttp() {
return http;
}
public void setHttp(String http) {
this.http = http;
}
public String getInterval() {
return interval;
}
public void setInterval(String interval) {
this.interval = interval;
}
}
public void setAddress(String address) {
this.address = address;
}
public void setPort(Integer port) {
this.port = port;
}
public void setTags(List<String> tags) {
this.tags = tags;
}
public void setInterval(String interval) {
this.interval = interval;
}
public void setMetaProject(String metaProject) {
this.metaProject = metaProject;
}
public void setMetaAppName(String metaAppName) {
this.metaAppName = metaAppName;
}
public void setMetaExporter(String metaExporter) {
this.metaExporter = metaExporter;
}
public void setMetaCategory(String metaCategory) {
this.metaCategory = metaCategory;
}
public void setRegisterUrl(String registerUrl) {
this.registerUrl = registerUrl;
}
public void setHealthUrl(String healthUrl) {
this.healthUrl = healthUrl;
}
}
Apollo配置中心配置
这个是配置中心配置
#management监控配置
management.endpoints.web.exposure.include=health,prometheus
management.health.elasticsearch.enabled=false
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always
management.health.elasticsearch.enabled=false
#prometheus-consul注册监控配置
#开启注册监控
prometheus.consul.enable=true
#注册接口
#prometheus.consul.register-url=/v1/agent/service/register
#consul地址
prometheus.consul.address=
#consul端口
prometheus.consul.port=8500
#环境tag
prometheus.consul.tags=${spring.profiles.active}
#健康检测间隔
prometheus.consul.interval=30s
#健康检查地址
#prometheus.consul.health-url=/actuator/health
#项目名
prometheus.consul.meta-project=wsf-mall
#应用服务名
prometheus.consul.meta-appName=${spring.application.name}
#应用服务类型
prometheus.consul.meta-category=SERVICE
#指标导出器名称(指标类型)
prometheus.consul.meta-exporter=wsf_mall_exporter
效果:
PS:对于一些属性还是没有弄太清楚,先记录,以后有用了再说