首页 存档 技术 查看内容

如何快速实现一个基于 Nginx 网站的监控场景

2018-3-30 13:00 |来自: 互联网 411 0

摘要: 小明所在的一家小型互联网创业公司采用通用的分布式 Nginx App 架构为用户提供电商数据统计的 webservice 服务。最近,小明的老板给小明布置了一个任务,希望把应用服务监控起来,以提高应用运行质量。-- 中间件小哥 ...

小明所在的一家小型互联网创业公司采用通用的分布式 Nginx App 架构为用户提供电商数据统计的 webservice 服务。最近,小明的老板给小明布置了一个任务,希望把应用服务监控起来,以提高应用运行质量。
-- 中间件小哥


本文导航
转载自 | https://yq.aliyun.com/articles/72273
 作者 | 中间件小哥


一切从应用服务监控说起

小明所在的一家小型互联网创业公司一直将应用运行在阿里云上。该应用采用通用的分布式 Nginx App 架构为用户提供电商数据统计的 webservice 服务。应用运行至今除偶发各类 Bug,性能问题以外,情况还算良好。

最近,小明的老板给小明布置了一个任务,希望把应用服务监控起来,以提高应用运行质量。老板的需求有三点:

  1. 先以应用服务监控为抓手,能

  • 实时统计应用各类服务的调用次数

  • 基于 a,实时统计各类服务各类返回值的次数,如 200,404,500,等。

  • 基于 b,如果某类返回值调用超限,进行实时报警。

  • 提供历史查询功能,能返回任意时段任意服务任意返回值调用次数统计。

  • 以后未来公司各类定制的业务监控能快速扩展到该系统上,如各接口响应统计时间,用户特征统计等。

  • “方案尽量多快好省,而且搭建的监控平台最好就在阿里云上,数据不要外放在第三方云上,主要是为了公网流量成本和以后大数据分析作准备”,老板最后提到。

    技术选项

    小明接到任务以后开始着手进行技术选型。摆在他面前貌似可行的有三个选择,传统 OLAP 式处理方式,搜索引擎,以及实时计算方式。

    在调研现状和众多技术后,他发现,

    1. 由于公司业务规模不小,白天峰段的平均 QPS 已经上百,而且业务还在快速增长,因此将每秒上百次调用信息每次直接存放到数据库中再实时查询肯定不合适,成本太高且不适合扩展。

    2. 阿里云提供搜索引擎服务,错误统计功能基本能满足老板需求。但是不确定因素有两个。一方面搜索引擎价格存储成本偏高(搜索引擎需要引入索引存储),而且各类聚合查询如接口响应时间统计等查询响应时间不太好保证,另一方面考虑到实时报警还需要编写 API 不停进行各类调用的错误次数的轮询,性能和成本都不太确定。

    3. 基于实时计算的架构,可以将线上所有日志通过服务,返回值错误类型,和时间等维度在内存中进行实时的聚合计算,然后再持久化到存储中。一方面实时计算效率高,聚合后的结果大小会比原始数据大大减少,因此持久化成本低,实时能保证;另一方面还可以在内存中实时校验报警策略,让报警的性能开销足够小。

    综上考虑,基于实时计算的架构看来最能满足当前公司的需求。决定了以后,小明开始思考进一步架构设计。

    架构设计

    决定了基于实时计算的技术以后,小明开始进行架构设计。通过参考各类技术网站,他发现要架构一个靠谱的网站监控方案,需要的组件以下缺一不可。

    • 数据通道:负责将数据从 Nginx 拉取出来,传送到搜索引擎。数据通道同时肩负数据堆积和数据重算的任务。

    • 计算引擎:基于 Nginx 服务,错误码,时间的维度的聚合实时计算逻辑需要基于选定的引擎进行编写。计算引擎最好能同时负责一些报警的逻辑。

    • 存储:存放最终 Nginx 监控结果的地方。考虑到监控结果虽然表结构简单,但是各种维度查询比较多,最好是类似于 OLAP 的存储类型。

    • 展示门户:针对所有 Nginx 监控结果作各类维度的快速分析和展示。

    好在针对前三个组件,阿里云提供了一些现成的产品组件,小明不需要自己手动一个个去搭建,因此入门门槛还不算高。

    • 数据通道这块,小明在阿里云上选取了一款类似于 Kafka 的数据通道,在支持性能和消息堆积等特性的同时,在数据接入上提供了一定的简便性。

    • 计算引擎上,小明为了简易入手,选择了一款基于 spark-stream 计算引擎组件,可以上面直接写 SQL 语句进行实时计算编排而不需要自己写流式计算程序。

    • 存储方面,由于没有太强事物需求,而且在容量上要求较高,小明选择了一款类似 Hbase 的云上存储产品。

    • 展示门户方面,没有直接对应产品。小明挠了挠头,决定还是只能自己突击一下前段编程技术,基于开源展示框架来编写一个简单的查询门户。

    跟老板申请了预算以后,小明开始陆续开通各类产品进行开发测试。预计一个月完成任务,

    漫漫开发路程

    开通流程很简单。花了半天不到,kafka、storm、hbase 的租户集群到手。可惜常言道,开发项目 80% 的时间花费在最终 20% 的坑上。项目过了一个月,但是功能尚未完成 70%。小明在自己的技术博客上默默的记录下以下踩过的坑。

    集成故障排查成本

    由于需要集成的组件包括数据通道,实时计算层,后台存储,并在代码中集成推送数据逻辑以及报警查询逻辑。每个环节稍有出错将造成整个链路阻塞,调试成本显得非常高。

    日志清洗

    开发期间为了获取到相关应用为了调整对于日志的推送逻辑,需要在每台 Nginx 日志内容变更以后再在每个服务端变更 API 的推送逻辑,变更过程冗长且容易出错。

    持久化表设计

    除了要针对监控项做出适合的表库设计,并尽量避免索引热点以外,还需要考虑当数据结果由于实时计算层不稳定重复计算时如何保证数据库写入幂等性,这对表结构设计是一个不小的挑战。

    延迟数据合并

    如果由于应用原因导致 Nginx 日志数据被延迟发送,如何保证比如晚到 1 个小时的数据能被实时计算引擎准确计算并将结果合并到之前的结果。

    报警

    针对所有结果需要设置定时任务每分钟对数据进行遍历查询。比如针对任何返回 500 调用错误超过 5% 占比的服务,需要所有服务进行多次的调用结果进行遍历查询。如何不遗漏所有的服务错误检查的同时保证高效率查询也是个不小的挑战。

    报警准确性

    有的时候由于日志延迟,上一分钟部分服务器正常日志还没采集全,导致局部 500 调用错误的服务暂时超过 5%,类似错误是否需要报警?如果报警,有可能误报,不报警的话,可能漏报,怎么处理呢?

    如何统计 UV、TopN

    以 UV 为例。如果要跨任意时间度查询 UV,则常规手段还需要在数据库中存入每单位时间(如分钟级别)的全量 IP 访问信息。这对于存储利用率来讲显然是无法接受的。有没有更优化的方案?

    针对错误场景的诊断方法

    针对各类返回值 500 的调用错误,业务方提出希望出现 500 错误时能根据时间和调用服务维度查询到详细的调用入参和其他详情,其场景和日志搜索类似。对于类似新加入需求,貌似通过实时聚合计算和存储不能直接办到。需要对日志另辟蹊径另行处理。

    以上问题还不包括前段展示的各类问题。

    掐指一算,两个月晃眼过了。项目还没弄完一半,小明有点急了。

    另外一种新的思路

    小明晚上约了自己的同门师兄老丹搓串。就着小酒,小明把自己最近的烦心事从头到尾跟老丹说了一遍。

    老丹听了一拍大腿:“小明,你这就奥特了。其实在阿里云上有一款云产品, 叫做业务实时监控,简称 ARMS,基本上你遇到的这些问题,在 ARMS 上已经提供了一站式的解决方案,你只需要快速接入即可。”。

    “噢,是么?我们业务的监控逻辑很多都是基于 Nginx 日志定制,ARMS 具备接入 Nginx 日志的能力,并允许让我定制业务监控能力么?“小明问道。
    “当然。ARMS 上不仅提供监控 Nginx 的任务模板,本身自带报警和监控报表,同时还全程开放定制能力。如果你要增加自己的业务监控逻辑,或者删除或修改自己不要的通用监控逻辑,直接在其平台上定制即可。”老丹答道。

    “听起来不错。最终结果除了报表和报警外,公司的下游业务平台也能用么?”

    “可以的,ARMS 提供 API, 下游系统直接对接数据 API 即可,跟你在云上直接读数据库没什么本质区别。”

    “听起来不错,看来我的项目有救了,我赶紧去看看。”

    实现一个基于 Nginx 的网站监控场景

    1. ARMS 的 Nginx 监控方案概述和准备

    目前在监控领域上比较流行的数据处理方法有很多种,例如,搜索引擎,时间序列数据库,实时计算,甚至是大数据离线计算,等。

    ARMS 采用的是实时计算 列式存储。这种方案的优势是数据实时性高,而且对于固定的数据查询接口查询效率非常块。在 Nginx 的监控方案中,其架构概要如下所示, 蓝色部分为 ARMS 所集成的 Nginx 监控开箱即用的黑盒。

    由于 ARMS 的分析是针对 Nginx 的 access.log 日志,因此对 Nginx 日志有一定要求,需要用户在 nginx.config 中配置出打印内容,包括:“$upstream_response_time” “$request_time” 等代表请求消耗时间的日志信息。如下例:

    1. log_format main '$remote_addr - $remote_user [$time_local] $status '

    2. '"$request" $body_bytes_sent "$http_referer" '

    3. '"$http_user_agent" "$http_x_forwarded_for"'

    4. '"$upstream_response_time" "$request_time" "$ user_cookie_id"' ;

    这样的话,打印出的日志,大致如下表所示。

    1. 58.211.119.29 144288 - [16/Mar/2017:21:47:07 0800] "POST http://arms.console.aliyun.com/api/query.json?action=DataQueryAction

    声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

    路过

    雷人

    握手

    鲜花

    鸡蛋

    相关分类

    返回顶部