日志链路健康检查总结

系统环境

  1. 淘宝主站
  2. 阿里云
  3. 共享区

整个日志系统是跨机房,跨region搭建的(底层依赖阿里云,对外的开放服务则搭建在淘宝主站),不同的region之间网络不通(除开放的公网地址),所以存在logService这样具有代理性质的服务组件.

跨网的数据传输会有比较大的延时,这点可以从jstorm的优化看出来

系统角色

  1. workstation:对外提供服务的界面
  2. logAgent:VM上的日志采集进程,也是日志链路的起点
  3. logService:跨Region提供日志服务的代理
  4. jstorm:实时计算处理集群,按一定规则将所有的日志进行封包,保证日志的局部有序不丢失,同时将处理好的日志写入SLS
  5. ONS:提供消息服务,暂存未处理的日志和实时日志
  6. SLS:提供查询日志服务

    设计

本监控项共覆盖四条日志链路,包括应用查询日志,应用实时日志,访问查询日志,访问实时日志,主要完成的功能是检查日志链路的源端尾端会不会存在日志丢包,方便日后日志问题的定位.

业务逻辑

  1. 部署一个WEB应用(以下称为目标应用)在容器中,监控项定时向WEB应用暴露出的URL发送HTTP请求.

    • /print,负责打印指定数量的日志.这部分产生的日志属于应用日志,通过我们自己实现的LogAppender将日志信息写入容器所在vm.
    • /acess, 一个空白URL,没有实际操作,接入层的Nginx记录URL请求,并产生访问日志.
  2. 在监控项中,采集日志链路终端的数据,检查是否丢失日志

    • 通过SLS提供的接口检查是不是所有的日志都被成功持久化
    • 通过jaeLogService提过的代理服务,取到ONS中的实时日志,检查是不是所有的日志都能被成功写入.

模块设计

遵循现有监控项的设计,总体业务逻辑分为三部分:Collector,Processor,Strategy.数据以MonitorItem对象的形式在三部分组成的流水线中流动.典型的链式程序设计.

Collector

监控数据的产生起点,根据业务要求从不同的地方收集监控数据,将达到报警要求的数据封装成MonitorItem交给下一级.

Processor

Collector产生的报警项中按业务要求写入对应的报警信息,然后传递给下一级

Strategy

Processor传递过来的报警项存入DB

纵观三个过程,Collector是最核心的部分,它决定了监控的数据收集策略,判断是否达到报警阈值,封装报警数据.它也是和外部系统打交道最多的模块.

顺便说一下,项目组依赖的外部系统真的非常多,尤其是对阿里云的依赖.整个容器建立在ACE的VM上(这也是大部分监控数据的来源),KV缓存使用OCS,日志的持久化存储使用SLS,利用ONS消息服务提供实时日志服务,利用alimonitor完成监控报警(报警通知到手机,邮件,旺旺等)

遇到的问题

  1. 最开始写代码的时候只要求覆盖一条日志链路,没有考虑扩展性,导致后来添加日志链路的时候进行了代码重构.
  2. 实时日志查询丢包问题.
    • 实时日志是经Jstorm封包(所有容器日志和访问日志)处理后,存入ONS,供LogService拉取,并对workstation提供服务.关键在LogService的日志拉取策略,第一次拉取是从队尾(ONS可以简单视为队列模型)向前追溯10个日志包,以此作为实时日志在队列中的的起始偏移量.日志拉取后,偏移量增加并存入OCS
    • 问题出在我的日志采集策略和起始偏移量的向前追溯.
      • 采集策略:目标应用产生日志->采集实时日志->等待日志写入SLS->采集查询日志
      • 向前追溯:很可能由于日志量过大,导致一部分包含目标应用相关日志的包写入ONS后,大量的包紧随其后,仅仅向前追溯10个包,不能保证起始偏移量在所有目标日志包之前.所以会出现实时日志丢失
    • 改变采集策略
      • 线上的实时日志应用场景一般是这样:用户需要查看实时日志定位问题->打开实时日志(logService将起始偏移量定位好)->用户进行某些产生日志的操作->日志封包进入ONS队尾(这时可以保证偏移量一定在所有目标日志包之前)->拉取实时日志
      • 因此,采集策略改为:打开实时日志采集开关(先定位起始偏移量)->产生目标日志->等待日志写入SLS->采集查询日志
  3. 二套环境自动同步主干代码,导致同样的操作会执行两次,干扰线上日志正常采集.主要原因还是没有将产生日志这些关键性操作设计成幂等操作.以后要多注意.
  4. 沟通与协作.依赖的外部系统多,架构复杂,必然需要经常和其他部门和师兄沟通.难免会出现诸多问题.以后要勇于礼貌且合理地向外寻求协助

感悟

  1. 熟悉了整个日志链路和大致的处理过程
  2. 以后设计程序的时候先尽量明确完整的需求,充分考虑扩展的问题,面向抽象去设计,并多注意模块的高内聚,低耦合.
  3. 合理地处理异常.工程代码一定要保证稳定可靠.要注意不能出现异常导致程序crash的情况.
    • 能处理的异常一定要处理,不能处理的向上抛出
    • 结合日志帮助错误定位
    • 注意RuntimeException也要捕获

感谢师兄们耐心的帮助.:)