turbine是怎么收集指标数据的

我们通过spring cloud图形化dashboard是如何实现指标的收集展示的知道了,图形化的指标是从turbine获取到指标数据的。那么turbine的数据是从哪里来的呢?

1、数据来源

我们通过url:http://localhost:10000/turbine.stream?cluster=default可以获取到指标的json数据。那么指标数据又是从何处获取到的。

答案是:从各个服务的/manage/hystrix.stream端点获取的

2、turbine架构设计

turbine官方的github地址:

https://github.com/Netflix/turbine/wiki

可以找到turbine的架构设计

详细信息参考

https://github.com/Netflix/Turbine/wiki/Design-And-Architecture-(1.x)

说明:turbine启动的时候,会去连接需要监控的主机,建立起监听,每一个实例会有一个监听。当实例监听从各个服务获取到数据的时候,会将数据填充到派发器dispatcher中,由派发器将数据输出到各个客户端。

3、源码阅读

turbine的实现在turbine核心包下

com.netflix.turbine:turbine-core

在该包下,可以找到几个关键的类

InstanceMonitorHandlerQueueTupleTurbineDataDispatcherTurbineStreamServlet

我们启动调试的时候,可以看到

实例的url其实是指向具体需要监控的实例的端点,即

http://sheng:8088/manage/hystrix.stream

查看这个链接我们可以看到

InstanceMonitor启动监听

public void startMonitor() throws Exception {
// This is the only state that we allow startMonitor to proceed in
if (monitorState.get() != State.NotStarted) {
return;
} taskFuture = ThreadPool.submit(new Callable<Void>() { @Override
public Void call() throws Exception { try {
//初始化,连接到具体实例上
init();
monitorState.set(State.Running);
while(monitorState.get() == State.Running) {
//关键代码
doWork();
}
} catch(Throwable t) {
logger.warn("Stopping InstanceMonitor for: " + getStatsInstance().getHostname() + " " + getStatsInstance().getCluster(), t);
} finally {
if (monitorState.get() == State.Running) {
monitorState.set(State.StopRequested);
}
cleanup();
monitorState.set(State.CleanedUp);
}
return null;
}
});
}

    private void init() throws Exception {

        HttpGet httpget = new HttpGet(url);

        HttpResponse response = gatewayHttpClient.getHttpClient().execute(httpget);

        HttpEntity entity = response.getEntity();
InputStream is = entity.getContent();
//初始化一个输入流
reader = new BufferedReader(new InputStreamReader(is)); int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != 200) {
// this is unexpected. We probably have the wrong endpoint. Print the response out for debugging and give up here.
List<String> responseMessage = IOUtils.readLines(reader);
logger.error("Could not initiate connection to host, giving up: " + responseMessage);
throw new MisconfiguredHostException(responseMessage.toString());
}
}

dowork()方法做了什么呢

    private void doWork() throws Exception {

        DataFromSingleInstance instanceData = null;

        //获取实例数据
instanceData = getNextStatsData();
if(instanceData == null) {
return;
} else {
lastEventUpdateTime.set(System.currentTimeMillis());
} List<DataFromSingleInstance> list = new ArrayList<DataFromSingleInstance>();
list.add(instanceData); /* send to all handlers */
//将获取到的数据添加到dispatcher中
boolean continueRunning = dispatcher.pushData(getStatsInstance(), list);
if(!continueRunning) {
logger.info("No more listeners to the host monitor, stopping monitor for: " + host.getHostname() + " " + host.getCluster());
monitorState.set(State.StopRequested);
return;
}
}

getNextStatsData读取数据


那么派发器是什么呢,它的实现查看TurbineDataDispatcher

查看它的pushData方法

发现调用的是tuple.pushData(statsData);tuple其实就像一个管道,查看HandlerQueueTuplepushData方法

    public void pushData(K data) {
if (stopped) {
return;
}
boolean success = queue.writeEvent(data);
if (isCritical()) {
// track stats
if (success) {
counter.increment(Type.EVENT_PROCESSED);
} else {
counter.increment(Type.EVENT_DISCARDED);
}
}
}

看到queue.writeEvent(data)、往队列里写数据

这个队列又是什么呢?

其实就是一个事件队列EventQueue,查看它的写事件方法

  public boolean writeEvent(T event) {
if (count.get() > maxCapacity) { // approx check for capacity
return false;
}
count.incrementAndGet();
queue.add(event);
return true;
}

如果队列中的长度大于maxCapacity,将不会再往队列里填充数据。


当客户端连接上的时候,queue就会被消费。如果客户端没有连接上的时候,queue读出来,经过一系列的操作会写回queue中,直到队列满了就不在写了。

1、当没有客户端连接上的时候

eventHandler经过一些列的处理,数据会被写回到queue中

2、当有客户端连上的时候,假设我们通过浏览器地址栏输入了

http://localhost:10000/turbine.stream?cluster=default

此时

我们看到eventHandler为TurbineStreamingConnection,见下图

handlData()就变成了TurbineStreamingConnection中的方法

    public void handleData(Collection<T> data) {

        if (stopMonitoring) {
// we have been stopped so don't try handling data
return;
}
//将数据写到steamHandler中
writeToStream(data);
}

writeToStream()中有个关键的操作streamHandler.writeData(jsonStringForDataHash)

writeData()方法就可以将数据写到response中

客户端访问http://localhost:10000/turbine.stream?cluster=default的时候,其实就是通过TurbineStreamServlet获取到响应结果的。

