最近有做一个Prometheus metrics代理的一个小项目,暂称为prom-proxy,目的是为了解析特定的指标(如容器、traefik、istio等指标),然后在原始指标中加入应用ID(当然还有其他指标操作,暂且不表)。经过简单的本地验证,就发布到联调环境,跑了几个礼拜一切正常,以为相安无事。但自以为没事不代表真的没事。

昨天突然老环境和新上prom-proxy的环境都出现了数据丢失的情况,如下图:

prom-proxy有一个自服务指标request_total,经观察发现,该指标增长极慢,因而一开始怀疑是发送端的问题(这是一个误区,后面会讲为何要增加缓存功能)。

进一步排查,发现上游发送端(使用的是victoriaMetrics的vmagent组件)出现了如下错误,说明是prom-proxy消费的数据跟不上vmagent产生的数据:

2022-03-24T09:55:49.945Z        warn    VictoriaMetrics/app/vmagent/remotewrite/client.go:277   couldn't send a block with size 370113 bytes to "1:secret-url": Post "xxxx": context deadline exceeded (Client.Timeout exceeded while awaiting headers); re-sending the block in 16.000 seconds

出现这种问题,首先想到的是增加并发处理功能。当前的并发处理数为8(即后台的goroutine数目),考虑到线上宿主机的core有30+,因此直接将并发处理数拉到30。经验证发现毫无改善。

另外想到的一种方式是缓存,如使用kafka或使用golang自带的缓存chan。但使用缓存也有问题,如果下游消费能力一直跟不上,缓存中将会产生大量积压的数据,且Prometheus监控指标具有时效性,积压过久的数据,可用性并不高又浪费存储空间。

下面是使用了缓存chan的例子,s.reqChan的初始大小设置为5000,并使用cacheTotal指标观察缓存的变更。这种方式下,数据接收和处理变为了异步(但并不完全异步)。

上面一开始有讲到使用request_total查看上游的请求是个误区,是因为请求统计和请求处理是同步的,因此如果请求没有处理完,就无法接受下一个请求,request_total也就无法增加。

func (s *Server) injectLabels(w http.ResponseWriter, r *http.Request) {
data, _ := DecodeWriteRequest(r.Body)
s.reqChan <- data
cacheTotal.Inc()
w.WriteHeader(http.StatusNoContent)
} func (s *Server) Start() {
go func() {
for data := range s.reqChan {
cacheTotal.Dec()
processor := s.pool.GetWorkRequest()
go func() {
processor.JobChan <- data
res := <-processor.RetChan
if 0 != len(res.errStr) {
log.Errorf("err msg:%s,err.code:%d", res.errStr, res.statusCode)
return
}
}()
}
}()
}

上线后观察发现cacheTotal的统计增加很快,说明之前就是因为处理能力不足导致request_total统计慢。

至此似乎陷入了一个死胡同。多goroutine和缓存都是不可取的。

回顾一下,prom-proxy中处理了cadvisor、kube-state-metrics、istio和traefik的指标,同时在处理的时候做了自监控,统计了各个类型的指标。例如:

prom-proxy_metrics_total{kind="container"} 1.0396728e+07
prom-proxy_metrics_total{kind="istio"} 620414
prom-proxy_metrics_total{kind="total"} 2.6840415e+07

cacheTotal迅猛增加的同时,发现request_total增长极慢(表示已处理的请求),且istio类型的指标处理速率很慢,,而container类型的指标处理速度则非常快。这是一个疑点

vmagent的一个请求中可能包含上千个指标,可能会混合各类指标,如容器指标、网关指标、中间件指标等等。

通过排查istio指标处理的相关代码,发现有三处可以优化:

  • 更精确地匹配需要处理的指标:之前是通过前缀通配符匹配的,经过精确匹配之后,相比之前处理的指标数下降了一半。
  • 代码中有重复写入指标的bug:这一处IO操作耗时极大
  • 将写入指标操作放到独立的goroutine pool中,独立于标签处理

经过上述优化,上线后发现缓存为0,性能达标!

一开始在开发完prom-proxy之后也做了简单的benchmark测试,但考虑到是在办公网验证的,网速本来就慢,因此注释掉了写入指标的代码,初步验证性能还算可以就结束了,没想到埋了一个深坑。

所以所有功能都需要覆盖验证,未验证的功能点都有可能是坑!

总结

  • 服务中必须增加必要的自监控指标:对于高频率请求的服务,增加请求缓存机制,即便不能削峰填谷,也可以作为一个监控指标(通过Prometheus metric暴露的),用于观察是否有请求积压;此外由于很多线上环境并不能直接到宿主机进行操作,像获取火焰图之类的方式往往不可行,此时指标就可以作为一个参考模型。
  • 进行多维度度、全面的benchmark:代码性能分为计算型和IO型。前者是算法问题,后者则涉及的问题比较多,如网络问题、并发不足的问题、使用了阻塞IO等。在进行benchmark的时候可以将其分开验证,即注释掉可能耗时的IO操作,首先验证计算型的性能,在计算型性能达标时启用IO操作,进一步做全面的benchmark验证。

