Dubbo原理解析-监控

Dubbo发布代码中,自带了一个简易的监控中心实现。对于一般的小业务这个监控中心应该能够满足需求,对于那些大业务量的大公司一般都会有自己的监控中心,更加丰富的功能如常用的报警短信通知等等。这章讲解分析使得读者能够了解一般的监控中心实现,也使得有自己接入监控中心需求的大概知道如何集成自己的监控中心实现。下面我们就以dubbo自带的监控中心开始讲解。

 

监控中心

1.  监控中心启动,我们先看下dubbo的属性文件

dubbo.container=log4j,spring,registry,jetty

dubbo.application.name=simple-monitor

dubbo.application.owner=

dubbo.registry.address=zookeeper://127.0.0.1:2181

dubbo.protocol.port=7070

dubbo.jetty.port=8080

dubbo.jetty.directory=${user.home}/monitor

dubbo.charts.directory=${dubbo.jetty.directory}/charts

dubbo.statistics.directory=${user.home}/monitor/statistics

 

相比于provider, consumer的启动注册中心多了registry, jetty容器启动

bubuko.com,布布扣

它们都是基于dubbo的spi扩展机制的。

SpringContainer容器启动就是加载classpath*:META-INF/spring/ *.xml spring的配置文件

<beanid="monitorService"class="com.alibaba.dubbo.monitor.simple.SimpleMonitorService">

       <propertyname="statisticsDirectory"value="${dubbo.statistics.directory}"/>

       <propertyname="chartsDirectory"value="${dubbo.charts.directory}"/>

</bean>

<dubbo:applicationname="${dubbo.application.name}"owner="${dubbo.application.owner}"/>

<dubbo:registryaddress="${dubbo.registry.address}"/>

<dubbo:protocolname="dubbo"port="${dubbo.protocol.port}"/>

<dubbo:serviceinterface="com.alibaba.dubbo.monitor.MonitorService"ref="monitorService"delay="-1"/>

<dubbo:referenceid="registryService"interface="com.alibaba.dubbo.registry.RegistryService"/>

 

2. SimpleMonitorService

监控中心配置了监控服务的实现SimpleMonitorService, 并且作为一个普通的dubbo服务暴露到注册中心,供服务的提供者和服务的消费方调用,将服务提供者和服务的消费方的调用数据保存到监控中心。

监控服务的接口定义

public interface MonitorService {

    /**

     * 监控数据采集.

     * 1. 支持调用次数统计:count://host/interface?application=foo&method=foo&provider=10.20.153.11:20880&success=12&failure=2&elapsed=135423423

     * 1.1host,application,interface,group,version,method记录监控来源主机,应用,接口,方法信息。

     * 1.2 如果是消费者发送的数据,加上provider地址参数,反之,加上来源consumer地址参数。

     * 1.3 success,faulure,elapsed 记录距上次采集,调用的成功次数,失败次数,成功调用总耗时,平均时间将用总耗时除以成功次数。

     *

     * @paramstatistics

     */

    void collect(URLstatistics);

 

    /**

     * 监控数据查询

     * 1. 支持按天查询:count://host/interface?application=foo&method=foo&side=provider&view=chart&date=2012-07-03

     * 1.1host,application,interface,group,version,method查询主机,应用,接口,方法的匹配条件,缺失的条件的表示全部,host0.0.0.0表示全部。

     * 1.2 side=consumer,provider 查询由调用的哪一端采集的数据,缺省为都查询。

     * 1.3 缺省为view=summary,返回全天汇总信息,支持view=chart表示返回全天趋势图表图片的URL地址,可以进接嵌入其它系统的页面上展示。

     * 1.4 date=2012-07-03指定查询数据的日期,缺省为当天。

     *

     * @param query

     * @returnstatistics

     */

    List<URL> lookup(URL query);

}

 

注: lookup方面可能在开源过程中依赖了阿里的什么系统,并没有具体的实现,如果使用着需要此功能则需要根据接口定义自己实现

 