turbine是怎么收集指标数据的的更多相关文章

  1. Spring Cloud 入门教程(八): 断路器指标数据监控Hystrix Dashboard 和 Turbine

    1. Hystrix Dashboard (断路器:hystrix 仪表盘)  Hystrix一个很重要的功能是,可以通过HystrixCommand收集相关数据指标. Hystrix Dashboa ...

  2. 运维相关指标数据采集并ES入仓 - 运维笔记

    为了进行数字化IT治理,需要对一些应用进程相关指标进行采集并入库.收集到的应用指标数据最好要进行ES入仓,入到Kafka里面,并通过Kibana可视化展示. 需要进行采集的应用进程相关指标如下: ES ...

  3. 使用 shell 脚本自动获取发版指标数据

    问题背景 大一点的公司都会建立一套规章流程来避免低级错误,例如合入代码前必需经过同行评审:上线前必需提测且通过 QA 验证:全量前必需经过 1%.5%.10%.20%.50% 的灰度过程.尤其是最后一 ...

  4. .NetCore下使用Prometheus实现系统监控和警报 (六)进阶Grafana集成自定义收集指标

    Prometheus中包含了很多收集指标,那么我们怎来在Grafana中来使用呢? 接下来我们还是以之前自定义的来演示如图:我们在Prometheus中已经可以看到这个之前我们自定义的类型了 关于Gr ...

  5. .NetCore下使用Prometheus实现系统监控和警报 (五)进阶自定义收集指标 之 Counter

    Prometheus下面定了四种类型的收集方式,下面我们主要来来说下Counter的使用 Nuget导入Prometheus.AspNetCore包 下面先来看下我的Prometheus配置,这里我没 ...

  6. nGrinder对监控机器收集自定义数据及源码分析

    转载:https://blog.csdn.net/neven7/article/details/50782451 0.背景 性能测试工具nGrinder支持在无需修改源码的情况下,对目标服务器收集自定 ...

  7. Facebook 被指收集用户数据:通过照片和文本

    北京时间5月25日消息,在加利福尼亚州进行的对Facebook泄露用户信息一案中,法院对Facebook提起一项新的诉讼,指控该公司通过App收集了用户及他们朋友的信息. 上周向加利福尼亚州圣马特奥市 ...

  8. tushare获取股票每日重要的基本面指标数据,并存入Elasticsearch

    tushare是一个开放的,免费的金融数据平台,包含沪深股票数据,指数数据,基金数据,期货数据,期权数据,债券数据,外汇数据,港股数据,行业经济数据,宏观经济数据以及新闻快讯等特色数据.其中以沪深股票 ...

  9. .Net最佳实践3:使用性能计数器收集性能数据

    本文值得阅读吗? 本文讨论我们如何使用性能计数器从应用程序收集数据.我们将先了解的基本知识,然后我们将看到一个简单的示例,我们将从中收集一些性能数据. 介绍: - 我的应用程序的性能是最好的,像火箭 ...

随机推荐

  1. 05: MySQLdb 原生SQL语句操作数据库

    1.1 MySQLdb安装与简介 1.MySQLdb 模块的安装(python3中目前这个模块还不可用)参考博客 1. linux: yum install MySQL-python 2. windo ...

  2. 20145334赵文豪《网络对抗》shellcode注入&Return-to-libc攻击深入

    Shellcode注入 shellcode实际是一段代码,但却作为数据发送给受攻击服务器,将代码存储到对方的堆栈中,并将堆栈的返回地址利用缓冲区溢出,覆盖成为指向 shellcode 的地址 下载安装 ...

  3. CreateDirectory 创建文件夹 C\C++

    函数原型: CreateDirectory( LPCTSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes ); 简介: CreateD ...

  4. SQLSERVER中order by ,group by ,having where 的先后顺序

    SELECT [Name]  FROM [LinqToSql].[dbo].[Student]  where name='***' group  by  name    having (name='* ...

  5. 质量管理三个概念:QC、QA和QM,你能分得清吗?

    今天这里谈的QC.QA和QM,不是岗位或职位,而是一种概念或质量管理的不同时期所关注的重点. 1.产品 早期的质量管理(工业化雏形期)侧重于对终产品的检测.测试,即QC(品质控制)时代. 这个时期的质 ...

  6. 深入理解JavaScript的变量作用域

    在学习JavaScript的变量作用域之前,我们应当明确几点: JavaScript的变量作用域是基于其特有的作用域链的. JavaScript没有块级作用域. 函数中声明的变量在整个函数中都有定义. ...

  7. The DELETE statement conflicted with the REFERENCE constraint

    Page是主表,主键是pageid:UserGroupPage表中的PageID字段是Page表里的数据. https://www.codeproject.com/Questions/677277/I ...

  8. 封装TeeChart控件

    public class MyChart { //字段 private TChart tChart; /// <summary> /// 构造函数,默认不是3D效果 /// </su ...

  9. C#创建继承的窗体

    http://blog.csdn.net/chenyujing1234/article/details/7555369 关键技术 基窗体,实质上相当于面向对象编程中提到的基类,而继承窗体则是子类或派生 ...

  10. 【Coursera】Fifth week(3)

    Ethernet 在 PARC(Xerox) 发明. 第一个 Local-Area-Network (LAN 局域网). 把 PCs 连接到 激光打印机上. 在夏威夷大学,被早期的无线网络 Aloha ...