本文转载自微信公众号《猿世界》,作者尹继焕。转载本文请联系元天地公众号。PrefaceMicrometer自带了很多其他框架的指标信息,可以通过prometheus方便的收集和监控。常用的信息有JVM信息、Http请求信息、Tomcat线程信息等,对于一些活跃的框架,有些还是不支持的,比如Dubbo。如果我们要监控Dubbo的一些指标,比如线程池的状态,需要手动展开并输出相应的线程池指标。在这种情况下,肯定没有想法,因为你不知道如何扩展。下面介绍一下做某事之前的思考。方法很重要。Dubbo有现成的实现吗?参照千分尺执行指标,跟着葫芦?Dubbo有现成的实现吗?应该没有完整的实现。结果现状,于是在Dubbo的Github上找到了一个相关的项目dubbo-spring-boot-actuator。https://github.com/apache/dubbo-spring-boot-project/tree/master/dubbo-spring-boot-actuatordubbo-spring-boot-actuator看名字就知道,它提供了各种信息端点和健康检查.从这里您可能会找到一些有用的代码。果然在介绍页看到了我想要的东西。线程池的指标数据只是拼接成字符串显示而已。"threadpool":{"source":"management.health.dubbo.status.extras","status":{"level":"OK","message":"Poolstatus:OK,max:200,core:200,largest:0,active:0,task:0,serviceport:12345","description":null}}然后去翻dubbo-spring-boot-actuator的代码,没找到代码的线程池。后来在dubbo.jar中找到了ThreadPoolStatusChecker这个类,核心逻辑就在里面。现在第一个问题已经解决了,就是获取Dubbo的线程池对象。参照千分尺指标执行,照葫芦画瓢?可以获取线程池对象,也可以获取各种数据。下一个问题是如何将其暴露给普罗米修斯集合。有两种方式,一种是自定义一个新的端点暴露,另一种是直接在已有的prometheus端点增加指标数据的输出,也就是照葫芦画瓢。查看源码,已经实现了很多Metrics。我们也可以实现一个Dubbo线程池Metrics。上图中框出的是一个已有的线程池Metrics,可以直接复用代码。实现的主要逻辑是实现一个MeterBinder接口,然后输出你需要的指标。所以打算在bindTo方法中获取Dubbo的线程池对象,然后输出指标。经测试,实例化MeterBinder时Dubbo还没有初始化,无法获取到线程池对象,绑定后无法成功输出指标。后面还是打算用定时采样的方式输出,自定义一个后台线程,定时输出数据。可以使用Timer,我的图简单直接while循环。/***Dubbo线程池指标**@authoryinjihuan*/@ConfigurationpublicclassDubboThreadMetrics{@AutowiredprivateMeterRegistrymeterRegistry;privatefinalIterableTAG=Collections.singletonList(Tag.of("thread.pool.name","dubboThreadPool"));@PostConstructpublicvoidinit(){newThread(()->{while(true){try{Thread.sleep(1000);}catch(InterruptedExceptione){e.printStackTrace();}DataStoredataStore=ExtensionLoader.getExtensionLoader(DataStore.class).getDefaultExtension();Mapexecutors=dataStore.get(Constants.EXECUTOR_SERVICE_COMPONENT_KEY);for(Map.Entryentry:executors.entrySet()){ExecutorServiceexecutor=(ExecutorService)entry.getValue();if(executorinstanceofThreadPoolExecutor){ThreadPoolExecutortp=(ThreadPoolExecutor)executor;Gauge.builder("dubbo.thread.pool.core.size",tp,ThreadPoolExecutor::getCorePoolSize).description("内核线程数").baseUnit("threads").register(meterRegistry);高ge.builder("dubbo.thread.pool.largest.size",tp,ThreadPoolExecutor::getLargestPoolSize).description("历史最高线程数").baseUnit("threads").register(meterRegistry);Gauge.builder("dubbo.thread.pool.max.size",tp,ThreadPoolExecutor::getMaximumPoolSize).description("最大线程数").baseUnit("threads").register(meterRegistry);Gauge.builder("dubbo.thread.pool.active.size",tp,ThreadPoolExecutor::getActiveCount).description("活跳线程序数").baseUnit("threads").register(meterRegistry);Gauge.builder("dubbo.thread.pool.thread.count",tp,ThreadPoolExecutor::getPoolSize).description("当前线程数").baseUnit("threads").register(meterRegistry);Gauge.builder("dubbo.thread.pool.queue.size",tp,e->e.getQueue().size()).description("队列大小").baseUnit("threads").register(meterRegistry);Gauge.builder("dubbo.thread.pool.taskCount",tp,ThreadPoolExecutor::getTaskCount).description("任务总数").baseUnit("threads").register(meterRegistry);Gauge.builder("dubbo.thread.pool.completedTaskCount",tp,ThreadPoolExecutor::getCompletedTaskCount).description("已完成任务的数量").baseUnit("threads").register(meterRegistry);}}}}).start();}}Metric信息:配置线程池图表新建一个dashboard配置图表,并然后新建一个面板配置指标信息,左侧有指标信息,右侧选择对应的图表格式。需要注意的是,如果有多个服务实例,Metrics端最好根据服务实例显示,指标后面需要加上条件,如下:dubbo_thread_pool_max_size_theads{application="$application",instance=~"$instance"}作者简介:尹继焕,单纯的技术爱好者,?、《Spring Cloud 微服务 入门 实战与进阶》的作者,公众号猩猩世界的创始人。原文链接:http://cxytiandi.com/blog/user/1