MonitorService的dubbo默认实现SimpleMonitorService

Collect方法被远程调用后将数据url(传过来的url包含监控需要的数据)保存到一个阻塞队列中BlockingQueue<URL>

启动定时任务将统计日志记录到本地,

String filename =${user.home}/monitor/statistics

                        + "/" + day

                        + "/" +statistics.getServiceInterface()

                        + "/" +statistics.getParameter(METHOD)

                        + "/" + consumer

                        + "/" + provider

                        + "/" + type + "." + key

这是文件在本地存储的格式

bubuko.com,布布扣

文件内容如图保存时间方法消费耗时

bubuko.com,布布扣

 

3. 起定时任务利用JFreeeChart绘制图表,保存路径

${user.home}\monitor\charts\date\interfaceName\methodName

bubuko.com,布布扣

 bubuko.com,布布扣

 

 

产生监控数据

注册中心暴露了MonitorService服务,它是被谁调用的呢,监控中心的数据是从哪里来呢,下面我们看下服务提供方与服务的消费方式如何介入监控中心的。

在服务的提供方跟消费方的dubbo配置加入如下配置

通过注册中心<dubbo:monitor protocol="registry" />

或者直连  <dubbo:monitor address="127.0.0.1:7070" />

bubuko.com,布布扣

在构建服务的调用链的时候有如上基于监控的扩展,下面我们就来看下这个类

@Activate(group = {Constants.PROVIDER, Constants.CONSUMER})

//此过滤器在服务的提供方,服务的消费方应用中被激活,也就是起作用

public class MonitorFilter implements Filter {

private MonitorFactory monitorFactory;

