• 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

  • 相关阅读:
    堆排序
    深入理解创建类设计模式(Creational Patterns)
    (Head First)设计模式基础
    SpringMVC中的适配器模式应用
    软工团队任务
    visio画UML用例图
    安卓架构设计
    结对项目编程之代码进展
    工大助手(爬虫——查成绩部分)
    设计模式
  • 原文地址:https://www.cnblogs.com/jing-yi/p/14392359.html
Copyright © 2020-2023  润新知