乐趣区

聊聊nacos-client的MetricsMonitor

本文主要研究一下 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
退出移动版