草庐IT

准召率超80%,网易游戏AIOps异常检测及故障定位优化实践

sw 2023-03-28 原文
根据 Gartner 的最新阐释,智能运维(AIOps)意指整合大数据和机器学习能力,通过松耦合、可扩展方式去提取和分析数据量(volume)、种类(variety)和速度(velocity)这三个维度不断增长的 IT 数据,进而为 IT 运维管理产品提供支撑。AIOps 围绕质量保障、成本管理和效率提升的基本运维场景,逐步构建智能化运维场景。在质量保障方面,保障现网稳定运行细分为异常检测、故障诊断、故障预测、故障自愈等基本场景;在成本管理方面,细分为资源优化,容量规划,性能优化等基本场景;在效率方面,分为智能变更、智能问答,智能决策等基本场景。

一、网易游戏AIOPS落地线路图

2016年开始, 网易游戏在AIOps这条道路上持续探索,力求实现从人工运维到智能化运维的转变。从2016年开始组建智能监控团队,构建智能运维平台,一直到现在,落地了异常检测、预测、关联分析、下钻分析、日志分析、运维机器人、故障定位、故障预警等。除此之外,还有很多其他功能,如火焰图分析、硬件预测、CDN文件发布等,都取得不错的实践效果。

二、异常检测  

异常检测是研究AIOps的必经之路,后续很多场景功能都以异常检测为基础,属于不得不解决的问题。异常检测指通过 AI 算法,自动、实时、准确地从监控数据中发现异常,为后续的诊断、“自愈”提供基础。相比传统阈值配置成本高、误报多、场景覆盖少的问题,异常检测有易配置、准确率高、场景覆盖面广、自动更新等优点。

对于异常检测,其实网上很多文档或者书籍都给出了一些算法或者工具,但在实际运用的过程中,会发现效果往往不是很好,究其原因是这些算法只能有效地针对一些特定的场景、以及需要做很多的优化来适配实际的场景。为了更好地在实际场景中落地,我们对算法做了一些调整优化,并结合业务需求对指标进行划分,达到更好的检测效果。我们将异常检测根据指标类型划分成了三种场景----业务黄金指标(如游戏在线人数)、性能指标(如cpu使用率)、文本数据(如日志),采用不同的检测算法。

1、业务黄金指标

业务黄金指标的特性是周期性强、曲线波动小、指标量级小、准确率和召回率要求高。我们知道有监督模型具有高准召率、高扩展性的优点,因此我们考虑采用有监督模型对业务黄金指标进行异常检测。然而有监督模型需要大量的标注数据,但对异常检测项目很难收集到足够的异常数据。那应该如何去解决和平衡这两者之间的关系呢?我们从样本构建到报警可视化,构建了一整套的检测框架。

1)样本构建

考虑到样本收集困难问题,我们的样本主要来自两个方面——历史KPI数据集和线上用户标注数据。首先,抽样部分KPI数据集,采用简单无监督检测模型如Iforest检测得到异常score,通过不等比例分层抽样筛选出疑似异常样本和正常样本,进行人工标注,并划分成训练集和测试集用户模型训练和测试。功能上线后,收集用户标注数据,用于模型优化。用户标注的数据仅会作用于本项目,避免不同用户异常认知差异导致的错误报警问题。还有一点需要注意,当历史异常数据不足时候,可以通过异常生成的方式生成样本,如加噪声、设计抖动模式等方式。

2)预处理

预处理模块包含曲线分类、缺失标准化处理以及特征计算三个部分。曲线分类采用LSTM+CNN的方式实现,将待检测KPI分成3类(稳定、不稳定、不检测),分类准确率可达到93%+。线性和前值填充的方式进行缺失值处理,并max-min归一化。特征包含统计特征、拟合特征、分类特征、滤波特征、自定义特征等,构建近500维特征。考虑到无效特征问题,需要进行特征选择,再进行建模。  

3)算法模型

模型主要采用常见模型,如RF\XGB\GBDT等,再用LR进行集成,进行检测。

4)可视化

可视化部分包含图文告警、快速标注、异常视图三个模块。通过图文形式进行报警,在报警消息中加上快速标注链接,用户在收到报警后可以快速确认是否有异常发生并标注。

通过有监督模型的方式可达到高准召率的检测效果,线上检测效果可达到90%+,可满足用户的需求。

2、性能指标

有监督检测模型可以很好地对业务黄金指标进行检测,但并不适合性能指标场景。如上面所说,性能指标量级大、指标类型复杂、周期不定等。若依旧考虑采用有监督模型,需要花费巨大的标注成本和训练成本,对于大规模部署的业务很不友好。因此,我们采用无监督模型来检测性能类型指标。

我们按异常类型进行划分,划分成毛刺、漂移、高频、线型趋势四种类型,分别采用不同的检测模型进行检测,用户可以根据自己的需求进行选择报警类型。

  • 毛刺类型:毛刺异常是最常见的一种类型,可以采用差分和SR算法进行检测,都有不错的效果。  
  • 漂移类型:漂移问题,首先需要进行STL周期分解,分解出周期、趋势和残差项。然后采用均值漂移和鲁棒回归算法进行检测。
  • 高频类型:高频是毛刺的一种变种,有时不关心顺时的抖动,但是持续抖动时候就需要关注了。因此,采用的检测算法也会比较类型,可以采用多步差分进行检测。
  • 线性趋势类型:线性趋势主要是为了监控内存泄漏类型问题,可以先进行STL分解,在LR回归和MK检测进行趋势检测。
