Dubbo监控的实现基本原理就是在服务调用时收集服务调用并发度、服务响应时间,然后以一定频率向监控中心汇报统计数据。
1、源码分析MonitorFilter过滤器
过滤器作用
监控过滤器,向监控中心汇报服务调用数据。
使用场景
搭建监控中心监控Dubbo服务调用。
阻断条件
非阻断过滤器。
注:MonitorFilter会在生产者、消费者两端生效。
1.2 getConcurrent方法详解
主要是获取当前调用服务的调用次数计算器。
代码@1:使用的是ConcurrentMap< String, AtomicInteger >作为缓存容器,其key为:interfaceName + “.” + methodName。
代码@2:如果是第一次调用,则创建AtomicInteger,否则返回原先的计数器。
1.3 invoker方法详解
代码@1:如果url中存在monitor,则设置了监控中心,收集调用信息。
代码@2:获取本次服务调用的上下文环境。
代码@3:服务调用并发次数增加1,(非服务调用总次数,而是当前服务的并发调用)。
代码@4:执行方法之前先记录当前时间,然后调用下一个过滤器,直到真实服务被调用。
代码@5:调用collect方法收集调用信息。
代码@6:如果调用发送RPC异常,则收集错误信息。
代码@7:一次服务调用结束,并发次数减一。
接下来分析一下collect方法。
1.4 invoker方法详解
代码@3:根据监控中心获取监控中心实现类,这是监控中心实现扩展点,默认使用com.alibaba.dubbo.monitor.dubbo.DubboMonitor。
代码@4:如果是消费端,由于Monitor在消费端与服务端都会生效:
localPort :本地端口设置为0;
remoteKey:MonitorService.PROVIDER,表示为服务端。
remoteValue:为invoker.getUrl().getAddress(),其值为(注册中心地址)或服务提供者地址(客户端直连服务端)。
代码@5:如果为服务端:
localPort :为服务端的服务端口号。
remoteKey:MonitorService.CONSUMER,表示远端为服务消费者。
remoteValue:消费者host(ip:port)。
代码@6:获取本次服务调用请求包的字节数,在服务端解码时会在RpcContext中。
代码@7:获取本次服务调用响应包的字节数,在服务端对响应包编码时会写入,具体代码请参考DubboCountCodec类。
代码@8:调用monitor#collect收集调用信息,Monitor默认实现为DubboMonitor。使用的协议为count://localhost:localPort/service/method?application=applicationName&remoteKey=remoteValue&success|failure=1&elapsed=调用开销&concurrent=并发调用次数&input=入参字节数&output=响应字节数&group=服务所属组&version=版本。
2、源码分析DubboMonitor实现原理
Dubbo中默认的Monitor监控实现类为DubboMonitor:
2.2 collect 收集统计信息方法
2.3 send方法
通过monitorService,最终通过monitorInvoker去调用RPC服务向监控中心汇报数据。接下来看一下监控中心的具体实现。
3、Dubbo监控中心实现原理
Dubbo官方提供了简易版本的监控中心,其项目为dubbo-ops:dubbo-monitor-simple。该项目是个spring-boot项目,启动后可以看到后台管理界面。
该项目服务提供者文件如下:
从中可以看出,监控中心服务提供者实现类为SimpleMonitorService,其实现接口为MonitorService。
接下来重点分析SimpleMonitorService监控中心的实现,关注如下两个点:
1、监控数据持久化。
2、监控报表生成逻辑。
核心属性说明:
ScheduledExecutorService scheduledExecutorService:定时调度线程,将监控数据写入饼图的定时任务,固定1个线程。
Thread writeThread:监控数据持久化线程。
BlockingQueue< URL > queue:持久化数据任务阻塞队列。
String statisticsDirectory = “statistics”:数据持久化目录,SimpleMonitorService将数据持久化到磁盘文件。该值指定目录名称。
String chartsDirectory = “charts”:饼图存储目录。
private volatile boolean running = true:持久化数据线程是否处于运行状态。
代码@1:创建有界阻塞队列LinkedBlockingQueue,容量默认为100000个,可通过配置参数dubbo.monitor.queue改变默认值,如果队列中已挤压未被处理,后续监控数据将被默认丢弃。
代码@2:创建持久化监控数据线程,名称为DubboMonitorAsyncWriteLogThread,其使命是从LinkedBlockingQueue中获取监控原始数据,如果队列中没数据则被阻塞,然后写入文件中。
代码@3:开启定时调度任务,已每个5分钟的频率,根据持久化的监控数据,生成饼图。
代码@4:获取数据持久化目录与饼图存放目录。
3.2 SimpleMonitorService#write
3.4.3、 Dubbo简易监控中心使用方法
1、安装Dubbo简易监控中心
从github dubbo仓库中下载dubbo-simple-monitor即可。
2、应用程序如何使用Dubbo监控中心
成功安装完监控中心还只是第一步,为了监控中心能收集服务调用信息,需要在Dubbo服务提、Dubbo消费者供者所在的应用的dubbo配置文件中加上如下内容:
< dubbo:monitor protocol=”registry” />,表示从注册中心发现监控中心的地址,并将服务调用信息提交到监控中心。
服务提供者默认以一分钟的频率(可配置)调用监控中心的dubbo服务,向监控中心上报服务调用信息。监控中心宕机,并不影响消费者,服务提供者的正常工作。
如果要配置其调用频率,可通过如下配置,默认建议保持一分钟的频率,甚至更小,这个频率设置低点,对整个服务器的压力不会增加更大