DUBBO监控,设置接口调用数据的上报周期
DUBBO监控,设置接口调用数据的上报周期
dubbo是目前比较好用的,用来实现soa架构的一个工具,dubbo的用法和好处,我们这里略过,今天我们来讨论跟监控有关的话题。
大家大知道,在确保系统的稳定道路上,系统监控是必不可少的,只有实时监控系统中接口的调用情况,并定期汇总统计数据,才能知道系统是否到了瓶颈,以及是否有接口异常调用情况。
dubbo已有的监控方案
dubbo中自带了dubbo-monitor模块,其作用简单来说就是:
根据配置判断是否启用
MonitorFilter
过滤器
当dubbo的xml配置文件中配置了<dubbo:monitor xxx/>
,比如:<dubbo:monitor protocol="registry" />
或<dubbo:monitor protocol="dubbo" address="dubbo://127.0.0.1:30004/MonitorService" />
等等
根据protocol配置,判断获取
MonitorService
接口方式以及获取接口地址
如果是registry
根据<dubbo:registry xxx />
配置获取,如果是dubbo
直接使用address属性配置的地址
根据protocol配置,判断使用哪个
MonitorFactory
如果是registry
,则根据最后获取到的具体通信协议来决定;
如果是dubbo
,使用默认工厂类:DubboMonitorFactroy。见dubbo默认配置文件:
META-INF/dubbo/internal/com.alibaba.dubbo.monitor.MonitorFactory
dubbo=com.alibaba.dubbo.monitor.dubbo.DubboMonitorFactroy
这里我们可以自定义协议,比如myDubbo
,然后在项目中创建一个文件:
META-INF/dubbo/com.alibaba.dubbo.monitor.MonitorFactory
myDubbo=org.rembau.dubboTest.MyDubboMonitorFactory
这时项目启动时,如果发现协议为myDubbo,会使用MyDubboMonitorFactory
执行相关操作。
问题:这里暴露了监控配置的一个问题,就是我们不能为dubbo协议重新定义一个MonitorFactory
,所以连带的不能重新实现Monitor
。
使用
MonitorFilter
过滤器处理每一个接口调用
如果我们用的dubbo协议来连接MonitorService
服务,则是使用DubboMonitor
实例来处理接口调用数据,该类实现了对调用数据的简单汇总,并每60秒调用MonitorService
服务的collect方法,把数据发送出来。
使用dubbo-monitor-simple接收数据
dubbo-monitor-simple是dubbo提供的简单监控中心,可以用来显示接口暴露,注册情况,也可以看接口的调用明细,调用时间等。
还有其他一些比较好的工具比如Dubbo-Monitor等
针对已有方案的改进
写到这里才是本文的重点,我们绝大部分使用者都是使用dubbo协议进行通信,所以也就是使用DubboMonitor
发送数据,这已经完全够用了。但是DubboMonitor
是每分钟上报一次,并且每个应用中,与之有关的所有接口都会产生一条数据,生产环境中,数据量还是挺大的。如果上报的时间间隔可以设置为10分钟或者30分钟,数据量也会相应减少10倍、30倍,如果我们自己汇聚还需要分布式服务对数据的一致性处理,会把事情变复杂。
查看
DubboMonitor
源码:
DubboMonitor
的构造方法:
this.monitorInterval = (long)monitorInvoker.getUrl().getPositiveParameter("interval", '60000');
this.sendFuture = this.scheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
public void run() {
try {
DubboMonitor.this.send();
} catch (Throwable var2) {
DubboMonitor.logger.error("Unexpected error occur at send statistic, cause: " + var2.getMessage(), var2);
}
}
}, this.monitorInterval, this.monitorInterval, TimeUnit.MILLISECONDS);
其中.getPositiveParameter("interval", '60000')
方法大概意思是,在URL对象实例中找interval参数的值。那URL的参数会从什么地方获取呢?
MonitorConfig
的属性、MonitorConfig
中Map<String, String> parameters
属性的key-value
最终获取的URL是根据MonitorConfig
得来的,查看AbstractInterfaceConfig
代码:
protected URL loadMonitor(URL registryURL) {
if (monitor == null) {
String monitorAddress = ConfigUtils.getProperty("dubbo.monitor.address");
String monitorProtocol = ConfigUtils.getProperty("dubbo.monitor.protocol");
if (monitorAddress != null && monitorAddress.length() > 0
|| monitorProtocol != null && monitorProtocol.length() > 0) {
monitor = new MonitorConfig();
} else {
return null;
}
}
appendProperties(monitor);
Map<String, String> map = new HashMap<String, String>();
map.put(Constants.INTERFACE_KEY, MonitorService.class.getName());
map.put("dubbo", Version.getVersion());
map.put(Constants.TIMESTAMP_KEY, String.valueOf(System.currentTimeMillis()));
if (ConfigUtils.getPid() > 0) {
map.put(Constants.PID_KEY, String.valueOf(ConfigUtils.getPid()));
}
appendParameters(map, monitor);
String address = monitor.getAddress();
String sysaddress = System.getProperty("dubbo.monitor.address");
if (sysaddress != null && sysaddress.length() > 0) {
address = sysaddress;
}
if (ConfigUtils.isNotEmpty(address)) {
if (! map.containsKey(Constants.PROTOCOL_KEY)) {
if (ExtensionLoader.getExtensionLoader(MonitorFactory.class).hasExtension("logstat")) {
map.put(Constants.PROTOCOL_KEY, "logstat");
} else {
map.put(Constants.PROTOCOL_KEY, "dubbo");
}
}
return UrlUtils.parseURL(address, map);
} else if (Constants.REGISTRY_PROTOCOL.equals(monitor.getProtocol()) && registryURL != null) {
return registryURL.setProtocol("dubbo").addParameter(Constants.PROTOCOL_KEY, "registry").addParameterAndEncoded(Constants.REFER_KEY, StringUtils.toQueryString(map));
}
return null;
}
方案1 使用javassist动态重写
MonitorConfig
class
在应用启动时,使用javassist给MonitorConfig
添加interval字段,并设置默认值,DubboMonitor
初始化时会获取到该字段的值,并使用这个值当作发送数据的周期。
如果应用使用了spring框架,则下面代码有关在加载spring配置文件之前执行。如果应用是web应用则处理起来更麻烦,需要重写org.springframework.web.context.ContextLoaderListener
代码如下:
ClassPool pool = ClassPool.getDefault();
try {
CtClass cc = pool.get("com.alibaba.dubbo.config.MonitorConfig");
// 增加属性,这里仅仅是增加属性字段
CtField ctField = new CtField(CtClass.intType, "interval", cc);
ctField.setModifiers(Modifier.PUBLIC);
cc.addField(ctField, "10000");//设置10秒周期
CtMethod ctMethod = new CtMethod(CtClass.intType, "getInterval", null, cc);
ctMethod.setBody("return interval;");
ctMethod.setModifiers(Modifier.PUBLIC);
cc.addMethod(ctMethod);
cc.toClass();
} catch (NotFoundException | CannotCompileException e) {
logger.error("", e);
}
方案2 使用
<dubbo:registry xxx />
配置
分析源码,可以知道,如果配置<dubbo:registry interval="10000" xxx />
,dubbo解析文件时,会把interval="10000"当作一个key-value存入MonitorConfig
中Map<String, String> parameters
DubboBeanDefinitionParser
中parse方法(摘选)
NamedNodeMap attributes = element.getAttributes();
int len = attributes.getLength();
for (int i = 0; i < len; i++) {
Node node = attributes.item(i);
String name = node.getLocalName();
if (! props.contains(name)) {
if (parameters == null) {
parameters = new ManagedMap();
}
String value = node.getNodeValue();
parameters.put(name, new TypedStringValue(value, String.class));
}
}
if (parameters != null) {
beanDefinition.getPropertyValues().addPropertyValue("parameters", parameters);
}
但是有个问题,如果我给<dubbo:registry xxx>
加上interval属性,应用启动时会报错。我们知道原因是dubbo的xsd文件没有放开这个限制,我们只要修改dubbo.xsd文件就可以了,但是dubbo.xsd是在jar包里,所以我们改不了。
我们可以自己写xsd配置,重命名为dubbo-youyue.xsd:
文件头改为:
<xsd:schema xmlns="http://code.alibabatech.com/schema/youyue/dubbo"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:tool="http://www.springframework.org/schema/tool"
targetNamespace="http://code.alibabatech.com/schema/youyue/dubbo">
monitorType节点添加:
<xsd:attribute name="interval" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[ The monitor interval. ]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
然后把dubbo.xml中关联的dubo.xsd改成我们自己写的xsd,如:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
改成
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:dubbo="http://code.alibabatech.com/schema/youyue/dubbo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://code.alibabatech.com/schema/youyue/dubbo
http://code.alibabatech.com/schema/youyue/dubbo/dubbo.xsd">
添加 spring.schemas 文件,用来使用本地文件取代远程文件
http://code.alibabatech.com/schema/youyue/dubbo/dubbo.xsd=META-INF/dubbo-youyue.xsd
添加 spring.handlers 文件,用来标记分析dubbo.xml中<dubbo:xx xx>
节点的分析处理类
至此,配置好<dubbo:registry interval="10000" xxx />
启动应用,可以看到上报周期由60秒变成了10秒。
DUBBO监控,设置接口调用数据的上报周期的更多相关文章
- Dubbo -- 关于 api接口调用不使用强依赖
首先,我们都知道 Dubbo 调用api 需要提供暴露 接口, 消费端才通过 ZK 可以调用 通常我们都会使用 提供 api jar包 的方式 使用 这样既方便又快捷 简单 只需要在spr ...
- webService 客户端接口调用【java】
最近实际项目中使用到了WebService,简单总结下使用方式: 1.拿到接口:http://*******:8080/osms/services/OrderWebService?wsdl 我们可以将 ...
- EasyNVR流媒体服务器网页兼容调试:ie浏览器下的接口调用成功但页面无法显示实时的数据
许多问题很难在开发的过程中就想的面面俱到,都是在实际应用.调试的过程中一一的优化的.由于easynvr的受众越来越多,因此也出现了好多在开发之初并没有留意的一些细节.我这次发现的问题就是给客户远程解决 ...
- 一行代码搞定Dubbo接口调用
本文来自网易云社区 作者:吕彦峰 在工作中我们经常遇到关于接口测试的问题,无论是对于QA同学还是开发同学都会有远程接口调用的需求.针对这种问题我研发了一个工具包,专门用于远程Dubbo调用,下面就让我 ...
- 借助Anyproxy实时监控接口调用次数和流量
监控接口调用次数,是为了测试客户端可能会异常频繁的调用服务端接口,出现性能问题. AnyProxy是一个开放式的HTTP代理服务器. github: https://github.com/alibab ...
- java接口对接——别人调用我们接口获取数据
java接口对接——别人调用我们接口获取数据,我们需要在我们系统中开发几个接口,给对方接口规范文档,包括访问我们的接口地址,以及入参名称和格式,还有我们的返回的状态的情况, 接口代码: package ...
- page分页问题,根据页码获取对应页面的数据,接口调用
添加一个log.js文件,进行接口调用. import axios from '@/libs/api.request' const MODULE_URL = '/log'; export const ...
- SAP调用RestfulApi接口POST数据到外部系统
作者:明光烁亮 出处:http://www.cnblogs.com/hezhongxun/ 微信号:HEme922 欢迎加好友一起交流SAP! 视频资料共享. 本文版权归作者和博客园共有,欢迎转载,但 ...
- Vue单页面中进行业务数据的上报
为什么要在标题里加上一个业务数据的上报呢,因为在咱们前端项目中,可上报的数据维度太多,比如还有性能数据.页面错误数据.console捕获等.这里我们只讲解业务数据的埋点. 业务数据的上报主要分为: 各 ...
随机推荐
- MongoDB下载及安装
MongoDB的下载及安装 1.下载: MongoDB的官网是:http://www.mongodb.org/ 2.安装: 方案一:(程序启动方式) 1> 创建文件夹:MongoDB 在D ...
- LinkedBlockingQueue源码解析(1)
此文已由作者赵计刚授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 1.对于LinkedBlockingQueue需要掌握以下几点 创建 入队(添加元素) 出队(删除元素) 2 ...
- CentOS 7 - 最小化安装以及引发的问题!
一,操作系统和虚拟机 操作系统:CentOS 7 官方网站:https://www.centos.org 下载地址:https://www.centos.org/download/ 下载版本分三个:D ...
- 《Python绝技:运用Python成为顶级黑客》 用Python分析网络流量
1.IP流量将何去何从?——用Python回答: 使用PyGeoIP关联IP地址和物理地址: 需要下载安装pygeoip,可以pip install pygeoip 或者到Github上下载安装htt ...
- 服务器 apache配置https,http强制跳转https(搭建http与https共存)
公司linux服务器上的nginx的已经改成https了,现在还剩下一个windows云服务器没配置. 环境 windows wampserver2.5 64位 1.腾讯云申请的ssl 包含三个文件: ...
- 算法逆向6——RSA识别
本文原创作者:i春秋作家——icq5f7a075d 1. 算法介绍 RSA算法是一种用数论构造的.基于大合数因子分解困难性的公开密钥密码.由于RSA密码既可用于加密,又可用于数字签名,安全.易懂,因此 ...
- express form/ajax 后端获取前端数据
-------------------2017/12/02补充:缺了一个重要条件... var bodyParser = require('body-parser');var app = expres ...
- [Swift实际操作]七、常见概念-(2)点CGPoint和变形CGAffineTransform的使用
本文将为你演示点对象CGPoint的使用,其中CG表示来自CoreGraphic(核心图形)这个跨平台框架 首先导入需要使用的两个框架第一个框架表示界面工具框架第二个框架表示核心绘图和动画框架 imp ...
- HttpClient和HttpURLConnection的使用和区别(上)
转自:点击打开链接 相信很多Android开发者碰到涉及到Http协议的需求时,都和我一样在犹豫是使用HttpClient还是使用HttpURLConnection呢.我在网上也搜索了很多文章,来分析 ...
- pythonweb框架Flask学习笔记04-模板继承
# -*- coding:utf-8 -*- from flask import render_template,Flask app=Flask(__name__) @app.route('/hell ...