RPC性能指标的收集——Prometheus
对于RPC的性能收集,以微博的motan和阿里的dubbo为例,也是通过intercept去做的。
motan的性能指标收集:使用的是motan中的扩展机制
//此处的spi使用的是weibo.com中的扩展 @SpiMeta(name = "pepperProfiler") @Activation(sequence = 2) public class MotanProfilerFilter implements Filter { //进来的请求指标 private static final Stats PROFILER_STAT_IN = Profiler.Builder .builder() .type("motan") .subType("in") .build(); //对外请求的指标 private static final Stats PROFILER_STAT_OUT = Profiler.Builder .builder() .type("motan") .subType("out") .build(); @Override public Response filter(Caller<?> caller, Request request) { if (!System.getProperty("motanProfileEnable", "true").equalsIgnoreCase("true")) { return caller.call(request); } final String category = MotanUtils.getShortName(request.getInterfaceName()); final String metrics = category + "." + request.getMethodName() + "(" + MotanUtils.getShortName(request.getParamtersDesc()) + ")"; String[] tags = new String[]{"method", metrics, "service", category}; if (StringUtils.isEmpty(metrics) || StringUtils.isEmpty(category)) { return caller.call(request); } long begin = System.nanoTime(); boolean specialException = true; boolean isError = false; beforeCall(tags, caller instanceof Provider); try { final Response response = caller.call(request); if (response == null) { isError = true; } else { if (response.getException() != null) { isError = true; } } specialException = false; return response; } finally { if (specialException) { isError = true; } postCall(tags, caller instanceof Provider, begin, isError); } } private void postCall(String[] tags, boolean isIncoming, long begin, boolean isError) { if (isIncoming) { PROFILER_STAT_IN.observe(System.nanoTime() - begin, TimeUnit.NANOSECONDS, tags); PROFILER_STAT_IN.decConc(tags); if (isError) { PROFILER_STAT_IN.error(tags); } } else { PROFILER_STAT_OUT.observe(System.nanoTime() - begin, TimeUnit.NANOSECONDS, tags); PROFILER_STAT_OUT.decConc(tags); if (isError) { PROFILER_STAT_OUT.error(tags); } } } private void beforeCall(String[] tags, boolean isIncoming) { if (isIncoming) { PROFILER_STAT_IN.incConc(tags); } else { PROFILER_STAT_OUT.incConc(tags); } } }
扩展类文件:因为使用的是motan自带的扩展过滤器,所以这里的文件名要是motan的文件路径。
dubbo的性能指标收集:
定义的指标收集模板类:
public abstract class DubboProfilerFilterTemplate implements Filter { static final Stats PROFILER_STAT_IN = Profiler.Builder .builder() .type("dubbo") .subType("in") .build(); static final Stats PROFILER_STAT_OUT = Profiler.Builder .builder() .type("dubbo") .subType("out") .build(); @Override public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException { final String category = invoker.getInterface().getSimpleName(); // 接口名 StringBuilder params = new StringBuilder(); Class[] clazzs = invocation.getParameterTypes(); for (int index = 0; index < clazzs.length; index++) { params.append(index == clazzs.length - 1 ? clazzs[index].getSimpleName() : clazzs[index].getSimpleName() + ", "); } final String metrics = invocation.getMethodName() + "(" + params.toString() + ")"; // method(参数类型...) String[] tags = new String[]{"method", metrics, "service", category}; if (StringUtils.isEmpty(category) || StringUtils.isEmpty(metrics)) { return invoker.invoke(invocation); } long begin = System.nanoTime(); boolean specialException = true; boolean isError = false; // before trace... beforeInvoke(tags); try { Result result = invoker.invoke(invocation); if (result == null || result.hasException()) { isError = true; } specialException = false; return result; } finally { if (specialException) { isError = true; } // after trace... afterInvoke(tags, begin, isError); } } abstract void afterInvoke(String[] tags, long begin, boolean isError); abstract void beforeInvoke(String[] tags); }
服务提供方收集类:
@Activate(group = {PROVIDER}) public class DubboProviderProfilerFilter extends DubboProfilerFilterTemplate { @Override void afterInvoke(String[] tags, long begin, boolean isError) { PROFILER_STAT_IN.observe(System.nanoTime() - begin, TimeUnit.NANOSECONDS, tags); PROFILER_STAT_IN.decConc(tags); if (isError) { PROFILER_STAT_IN.error(tags); } } @Override void beforeInvoke(String[] tags) { PROFILER_STAT_IN.incConc(tags); } }
服务调用方收集类:
@Activate(group = {CONSUMER}) public class DubboConsumerProfilerFilter extends DubboProfilerFilterTemplate { @Override void afterInvoke(String[] tags, long begin, boolean isError) { PROFILER_STAT_OUT.observe(System.nanoTime() - begin, TimeUnit.NANOSECONDS, tags); PROFILER_STAT_OUT.decConc(tags); if (isError) { PROFILER_STAT_OUT.error(tags); } } @Override void beforeInvoke(String[] tags) { PROFILER_STAT_OUT.incConc(tags); } }
扩展类文件:
总结:到这里,一些列关于Prometheus介绍,端点暴露,健康指标健康,常用的业务级别性能指标(http、mybatis、rpc)的性能指标收集就全都分享完了。最后再推荐一下同事的开源项目:https://github.com/zrbcool/pepper-metrics