【问题标题】:What is the best way to build own system metric collector agent构建自己的系统指标收集器代理的最佳方法是什么
【发布时间】:2021-12-23 18:42:22
【问题描述】:

我自己有一个想法,为具有各种自定义功能和控件的 linux 系统构建自己的指标收集代理。想知道从 linux 系统连续收集指标的最佳做法是什么。

  1. 对于所需的数据收集时间间隔,是否最好使用带有睡眠的无限 while 循环?或任何其他可用于递归数据收集而不浪费太多系统内存的最佳方法。

  2. 如果我想收集多个指标,如 CPU util、memory util、disk util 等。并行执行所有命令的最佳方法是什么?使用 & 并将其留作后台并收集所有进程 ID 并验证所有进程是否已完成,这是一种好方法吗?或任何其他为此目的的最佳方式?

提前致谢。

【问题讨论】:

  • Sooo,为什么不推出现有的解决方案? Zabbix,nagios? Is it best to 用什么来衡量“最好”?很可能不会,因为sleep 会比需要的睡眠时间多一点。使用特定于操作系统的工具以特定间隔执行任务可能更准确。我的意思是timer_create()。但这取决于什么被认为是“最好的”。 What is the best way 用什么来衡量“最好”?没有“最好”或“更差”,这完全取决于。因此,我认为您的问题过于宽泛。请看How to Ask,我推荐meta.stackoverflow.com/q/260648/9072753
  • 感谢您的回复。 1. 我以 CPU、Mem 等为例来解释我的用例。在实际场景中,收集指标可能会有所不同,这在 Nagios 等现有解决方案上可能不可用。 2. 最佳手段,遵循的最佳方法。这个问题背后的原因是,这是一个在操作系统上无限运行的代理。所以我需要低 CPU 和内存消耗代理来完成我的所有操作。如果 while 循环继续向 ram 添加数据,那么我不推荐使用 while 循环。这就是我所说的最好的意思。降低计算消耗。
  • which may not available on existing solutions like Nagios 都有“自定义指标”或类似的东西。 Best means, the best method to follow 不回答问题。如何衡量“最佳”?如何衡量最好遵循什么?最好的在我看来,不是重新发明轮子。如果您真的需要自定义语义,请使用 zabbix-agent2 源代码并根据需要对其进行修改。如果您只需要自定义指标,我认为滚动自定义解决方案没有任何价值,因为它会很昂贵,而且会占用大量没有价值的工作时间。使用现有的解决方案会更有价值。

标签: linux parallel-processing infinite-loop agent infinite-recursion


【解决方案1】:

较低的计算消耗

使用 C 编程语言,或用汇编语言编写。一般来说,答案是:越低越好,越少越好。我在下面的答案中假设 C 编程语言。

对于所需的数据收集时间间隔,是否最好使用带有睡眠的无限 while 循环?

使用特定于操作系统的界面定期执行操作。 timer_create()。在循环中调用nanosleep() 需要计算时间差才能准确,这需要获取当前时间,这是昂贵的。取决于内核更好。

在中断处理程序中,仅在信号处理程序中设置一个sig_atomic_t 标志。使用pause() 在循环中异步等待事件。

并行执行所有命令的最佳方式是什么?

为了尽量减少“计算消耗”,不要调用fork(),不要创建线程。如果事件是异步的,则使用一个带有一个大循环的线程和poll() 调用等待所有事件。这种方法很快就会产生意大利面条式的代码——要特别注意正确地构建和模块化代码。

open()所有/proc/**/sys/**需要监控的接口,定期lseek它们并在需要发送数据时再次读取。

总的来说,在非常伪代码中:

void timer_callback(int) {
   flag = 1;
}
int main() {
    metrics_read = 0; // keep count of asynchronous reads

    timer_create();
    foreach(metric) {
        int usage = open("/proc/stat", O_NONBLOCK); // for example
    }

    while(1) {
       r = pselect(...);
       if (FD_ISSET(socket_to_send_data)) {
           // take action, in case like socket was closed or smth
       }
       if (FD_ISSET(usage)) {
           parse(usage_buffer); // parse events as they come
           metrics_read++;
       }
       // FD_ISSET etc. for each metric

      if (EINTR && flag) {
          flag = 0;
          foreach(metric) {
              lseek(usage, SEEK_SET, 0)
              read(usage, usage_buffer); // non blocking, each read with custom buffer, to let kernel do the job
          }
       }

       if (metrics_read == ALL_METRICS_CNT) {
           send_metrics(); // also asynchronous on `socket()` `write()` with O_NONBLOCK
           metrics_read = 0;
       }
 }
               
          

不要写任何日志。日志会导致 I/O 操作,这是“计算消耗”。不要输出任何东西。此外,需要对pselect 进行特殊工作,以屏蔽信号以“保证”始终按时正确解析标志。

使用 & 并将其留作后台并收集所有进程 ID 并验证所有进程是否已完成,这是一种好方法吗?

绝对不是——fork() 是一个非常“消耗计算”的函数,生成进程的成本非常高。最好不要留下任何“作为背景”的东西,并在单线程单进程中执行所有内容。

或任何其他为此目的的最佳方式?

较低的“计算消耗”当然是编写一个完成这项工作的内核模块。然后,您可以专门管理内核资源,以实现尽可能低的“计算消耗”,同时保持您的系统与 linux 兼容。

【讨论】:

    猜你喜欢
    • 2020-09-19
    • 1970-01-01
    • 1970-01-01
    • 2010-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多