最后,均需要进行周期抑制的步骤,避免周期性的误报问题。

无监督的检测模型,准召率可达到80%+,基本可达到用户预期。通过图文告警的方式告警,帮助用户快速确认报警的正确性。

3、文本数据

业务的高速发展,对系统稳定性提出了更高的要求,各个系统每天产生大量的日志:

  • 系统有潜在异常,但被淹没在海量日志中,有的项目警量最多可达每日1w+,如何合并告警。
  • 故障出现后,日志报警量级太大,难以定位。
  • 新版本上线,系统行为有变化,却无法感知。
这些问题,归根到底,是日志信息太多、格式多样,不能很好归类。日志智能分析基于大数据和AI算法,提供实时日志智能分类,以及日志指标异常检测等功能。利用模型根据日志文本的相似性进行归类,自动提取对应的日志模版。如下图,可以从两条日志中提取出模板。

目前业界日志分类的算法相对成熟,有很多的算法都可以达到不错的效果。一次分类我们采用drain算法,然后Spell进行二次分类,解决一次分类长度不同日志分在不同模板的问题。

得到日志模板后,可以基于日志模板数量进行异常检测。智能异常检测会对比不同时间段的分类日志数量,利用机器学习模型自动识别突变或者和历史趋势不一致的日志类型,并发出告警信息:

  • 根据历史两天日志分布情况训练模型,学习正常日志波动周期。
  • 从日志整体分布分析,减少单类日志小抖动造成的误报。
  • 自动选取影响分布最大的topN类日志。

与指标异常检测不同,日志异常检测可以检测到代码类型异常,对程序排障有重大帮助。此外,日志分类可以对日志治理也要很大的帮助,新项目/服务上线时候通过审查日志模板,可以根据需求整理、删除无效日志。

三、故障定位

在标准的故障处理流程中,故障定位一般可分为两个阶段:

  • 故障止损前:可以快速获得可用于止损决策的信息,做出相应的止损操作使得服务恢复。
  • 故障止损后:进一步找到导致故障的深层次原因,确定故障根因,将线上环境恢复到正常状态。  
在游戏场景中,随着游戏及系统架构的日渐复杂,运维人员收到的报警信息也变得多种多样,在面对故障时,纷杂的报警信息令运维人员一时难以理清逻辑,甚至顾此失彼,无法在第一时间解决最核心的问题:

  • 游戏架构日渐复杂,出现故障后排查链路比较长。
  • 故障产生后,往往会引发多个报警,但是这些报警比较零散,没有按照一定的规则去分类和可视化。导致排查过程中需要人工先去梳理,和过滤报警。
  • 目前故障定位依赖人工经验,这些经验难以被复用。

1、资源  

资源维度可区分机器、网络渠道、SaaS进行分析给出异常信息。  

1)机器

对最近20min内所有metric进行异常检测,计算异常检测分数。再基于越早发生的异常越有可能是根因、指标异常越严重越可能是根因、机器故障越严重越可能是根因几个准则进行排序,给出topN异常机器。

2)网络/渠道

采用Adtributor算法,按区域、运营商等维度进行下钻分析,给出topN异常维度。

3)saas

目前我们SaaS有比较完善的报警,直接可获取异常结果进行汇总。

2、代码

代码问题直接可通过日志分类和异常检测发现,给出topN异常模板。

3、人为操作

人为部分主要是变更事件,与变更系统联动,关联到故障发生前的变更事件,并异常提醒。

4、历史故障

除了分析机器、代码等问题,还有一个比较有效定位故障根因的方式就是关联历史故障。如果本次故障与历史故障异常表现相似,那么大概率是相同的原因导致,故可以历史故障原因作为本次故障根因的推荐。计算当前故障与历史故障的Tanimoto系数,推荐Tanimoto值最大且超过阈值的topN故障以及其根因。

整体的故障定位流程,检测到故障的发生,基于拓扑资源、代码、人为因素、历史故障这几个角度出发,采用不同的方式进行根因分析。如检测到游戏在线人数下降,出发故障定位流程,检测到机器A 网络连接异常,告警出网络问题,人工进行排查出公网故障导致。

图片

