跳到正文 →

运维团队如何简化繁琐的工作量

我们都知道有一种产品开发模式,叫数据驱动开发,其实对于业务运维,也是需要数据驱动的。那么在DevOps大潮下,业务运维怎么做比较合适呢?本期我们请到了日志易产品总监饶琛琳为我们分享实时数据驱动下的应用运维。

过去一个业务系统,在项目组建立的时候,就已经定好了上线后有多少量,要多少服务器,运维主要负责上线维护,这时候数据其实更多来自经验值;但是现在,运维人员需要随时去横向扩展集群,随时去缩减、扩容虚拟机、容器、云主机、云存储,这个频率越频繁,所谓的『经验值』就越没作用了。

DevOps号称要每天上线、扩展几十上百次,这个频率要求必须有切实的数据,证明需要扩、扩多少、影响多大。

这就是一个要数据驱动的理由。

01/日志作为监控系统的优势对于运维,数据的直接来源就是各种监控系统。比较传统的是系统级的监控系统,开原方案也有很多。但是容器化、微服务化之下,操作系统的指标数据,不足以说明什么,需要从整体来反应服务效果。前几天国外devopsweekly上就流传一篇文章,主题大意是『微服务化最缺一个跟踪监控系统』。

所以要紧的应该是有一个针对业务的,能反应业务状况的监控。但是这些,都意味着需要有比较好的技术掌控力。上tracing需要改代码,改代码,改代码……有些APM可以说hook了底层函数,减少上层业务的代码改动,不过这个掌控力的要求更高了。如果找第三方呢,又会有额外的一些担心,毕竟自己不可见也挺为难的,偏偏这方面的开源项目又出奇的少。所以折中一下,还有一种方式:技术难度没那么高,安全性上又放心的就是老老实实打日志。全面一点的话,可以说从前到后都可以打日志。页面埋点可以出日志,服务器访问肯定有日志,业务逻辑可以出日志,跑业务的PHP-fpm、tomcat、rails,再往后的数据库啊,缓存啊,各种后端集群啊……默认也都是有日志的。

因为日志本身有append的特性,所以打日志对业务应用的IOPS影响也小。应该说开发们应该或多或少都是有这个习惯的,从这里入手,对于业务运维也是最方便。

不过通过日志来获取整个系统的状态,也是有难度的。传统方式下,运维是怎么用日志的?SSH上服务器,然后cat | grep | awk | sort | uniq | less.

因为日志在服务器上存储的时候,一般是按照天去rotate的,如果要排查一个三五分钟的问题,比如早上看下报表,发现『昨晚 23:12 到 23:29 那会儿有个小坑,找找问题吧』,如果预定思路都没有,从几个方向试一下,这个文件就被一遍又一遍的cat全文再grep那几分钟……当然对于比较小的文件有OS的VFS cache可以帮忙——但是如果这个事情放到服务化场景下,要横跨十几台服务器上几十个文件呢?运维一天可能也就够干这一件事情了。

上面这个举例,其中难点,文件大、跨服务器,这都不是最难的。最难的是因为你不知道问题在哪,所以你要尝试各个方向都先找找。这就是定点采样的监控系统、离线分析的Hadoop系统都比较难搞的地方了。

这两种方式都要求你有规划好的逻辑、规则了,然后去编码,固化下来。但是很多业务运维的工作是“我知道有问题,我知道问题原因一定在这堆数据里,但是我现在也不知道在哪。”

所以需要一种可以随时让我们修改规则、实时反馈数据结果的方式,才能真正的简化在服务化场景下的业务运维工作。

02/日志搜索引擎的实践分析前两年我在微博做架构师,最终就选择了通过日志搜索引擎的方式来简化我们团队、乃至我们对口的研发团队的苦逼工作。开源社区对应这个方式,有一系列开源项目,合称叫ELK Stack。比如监控系统,大家都知道时间序列趋势是最重要的。这是防火墙之父说的一条法则。

