序
本文主要研究一下 nacos client 的 MetricsMonitor
MetricsMonitor
nacos-1.1.3/client/src/main/java/com/alibaba/nacos/client/monitor/MetricsMonitor.java
public class MetricsMonitor {private static Gauge nacosMonitor = Gauge.build()
.name("nacos_monitor").labelNames("module", "name")
.help("nacos_monitor").register();
private static Histogram nacosClientRequestHistogram = Histogram.build().labelNames("module", "method", "url", "code")
.name("nacos_client_request").help("nacos_client_request")
.register();
public static Gauge.Child getServiceInfoMapSizeMonitor() {return nacosMonitor.labels("naming", "serviceInfoMapSize");
}
public static Gauge.Child getDom2BeatSizeMonitor() {return nacosMonitor.labels("naming", "dom2BeatSize");
}
public static Gauge.Child getListenConfigCountMonitor() {return nacosMonitor.labels("naming", "listenConfigCount");
}
public static Histogram.Timer getConfigRequestMonitor(String method, String url, String code) {return nacosClientRequestHistogram.labels("config", method, url, code).startTimer();}
public static Histogram.Child getNamingRequestMonitor(String method, String url, String code) {return nacosClientRequestHistogram.labels("naming", method, url, code);
}
}
- MetricsMonitor 内置了 nacosMonitor、nacosClientRequestHistogram;并提供了 getServiceInfoMapSizeMonitor、getDom2BeatSizeMonitor、getListenConfigCountMonitor、getConfigRequestMonitor、getNamingRequestMonitor 静态方法
MetricsHttpAgent
nacos-1.1.3/client/src/main/java/com/alibaba/nacos/client/config/http/MetricsHttpAgent.java
public class MetricsHttpAgent implements HttpAgent {
private HttpAgent httpAgent;
public MetricsHttpAgent(HttpAgent httpAgent) {this.httpAgent = httpAgent;}
@Override
public void start() throws NacosException {httpAgent.start();
}
@Override
public HttpResult httpGet(String path, List<String> headers, List<String> paramValues, String encoding, long readTimeoutMs) throws IOException {Histogram.Timer timer = MetricsMonitor.getConfigRequestMonitor("GET", path, "NA");
HttpResult result = null;
try {result = httpAgent.httpGet(path, headers, paramValues, encoding, readTimeoutMs);
} catch (IOException e) {throw e;} finally {timer.observeDuration();
timer.close();}
return result;
}
@Override
public HttpResult httpPost(String path, List<String> headers, List<String> paramValues, String encoding, long readTimeoutMs) throws IOException {Histogram.Timer timer = MetricsMonitor.getConfigRequestMonitor("POST", path, "NA");
HttpResult result = null;
try {result = httpAgent.httpPost(path, headers, paramValues, encoding, readTimeoutMs);
} catch (IOException e) {throw e;} finally {timer.observeDuration();
timer.close();}
return result;
}
@Override
public HttpResult httpDelete(String path, List<String> headers, List<String> paramValues, String encoding, long readTimeoutMs) throws IOException {Histogram.Timer timer = MetricsMonitor.getConfigRequestMonitor("DELETE", path, "NA");
HttpResult result = null;
try {result = httpAgent.httpDelete(path, headers, paramValues, encoding, readTimeoutMs);
} catch (IOException e) {throw e;} finally {timer.observeDuration();
timer.close();}
return result;
}
@Override
public String getName() {return httpAgent.getName();
}
@Override
public String getNamespace() {return httpAgent.getNamespace();
}
@Override
public String getTenant() {return httpAgent.getTenant();
}
@Override
public String getEncode() {return httpAgent.getEncode();
}
}
- MetricsHttpAgent 代理了 httpAgent,它在 httpGet、httpPost、httpDelete 方法执行前后通过 MetricsMonitor.getConfigRequestMonitor 获取 Histogram.Timer,记录了响应耗时
NamingProxy
nacos-1.1.3/client/src/main/java/com/alibaba/nacos/client/naming/net/NamingProxy.java
public class NamingProxy {
private static final int DEFAULT_SERVER_PORT = 8848;
private int serverPort = DEFAULT_SERVER_PORT;
private String namespaceId;
private String endpoint;
private String nacosDomain;
private List<String> serverList;
private List<String> serversFromEndpoint = new ArrayList<String>();
private long lastSrvRefTime = 0L;
private long vipSrvRefInterMillis = TimeUnit.SECONDS.toMillis(30);
private Properties properties;
public NamingProxy(String namespaceId, String endpoint, String serverList) {
this.namespaceId = namespaceId;
this.endpoint = endpoint;
if (StringUtils.isNotEmpty(serverList)) {this.serverList = Arrays.asList(serverList.split(","));
if (this.serverList.size() == 1) {this.nacosDomain = serverList;}
}
initRefreshSrvIfNeed();}
//......
public String callServer(String api, Map<String, String> params, String curServer, String method)
throws NacosException {long start = System.currentTimeMillis();
long end = 0;
checkSignature(params);
List<String> headers = builderHeaders();
String url;
if (curServer.startsWith(UtilAndComs.HTTPS) || curServer.startsWith(UtilAndComs.HTTP)) {url = curServer + api;} else {if (!curServer.contains(UtilAndComs.SERVER_ADDR_IP_SPLITER)) {curServer = curServer + UtilAndComs.SERVER_ADDR_IP_SPLITER + serverPort;}
url = HttpClient.getPrefix() + curServer + api;}
HttpClient.HttpResult result = HttpClient.request(url, headers, params, UtilAndComs.ENCODING, method);
end = System.currentTimeMillis();
MetricsMonitor.getNamingRequestMonitor(method, url, String.valueOf(result.code))
.observe(end - start);
if (HttpURLConnection.HTTP_OK == result.code) {return result.content;}
if (HttpURLConnection.HTTP_NOT_MODIFIED == result.code) {return StringUtils.EMPTY;}
throw new NacosException(NacosException.SERVER_ERROR, "failed to req API:"
+ curServer + api + ". code:"
+ result.code + "msg:" + result.content);
}
//......
}
- NamingProxy 的 callServer 方法会在执行完 http 请求之后通过 MetricsMonitor.getNamingRequestMonitor 来记录请求耗时
小结
MetricsMonitor 内置了 nacosMonitor、nacosClientRequestHistogram;并提供了 getServiceInfoMapSizeMonitor、getDom2BeatSizeMonitor、getListenConfigCountMonitor、getConfigRequestMonitor、getNamingRequestMonitor 静态方法
doc
- MetricsMonitor