    public Result invoke(Invoker<?>invoker, Invocation invocation) throws RpcException {

    if(invoker.getUrl().hasParameter(Constants.MONITOR_KEY)) {

         //有注监控中心处理

1.  获取invoker的调用上下文

2.  记录起始时间戳

3.  并发计数加一

try {

4.  调用调用链的下一步

5.  采集调用信息

} finally {

6.  并发计数减一

}

    } else {

         //没有配置监控中心,直接往下调用

         return invoker.inovke(invocation);

   }

}

 

上面第5点信息采集

1. 计算调用耗时

2. 获取并发数

3. 获取服务名称

4. 获取方法名

5. 判断是服务消费方监控还是服务提供方监控

6. 由工厂类monitorFactory.getMonitor(监控url),获取DubboMonitor对象,

构建调用监控中心服务的的Url, url中包括了监控中心所需的监控信息

monitor.collect(newURL(Constants.COUNT_PROTOCOL,

                  NetUtils.getLocalHost(),localPort,

                  service + "/" +method,

                  MonitorService.APPLICATION, application,

                   MonitorService.INTERFACE,service,

                   MonitorService.METHOD,method,

                   remoteKey, remoteValue,

                   error ?MonitorService.FAILURE : MonitorService.SUCCESS, "1",

                   MonitorService.ELAPSED,String.valueOf(elapsed),

                   MonitorService.CONCURRENT,String.valueOf(concurrent),

                   Constants.INPUT_KEY, input,

                  Constants.OUTPUT_KEY, output));

 

DubboMonitor是调用监控中心的服务的封装,之所以没有直接调监控中心而是通过DubboMonitor调用,是因为监控是附加功能,不应该影响主链路更不应该损害主链路的新能,DubboMonitor采集到数据后通过任务定时调用监控中心服务将数据提交到监控中心。

 

RegistryContainer

监控中心refer引用了注册中心暴露的RegistryService服务,主要是被下面的RegistryContainer使用的。

 

RegistryContainer主要是到注册中心收集服务,分组,版本信息,并注册回调当注册中心数据发生变化的时候更新到监控中心

下面看下RegistryContainer的start方法流程:

1. 通过SpringContainer获取前面初始化的RegistryService, 得到其实是对注册中心的一个远程代理服务

2. 构建订阅注册中心数据的URL,看可以看出下面的url是订阅服务提供者和服务消费者的所有服务

subscribeUrl = newURL(Constants.ADMIN_PROTOCOL, NetUtils.getLocalHost(), 0,"",

                Constants.INTERFACE_KEY,Constants.ANY_VALUE,//所有服务

                Constants.GROUP_KEY,Constants.ANY_VALUE,//所有分组

                Constants.VERSION_KEY, Constants.ANY_VALUE,//所有版本

                Constants.CLASSIFIER_KEY,Constants.ANY_VALUE,//所有分类

Constants.CATEGORY_KEY,Constants.PROVIDERS_CATEGORY + ","  + Constants.CONSUMERS_CATEGORY,//服务的提供者和服务的消费者

                 Constants.CHECK_KEY,String.valueOf(false));//不检查

3.  调注册中心服务registry.subscirbe(subscribeUrl,listener)订阅所有数据, NotifyListener在监控中心暴露为回调服务,由注册中心回调

回调接口NotifyListener实现的功能主要是按服务提供者和服务的消费者分类,收集服务名称,服务的url,服务提供方或者消费方的系统相关信息。 同时提供了一系列方法供注册中心调用查询。

 

JettyContainer

监控中心将采集到的信息通过内置jetty来展现给用户,这里为了不依赖与jsp, velocity,freemarker等一些编写web应用的技术,采用在servlet中将html,css,js打印出来

JettyContainer的start方法启动了内置的jettyweb容器

将监控中心访问的本地文件目录设置到ResourceFilter中,并设置这个filter的访问映射到jetty中   , ResourceFilter主要是读取本地保存的JFreeChart绘制的图片到浏览器中去。

将监控中心的前置控制器PageServlet, 以及这个servlet的访问映射配置到jetty中。之所以叫PageServet为前置控制器,就像其他的mvc框架一样用来分发具体的业务类

 

PageServet的init初始化方法在web容器启动的时候加载所有的页面处理器PageHandler, 用来根据不同的请求生成不同的页面,前面说过这里页面html都是通过java代码打印出来的。

PageServet的init方法加载所有PageHandler时会判断PageHandler上是否有@Menu注解,将有注解的PageHandler加入集合,以被HomePageHandl er用来生成主页以及各个页面的uri

PageServet的doGet, doPost接收浏览器请求,请求以xx.hml形式,xx就是PageHandler扩展的key,找到对应的PageHandler绘制对应的页面返回给浏览器。

 

 

@Menu(name = "Home",desc = "Home page.", order = Integer.MIN_VALUE)

//有注解 namedesc属性都是在页面中展示给用户看的

public class HomePageHandlerimplements PageHandler {

    public Page handle(URL url) {

        List<List<String>> rows =new ArrayList<List<String>>();

        for (PageHandler handler :PageServlet.getInstance().getMenus()) {

            String uri =ExtensionLoader.getExtensionLoader(PageHandler.class).getExtensionName(handler); //这个uri其实就是PageHandler扩展配置的key页面中用它来请求选择具体的handler绘制     //出具体的page

            Menu menu =handler.getClass().getAnnotation(Menu.class);

            List<String> row = newArrayList<String>();

            row.add("<ahref=\"" + uri + ".html\">" + menu.name() +"</a>");

            row.add(menu.desc());

            rows.add(row);

        }

        return new Page("Home","Menus",  new String[]{"Menu Name", "Menu Desc"}, rows);  //一个Page实体就是一个页面,这里包含所有主要HomePage的页面内容

    }

}

 

PageHandler的在com.alibaba.dubbo.container.page.PageHandler文件中的扩展配置

index=com.alibaba.dubbo.container.page.pages.HomePageHandler

providers=com.alibaba.dubbo.monitor.simple.pages.ProvidersPageHandler

consumers=com.alibaba.dubbo.monitor.simple.pages.ConsumersPageHandler

。。。。

下面截图看下dubbo大概提供了哪些扩展

bubuko.com,布布扣