但是通过日志搜索引擎出来的时间序列效果会更特殊一点。上个图:

运维团队如何简化繁琐的工作量
这些趋势图是从哪来的呢,从微博PHP记录的日志里:

运维团队如何简化繁琐的工作量

诈一看好像我们上个storm实时计算这些数也行啊,为啥用了个没那么有名的东西呢?奥秘在上面截图的顶部那堆小白框里。

我再放大了单独截取一下这些小白框:运维团队如何简化繁琐的工作量这里每个框,都是一个搜索框。搜索框跟下面的图表,是多对多的关系。

那么只需要在某个搜索框里,填一个关键字,或者复杂一点点的语法,比如request_time:>100 AND backend_time:<10,也不是太复杂的语法,一共也就几种。敲下回车,下面对应的图表,立刻就会同步更新结果。

这个结果,是实时的。也就是说,你设置时间是now-1h TO now,那就每次搜索都是反馈到最近的结果。

比如你一个网站,有 2000 个接口,常见的状态码有 6、7 个,客户端平台版本也有 6、7 个,机器上千台(嗯,这既是微博的状态)。如果通过传统预先定义的方式做监控,这就是好几千万个metric了,怎么可能搞得完。而在这个系统里,就是一份日志,随时可以换逻辑看结果。

上面这个例子,还是在时序趋势图的范畴呢。其实做数据分析还会有很多别的可视化方案。下面还是拿PHP说,另一个做运维的时候其实应该很关心的日志,PHP的slowlog是这个样子的。

运维团队如何简化繁琐的工作量

可能很多人其实平常就没把这东西放到监控系统要考虑的范畴里,就是等到业务已经出问题了才上去看,其实slowlog能预知到不少情况的。

当然如果只是说时序趋势统计,那么slowlog你就只关心一下堆栈最底下那个函数就是了。

但是我们有另外一个方式:

运维团队如何简化繁琐的工作量

这个仪表盘上三张图,不多~但是顶上这张就很有趣了~~其实是把整个slowlog的堆栈完全都处理出来,而不单是最底部的:

运维团队如何简化繁琐的工作量

那么我们对每一层的函数,做一个堆叠式的统计,然后做一个千层饼式的可视化,就不单单知道那个函数最慢,还能知道哪个请求链受这个影响最大了。比如这个示例里,就可以看到微博最慢的处理是往推荐平台后端做curl请求。

按说机房这个维度,对于微博这个服务化的场景,影响应该不大。哪个机房这个效果应该都类似才对。但是截图里可以看到有一张饼图,明显杂色比别人多蛮多的。那么我们看看下面的图表,时间趋势图上,也是按机房划分,似乎又看不出来什么异常。再看看主机统计表格。top10里,9个是yhg机房,唯独一个是xd机房的主机,那问题就比较集中了。

现在做一步:点击这个xd机房的主机名。页面变成这样了:

运维团队如何简化繁琐的工作量

整个页面都变成只针对这一台主机的情况了。时序趋势说明这会儿这台机器确实slowlog涨幅很大。(虽然在整个机房里显不出来)

不过这没什么。要点在上面的饼图。这个分布跟之前差别就太大了。鼠标挪上去看看堆栈情况:占比最大的堆栈请求链,变成了链接memcached时,需要的gethostbyname()函数太慢。

这下问题就清楚了。

最后我们另一位同事上去大概花了几分钟,strace跟了一下,定位到dnsmasq的cache容量不够,所以会不定期的域名解析缓存失效,导致服务抖动。

这个问题,其实会影响到整个服务的SLA的。(可能平均时间上反应不出来,但是我们SLA是按百分位时间来定,这种解析超时反应到SLA上就是蛮头疼的总有一些人响应快不了了)

如果按部就班的查问题,时间花费太久,但是通过日志搜索统计,前后加起来不到半个小时。整个一套下来,一点代码没写,当然也有配合devops进程写代码的时候,是另一个场景:app发版,需要特别关注crash。