记一次Prometheus代理性能优化问题的更多相关文章

  1. web性能优化——代理(nginx)

    简介 一个很好的原则是调优时每次只个性一个配置.如果对配置的个性不能提高性能的话,改回默认值 优化必须要通过性能测试.不能意淫,需要前后对比,真实说明问题. 场景 优化nginx. 确保每次请求控制一 ...

  2. 性能测试——记XX银行保全项目性能问题分析优化

    记XX银行保全项目性能问题分析优化 数据库问题也许是大部分性能问题的关注点,但是JAVA应用与数据库交互的关节,JDBC 就像是我们人体的上半身跟下半身的腰椎,支持上半身,协调下半身运动的重要支撑点. ...

  3. Nginx正向代理、反向代理、负载均衡及性能优化

    一.Nginx是什么 Nginx是一款高性能的 HTTP 和反向代理服务器,由俄罗斯人Igor Sysoev(伊戈尔·赛索耶夫)为俄罗斯网站Rambler.ru开发的,在Rambler.ru网站平稳的 ...

  4. 安全开发运维必备,如何进行Nginx代理Web服务器性能优化与安全加固配置,看这篇指南就够了

    本章目录 1.引言 1.1 目的 1.2 目标范围 1.3 读者对象 2.参考说明 2.1 帮助参考 2.2 参数说明 3.3 模块说明 3.服务优化 3.1 系统内核 3.2 编译优化 3.3 性能 ...

  5. 记一次mysql性能优化过程

    摘要: 所谓mysql的优化,三分是配置的优化,七分是sql语句的优化,通过一些案例分析,希望给大家在工作中带来一些思路 由于配置是运行过那么长时间,很稳定,基本上不考虑,所以本次主要是sql的优化, ...

  6. 记我的一次 Java 服务性能优化

    背景 前段时间我们的服务遇到了性能瓶颈,由于前期需求太急没有注意这方面的优化,到了要还技术债的时候就非常痛苦了. 在很低的 QPS 压力下服务器 load 就能达到 10-20,CPU 使用率 60% ...

  7. 记一次线上 OOM 和性能优化

    大家好,我是鸭血粉丝(大家会亲切的喊我 「阿粉」),是一位喜欢吃鸭血粉丝的程序员,回想起之前线上出现 OOM 的场景,毕竟当时是第一次遇到这么 紧脏 的大事,要好好记录下来. 1 事情回顾 在某次周五 ...

  8. SQL Server 性能优化详解

    故事开篇:你和你的团队经过不懈努力,终于使网站成功上线,刚开始时,注册用户较少,网站性能表现不错,但随着注册用户的增多,访问速度开始变慢,一些用户开始发来邮件表示抗议,事情变得越来越糟,为了留住用户, ...

  9. Yahoo关于性能优化的N条规则

    本来这是个老生常谈的问题,上周自成又分享了一些性能优化的建议,我这里再做一个全面的Tips整理,谨作为查阅型的文档,不妥之处,还请指正: 一. Yahoo的规则条例: 谨记:80%-90%的终端响应时 ...

随机推荐

  1. 四路4 GSPS@ 12 bit,四路12 GSPS@16 位4T4R 射频芯片AD9988

    一.产品概述 AD9988 是一款高度集成的套件,是北京太速最新研发的,具有四个 16 位.12 GSPS 最大采样率.RF 数模转换器 (DAC) 内核,以及四个 12 位.4 GSPS 速率.RF ...

  2. linux可以这样玩 之 杂乱无章的随笔(不定期更新)

    文章目录 快速重命名 vim的进化 vim高亮当前行 vim列编辑 vim块编辑 vim行编辑 vim 中替换内容 vim保留当前已经编辑的内容,切换到其他用户继续编辑 修改服务的进程限制 CentO ...

  3. 使用并发 ssh 连接来提升捞日志脚本执行效率

    问题背景 公司有个简单粗暴的日志服务,它部署在多台机器实例上,收集的日志记录在每台机器本地硬盘,写一个小时自动切换日志文件,硬盘空间写满了自动回卷,大约可以保存两三天的历史数据.为什么说它粗暴呢?原来 ...

  4. TCP三次握手原理

    本文主要讲述的是 1.TCP协议三次握手原理,以及为什么要三次握手,两次握手带来的不利后果. 2.TCP协议四次挥手原理,为什么要四次挥手. TCP协议三次握手原理: 首先,给张图片,建立TCP三次握 ...

  5. 『无为则无心』Python面向对象 — 54、重写和super()函数

    目录 1.重写 2.super()函数 方式一 方式二 __mro__内置类属性说明 1.重写 在子类中如果有和父类同名的方法,则通过子类实例去调用该方法时,会调用子类中的该方法而不是父类的方法,这个 ...

  6. 前端防抖,double click 克星

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  7. close-on-exec 相关的一个 bug

    close-on-exec 相关的一个 bug 测试一个用 V4L2 拍照的程序时,发现程序单独运行很正常,但在多进程环境下运行时就会出现问题,具体表现为执行 open 系统调用打开 /dev/vid ...

  8. 2021年都要过去啦,你还在用Excel做数据可视化效果吗?

    2021年都要过去啦,你还在用Excel做数据可视化效果吗?古语有云,"工欲善其事,必先利其器",没有专业的工具,前期准备的再好也是白搭.现在运用数据可视化工具于经营活动中的企业是 ...

  9. WPF 开发,优化 AvalonEdit 显示单行超长文本的性能。

    路遥工具箱内置了一个名为"JSON 格式化"的功能.通过该功能可以将 JSON 字符串进行美化和简化(设置缩进和取消缩进). 该功能上线后收到很多客户的反馈:大部分经由网络传输的J ...

  10. 【Windows 操作系统】Windows 进程的内核对象句柄表

    总结: 1.句柄就是进程句柄表中的索引.2.句柄是对进程范围内一个内核对象地址的引用,一个进程的句柄传给另一个进程是无效的.一个内核对象可用有多个句柄.Windows之所以要设立句柄,根本上源于内存管 ...