 下面截几张图看看监控中心的页面。

bubuko.com,布布扣

bubuko.com,布布扣

bubuko.com,布布扣

bubuko.com,布布扣


转载于:https://www.cnblogs.com/duyinqiang/p/5696319.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/257123.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

学习笔记(04):Python网络编程并发编程-什么是socket

立即学习:https://edu.csdn.net/course/play/24458/296233?utm_sourceblogtoedu 1.什么是网络编程&#xff1f; 答&#xff1a;网络编程也叫做socket编程即套接字编程&#xff0c;基于遵循socket套接字的规定进行的编程 2.什么是socket&#xff1f; 答&#xff1a;socket就是…

JeeSite 4.0 说说前端的那些事

2019独角兽企业重金招聘Python工程师标准>>> 引言 一个不得不说的话题&#xff0c;经过近几年的发展&#xff0c;Web前端开发已经不是一个新有的岗位了&#xff0c;前端技术发展非常迅速&#xff0c;技术更新换代也很快&#xff0c;对于前端工程师来说是一个很大的挑…

程序包com.sun.istack.internal不存在

添加一下依赖 <!-- https://mvnrepository.com/artifact/com.sun.xml.bind/jaxb-impl --><dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId> <version>2.2.11</version></dependency&…

iOS微博项目(七)发微博和定位

class a导入class b&#xff0c;class b导入class a 会出现错误 如果keyboard不显示&#xff0c;应该是hardware-》connect选择了 1. 发微博UI 2.定位 一直不回调&#xff0c;后来发现是ios8后方法更新了&#xff1a;http://blog.devzeng.com/blog/ios8-corelocation-framework…

设计模式之UML类图

在学设计模式的过程中经常碰到各式各样的UML类图。那些眼花缭乱的符号有什么含义呢&#xff1f; 类图含义 类图中的关系 从网上找来一张图作为实例 依赖关系&#xff1a;比如动物依赖氧气和水&#xff0c;这里如学生要依赖自行车。用虚线箭头表示。关联关系&#xff1a;学生和身…

tomcat启动报:No Spring WebApplicationInitializer types detected on classpath

2019独角兽企业重金招聘Python工程师标准>>> 对于maven项目&#xff0c;tomcat启动不加载spring配置文件&#xff0c;是因为找不到web.xml文件 右键项目properties 选择 Deployment Assembly 编辑 Web Deployment Assembly&#xff0c;注意主要是红色线框中的路径 …

Linux-正则表达式学习(精)

正则表达式30分钟入门教程 来园子之前写的一篇正则表达式教程&#xff0c;部分翻译自codeproject的The 30 Minute Regex Tutorial。 由于评论里有过长的URL,所以本页排版比较混乱,推荐你到原处查看,看完了如果有问题,再到这里来提出. 一些要说的话&#xff1a; 如果你没有正则表…

Flume sink=avro rpc connection error

要求 conf 文件 a1.sourcesr1 a1.sinksk1 a1.channelsc1a1.sources.r1.typeavro a1.sources.r1.bindmaster a1.sources.r1.port9999a1.sinks.k1.typeavro a1.sinks.k1.hostnameslave1 a1.sinks.k1.port7777a1.channels.c1.typememory a1.channels.c1.capacity1000 a1.channels.…

【腾许Bugly干货分享】“HTTPS”安全在哪里?

背景 最近基于兴趣学学习了下 HTTPS 相关的知识&#xff0c;在此记录下学习心得。 在上网获取信息的过程中&#xff0c;我们接触最多的信息加密传输方式也莫过于 HTTPS 了。每当访问一个站点&#xff0c;浏览器的地址栏中出现绿色图标时&#xff0c;意味着该站点支持 HTTPS 信息…

CCNP精粹系列之十八--路由映射实战二,博主推荐文章

路由映射实战二 本篇博文和上一篇是紧密结合的&#xff0c;只是在上个试验的基础上作了改动&#xff0c;达到其他的试验效果。试验二&#xff1a;在R1上增加一个网段&#xff0c;并发布路由。这里采用三种方法。 如下是第一种&#xff0c;是在试验一的基础上直接增加一个网段&a…

【JUC】JDK1.8源码分析之ConcurrentLinkedQueue(五)

一、前言 接着前面的分析&#xff0c;接下来分析ConcurrentLinkedQueue&#xff0c;ConcurerntLinkedQueue一个基于链接节点的无界线程安全队列。此队列按照 FIFO&#xff08;先进先出&#xff09;原则对元素进行排序。队列的头部是队列中时间最长的元素。队列的尾部 是队列中时…

学习笔记(10):Python网络编程并发编程-粘包现象

立即学习:https://edu.csdn.net/course/play/24458/296240?utm_sourceblogtoedu粘包现象&#xff1a;服务器接收到客户端的命令后&#xff0c;进行执行得到结果后&#xff0c;再发送回给客户端&#xff0c;在这个过程中如果服务器返回的结果的字节数会大于客户端所接收最大字节…

学习笔记(11):Python网络编程并发编程-粘包底层原理分析

立即学习:https://edu.csdn.net/course/play/24458/296241?utm_sourceblogtoedu1.send和recv底层分析 1&#xff09;不管是recv还是send都不是直接接收对方数据或者发送给对方数据&#xff0c;而是对自己的操作系统内存进行操作&#xff1b; 2&#xff09;客户端与服务端并不是…

VMware内存回收与分配机质

VMware内存回收与分配机质 整理了下学习过的东西&#xff0c;为了防止以后忘记。^_^VMware内存回收按照内存回收先后顺充&#xff0c;依次为&#xff1a;1.TPS 透明页共享2.Ballooning 气球回收3.Compressiong 内存压缩4.Swapping 内存交换网上对这个的解释也挺多&#xff…

关于for循环中的变量int i 如果跳出了这个for循环后,i的值是继续保留还是被释放掉了

#include<iostream> using namespace std;int main() {char a[10]; //定义一个一维数组用来存放字符串int i,j; //定义变量cout<<"请输入字符&#xff1a;“;for(i0;i<10;i) //接收用户的输入{ ci…

C#多态

C#多态 多态性&#xff08;C# 编程指南&#xff09;转自MSDN通过继承&#xff0c;一个类可以用作多种类型&#xff1a;可以用作它自己的类型、任何基类型&#xff0c;或者在实现接口时用作任何接口类型。这称为多态性。C# 中的每种类型都是多态的。类型可用作它们自己的类型或用…

C#项目中常用到的设计模式

C#项目中常用到的设计模式 1. 引言 一个项目的通常都是从Demo开始&#xff0c;不断为项目添加新的功能以及重构&#xff0c;也许刚开始的时候代码显得非常凌乱&#xff0c;毫无设计可言。但是随着项目的迭代&#xff0c;往往需要将很多相同功能的代码抽取出来&#xff0c;这也是…

分布式数据库 HBase

原文地址&#xff1a;http://www.oschina.net/p/hbase/ HBase 概念 HBase – Hadoop Database&#xff0c;是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统&#xff0c;利用HBase技术可在廉价PC Server上搭建起大规模结构化存储集群。 HBase是Google Bigtable的开源实…

学习笔记(15):Python网络编程并发编程-进程理论

立即学习:https://edu.csdn.net/course/play/24458/296423?utm_sourceblogtoedu 1.进程&#xff1a;正在运行的一个过程或者一个任务&#xff1b; 2.进程与程序的区别&#xff1a;程序是一堆代码&#xff0c;程序运行起来就是进程了&#xff0c;一个程序运行两次&#xff0c;算…

【翻译】Designing Websites for iPhone X

让网站适配 iphone X 英文原文地址&#xff1a;https://webkit.org/blog/7929/...本文原文地址&#xff1a;https://github.com/cnsnake11/... The section below about safe area insets was updated on Oct 31, 2017 to reflect changes in the iOS 11.2 beta. 以下关于safe …