crash的日志也是汇报上来的。

运维团队如何简化繁琐的工作量

这种大crash在页面上看当然可以。不过我们不仅仅满足于此了。因为这个模式是比较固定的。那么就花了几十行代码,固化一下,把新出现的appversion和新上量的crashlog函数堆栈,直接同步到jira上,由QA去分发到人。

因为ES引擎是RESTful接口,所以这固化逻辑的代码基本就是拼JSON。

说到固化DevOps的逻辑成代码。DevOps文化其实强调一点,其他部门也要参与~我们这个系统出了业务运维和研发,其实包括客服也是在使用了:

运维团队如何简化繁琐的工作量
对业务的最终用户反馈,投诉报错,先由客服人员在系统上过一遍,根据 uid 搜索,一下子就知道这个投诉过了哪些关,触发了哪些报错。客服当然不知道这意味着啥,但是她联系开发或者运维,告诉对方啥问题的时候,就明确多了,这也是一种提高DevOps效率的途径。

03/Q&A
Q1:我们线上是三台elasticsearch,每分钟查询总会碰到一个查询近10s的(即使这个search是之前查过的),一直无解,困扰许久,望解答。(服务器的配置是8核32GB三台,线上数据900GB,在写入数据的时候,会出现以上情况。)明确一下你的查询语句,查询范围是什么。有些条件是es无法缓存的,比如now。只要走search接口就会出现,没有用复杂的查询语句,60秒内查询同一句语句也会出现这个情况,其它50+s都是100毫秒以内返回,就会出现一个search,特别慢。同样一句search,在第一次搜索返回时间正常的情况下,一分钟内连续尝试,也会出现这个长达10s的回应,是什么原因呢?

几种可能:你的索引refresh间隔或者flush频率或者merge频率恰好如此,这几个操作是要短暂占用大量cpu的,建议观察一下当时的vmstats;另一种,你是每分钟请求一个新的范围,第一个到这个范围的需要“帮”后面那些加载vfs cache,所以比后面那些显得长了。建议清空cache单独跑查询验证在相同hits数下的时间。

如果你搜索语句毫无时间因素,因为我不清楚你是kibana还是自己写,那么后一种确实不能成立了

还有一种可能:你的连续是怎么连续的啊,如果异步或者并发,也可能是到search threadpool里等着了……

不是并发,纯人肉测得数据。Search queue也查过,系统指标看上去也不是高负载的样子。

vmstats 1过程中一直没见cpu util%高过?

Vmstat倒没查过,iostat正常,我回去再试试!假设是由于flush或merge引起的短暂cpu高负载,是否意味着只能通过纵向升级,扩大单节点处理能力来解决呢?

那可真不是啥常见问题了。建议在等待期间查看一下hot thread,以及调整es自己的log level,把search的改到trace看看……

横向扩展,导致每次merge的量没那么大,也行……不过这意味着segment数量变多,本身又会导致查询变慢—-要从更多的文件里作初步的map才能有查询结果了。

可以先调整max_segment_size配置测试验证这个思路。

Q2:分布式系统中的log,怎样整合抓取?要显示每次web请求的调用链,你们前后端怎么做的?

日志抓取的开源方案太多啦,都可以单开一个小时吐槽^_^。不过到目前,基本上中间一定都是有kafka的。在微博来说,我们选了一条特别的路:我们用rsyslog,这个很古老但是其实新版本一直在改进的东西。

第一我们团队深度参与了rsyslog源码贡献了,有三个module是我发的;第二,syslog()是系统函数,对开发人员输出日志特别特别特别方便!

前后端调用链,我们也是用request_id做全局唯一的串联的。

这个来自nginx的uid模块生成,后续业务纪录。

其实调用链,原理上还就是tracing系统那套设计,不过很多tracing是采样,而es给了我们全量存取的能力。现在市面上开源的tracing项目,基本都是采样,或者全量但只记指标而不全文。

归类 技术分享