有关准召率超80%,网易游戏AIOps异常检测及故障定位优化实践的更多相关文章

  1. ruby-on-rails - Rails - 乐观锁定总是触发 StaleObjectError 异常 - 2

    我正在学习Rails,并阅读了关于乐观锁的内容。我已将类型为integer的lock_version列添加到我的articles表中。但现在每当我第一次尝试更新记录时,我都会收到StaleObjectError异常。这是我的迁移:classAddLockVersionToArticle当我尝试通过Rails控制台更新文章时:article=Article.first=>#我这样做:article.title="newtitle"article.save我明白了:(0.3ms)begintransaction(0.3ms)UPDATE"articles"SET"title"='dwdwd

  2. ruby - #之间? Cooper 的 *Beginning Ruby* 中的错误或异常 - 2

    在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee

  3. ruby - 在 Ruby 中重新分配常量时抛出异常? - 2

    我早就知道Ruby中的“常量”(即大写的变量名)不是真正常量。与其他编程语言一样,对对象的引用是唯一存储在变量/常量中的东西。(侧边栏:Ruby确实具有“卡住”引用对象不被修改的功能,据我所知,许多其他语言都没有提供这种功能。)所以这是我的问题:当您将一个值重新分配给常量时,您会收到如下警告:>>FOO='bar'=>"bar">>FOO='baz'(irb):2:warning:alreadyinitializedconstantFOO=>"baz"有没有办法强制Ruby抛出异常而不是打印警告?很难弄清楚为什么有时会发生重新分配。 最佳答案

  4. SPI接收数据异常问题总结 - 2

    SPI接收数据左移一位问题目录SPI接收数据左移一位问题一、问题描述二、问题分析三、探究原理四、经验总结最近在工作在学习调试SPI的过程中遇到一个问题——接收数据整体向左移了一位(1bit)。SPI数据收发是数据交换,因此接收数据时从第二个字节开始才是有效数据,也就是数据整体向右移一个字节(1byte)。请教前辈之后也没有得到解决,通过在网上查阅前人经验终于解决问题,所以写一个避坑经验总结。实际背景:MCU与一款芯片使用spi通信,MCU作为主机,芯片作为从机。这款芯片采用的是它规定的六线SPI,多了两根线:RDY和INT,这样从机就可以主动请求主机给主机发送数据了。一、问题描述根据从机芯片手

  5. ruby - 我需要从 facebook 游戏中抓取数据——使用 ruby - 2

    修改(澄清问题)我已经花了几天时间试图弄清楚如何从Facebook游戏中抓取特定信息;但是,我遇到了一堵又一堵砖墙。据我所知,主要问题如下。我可以使用Chrome的检查元素工具手动查找我需要的html-它似乎位于iframe中。但是,当我尝试抓取该iframe时,它​​是空的(属性除外):如果我使用浏览器的“查看页面源代码”工具,这与我看到的输出相同。我不明白为什么我看不到iframe中的数据。答案不是它是由AJAX之后添加的。(我知道这既是因为“查看页面源代码”可以读取Ajax添加的数据,也是因为我有b/c我一直等到我可以看到数据页面之后才抓取它,但它仍然不存在)。发生这种情况是因为

  6. ruby - 如何捕获 ruby​​ 中的所有异常? - 2

    我们如何捕获或/和处理ruby​​中所有未处理的异常?例如,这样做的动机可能是将某种异常记录到不同的文件或发送电子邮件给系统管理。在Java中我们会做Thread.setDefaultUncaughtExceptionHandler(UncaughtExceptionHandlerex);在Node.js中process.on('uncaughtException',function(error){/*code*/});在PHP中register_shutdown_function('errorHandler');functionerrorHandler(){$error=error_

  7. ruby - Sinatra 中的全局救援和日志记录异常 - 2

    如何在出现异常时指定全局救援,如果您将Sinatra用于API或应用程序,您将如何处理日志记录? 最佳答案 404可以在not_found方法的帮助下处理,例如:not_founddo'Sitedoesnotexist.'end500s可以通过调用带有block的错误方法来处理,例如:errordo"Applicationerror.Plstrylater."end错误的详细信息可以通过request.env中的sinatra.error访问,如下所示:errordo'Anerroroccured:'+request.env['si

  8. 多种方法期间的 Ruby 救援异常 - 2

    我构建了一个简单的银行应用程序,它能够执行通常的操作;充值、提现等我的Controller方法执行这些操作并拯救由帐户或其他实体引发的异常。以下是Controller代码中使用的一些方法:defopen(type,with:)account=createtype,(holders.findwith)addaccountinit_yearly_interest_foraccountboundary.renderAccountSuccessMessage.new(account)rescueItemExistError=>messageboundary.rendermessageendde

  9. ruby-on-rails - 使用 Ruby 正确处理 Stripe 错误和异常以实现一次性收费 - 2

    我查看了Stripedocumentationonerrors,但我仍然无法正确处理/重定向这些错误。基本上无论发生什么,我都希望他们返回到edit操作(通过edit_profile_path)并向他们显示一条消息(无论成功与否)。我在edit操作上有一个表单,它可以POST到update操作。使用有效的信用卡可以正常工作(费用在Stripe仪表板中)。我正在使用Stripe.js。classExtrasController5000,#amountincents:currency=>"usd",:card=>token,:description=>current_user.email)

  10. python - Ruby 或 Python 的 3d 游戏引擎? - 2

    关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于StackOverflow来说是偏离主题的,因为它们往往会吸引自以为是的答案和垃圾邮件。相反,describetheproblem以及迄今为止为解决该问题所做的工作。关闭9年前。Improvethisquestion是否有适用于这些的3d游戏引擎?

随机推荐