函数计算+日志服务 -- Serverless监控指标聚合新玩法

简介: 背景本文旨在介绍通过阿里云函数计算(FC)结合日志服务 (Log Service)简单方便地搭建一套Serverless监控系统。日志服务的一个典型使用场景是将监控指标数据通过日志(json/csv 格式)的方式上传到日志服务(例如每个请求一条日志),借助日志服务强大易用的功能做索引,查询分析,制作面板功能和设置报警规则,可以花费很小的代价就能建立起监控大盘和报警系统。

背景

本文旨在介绍通过阿里云函数计算(FC)结合日志服务 (Log Service)简单方便地搭建一套Serverless监控系统。日志服务的一个典型使用场景是将监控指标数据通过日志(json/csv 格式)的方式上传到日志服务(例如每个请求一条日志),借助日志服务强大易用的功能做索引,查询分析,制作面板功能和设置报警规则,可以花费很小的代价就能建立起监控大盘和报警系统。然而随着业务增长,当日调日志条数超过几亿甚至更多,实时聚合超过一个月的原始数据(如大盘显示过去30天的P99延迟变化)显然不再现实。一个可能的解法是在服务端做本地聚合,减少日志聚合的数量,然而这样的做法会丢失掉原始日志中详细的信息,不便于日后单请求问题的调查,并不完美。既然问题的根源在于长时间query聚合数据量过大,那么自然可以基于日志服务做定时的pre-aggregation。我们抽象出如下图所示的指标聚合系统,本文将介绍如何使用FC实现Aggretor借助Log Service的查询分析能力实现Serverless的海量指标聚合系统。

metrics_agg_fc_store

系统架构

下面展示了一个非常简单的Serverless指标聚合系统的架构,仅需要实现以下模块:

  1. FC定时触发器 (Time Trigger): 负责定时调用聚合函数
  2. Aggregator FC 函数: 负责向 Log Service 发起SQL聚合query (GetLogs API)
  3. 原始数据 Logstore (Raw) : 负责存储原始数据的Log Service logstore, 数据量大
  4. 聚合数据 Logstore (Agg) : 负责存储聚合后数据的Log Service logstore, 数据量很小

metrics_agg_fc_0.jpg

定时触发器会将triggerTime 通过函数event传入, 函数将这个时间相对的前1-2分钟作为聚合开始时间,1分钟为粒度,向日志服务发起类似下面的SQL聚合query。日志服务将 O(N)的原始数据在聚合后变为O(1)的数据返回给函数,函数再将聚合数据存回Logstore(Agg).

为了避免函数逻辑出现异常,导致某段时间聚合失败,也可以采用下图的架构,不依赖triggerTime, 将完成过的聚合时间利用表格存储持久化,作为下一次聚合的开始时间:

metrics_agg_fc_no_store

配置准备

  1. 假设原始日志logstore已经存在,如果没有则需要创建, 该示例命名为 “metrics-raw”
  2. 创建一个新的logstore, 该示例命名为 “metrics-agg”
  3. 将两个logstore的索引以及查询分析字段配置好

metrics_agg_logstore_raw

metrics_agg_logstore_agg

编写函数

创建函数, 这里用python2.7 runtime 编写函数,Log Service Python SDK内置于FC python2.7 runtime, 无需额外打包。函数会向Log Service发起下面的query,将原始数据聚合出请求成功数,错误数,平均, P99, P99.9 延迟。

select (__time__ - __time__ %60) as t, avg(latency) as latencyAvg, approx_percentile(latency, 0.99) as latencyP99, approx_percentile(latency, 0.999) as latencyP99dot9, count_if(status >= 200 and status < 300) as successes, count_if(status >= 400 and status < 500) as clientErrors, count_if(status >= 500) as serverErrors group by t order by t limit 3000
import logging
import time
from datetime import datetime
import os
from aliyun.log import *
import json

def handler(event, context):
  evt = json.loads(event)
  trigger_time = evt['triggerTime']
  dt=datetime.strptime(trigger_time, "%Y-%m-%dT%H:%M:%SZ")
  starttime_unix = int(time.mktime(dt.timetuple()))

  logger = logging.getLogger()
  logger.info(evt)
  endpoint = 'https://cn-shanghai.log.aliyuncs.com'
  creds = context.credentials
  access_key_id = creds.access_key_id
  secret_key = creds.access_key_secret
  security_token = creds.security_token
  
  # Replace with your own log project and logstores
  project = 'metrics-project'
  logstore_raw = 'metrics-raw'
  logstore_agg = 'metrics-agg'

  client = LogClient(endpoint, access_key_id, secret_key, securityToken=security_token)
  topic = ""
  source = ""

  topic = ""
  query = "*|select (__time__ - __time__ %60) as t, avg(latency) as latencyAvg, approx_percentile(latency, 0.99) as latencyP99, approx_percentile(latency, 0.999) as latencyP99dot9, count_if(status >= 200 and status < 300) as successes, count_if(status >= 400 and status < 500) as clientErrors, count_if(status >= 500) as serverErrors group by t order by t limit 3000"
  
  # Query time range between trigger_timer - 120s and trigger_timer - 60s
  from_time = starttime_unix - 120
  to_time = starttime_unix - 60
  logger.info("From " + str(from_time) + ", to " + str(to_time))

  # Retry if get logs response is not complete
  res = None
  for retry_time in range(0, 3):
    # Make query to Log Service
    req4 = GetLogsRequest(project=project, logstore=logstore_raw, fromTime=from_time, toTime=to_time, topic=topic, query=query)
    resp = client.get_logs(req4)
    logitems = []
    if resp is not None and resp.is_completed():
      for log in resp.get_logs():
        logitem = LogItem()
        logitem.set_time(int(time.time()))
        logcontents = log.get_contents()
        contents = []
        for key in logcontents:
          print(key)
          print(logcontents[key])
          contents.append((key, logcontents[key]))
          logitem.set_contents(contents)
          logitems.append(logitem)

        if len(logitems) == 0:
          print("No more logitems to put, breaking")
          break

        # Put aggregated logs into the "agg" logstore
        req2 = PutLogsRequest(project, logstore_agg, topic, source, logitems)
        res2 = client.put_logs(req2)
        break

  return str(len(logitems)) + " log items were put into " + logstore_agg

注:service role需要有Log Service相应logstore的权限

配置定时触发器

为Aggregator函数配置定时触发器,可根据需求选择触发频率或规则:

metrics_agg_time_trigger

效果

每分钟函数触发都会借助Log Service 做1分钟数据量的聚合,即使每天有1000亿条(百万TPS)数据,每分钟也只需要聚合7千万条原始数据,Log Service 对于亿条日志都可以在秒级别完成。

metrics_agg_agg_results

在聚合Logstore中数据很少,可以轻松的查询几个月的聚合数据,使对业务长期发展的监控和分析变成可能。FC的函数有

metrics_agg_dashboard

总结

这篇文章用不到100行python代码,两个Log Service logstore,不用一台server, 实现了一套简单轻量却可以覆盖大多数监控,BI需求的指标的预聚合系统,解决了ad-hoc query 基于海量原始数量无法完成或快速返回的痛点。这套系统也享受Serverless天生带来的优势:

  1. 按需付费: 函数每分钟触发一次,由于聚合任务由日志服务承担,函数执行时间基本在秒级别,这样的频率几乎不用付费(函数计算自带的每月100万次免费调用)。
  2. 无运维: 好处无需多述
  3. 附加价值: Log Service自带的面板功能,报警功能都可以用在聚合后的指标上,使这些数据变得actionable

希望借此文投石引路,由开发者发现更多Serverless在监控领域的新玩法。

相关实践学习
【玩转ComfyUI】基于函数计算一键部署AI生图平台ComfyUI
本次实验将带大家通过使用阿里云产品函数计算FC,快速使用ComfyUI实现更高质量的图像生成。
从 0 入门函数计算
在函数计算的架构中,开发者只需要编写业务代码,并监控业务运行情况就可以了。这将开发者从繁重的运维工作中解放出来,将精力投入到更有意义的开发任务上。
目录
相关文章
|
9月前
|
Prometheus 监控 Cloud Native
基于docker搭建监控系统&日志收集
Prometheus 是一款由 SoundCloud 开发的开源监控报警系统及时序数据库(TSDB),支持多维数据模型和灵活查询语言,适用于大规模集群监控。它通过 HTTP 拉取数据,支持服务发现、多种图表展示(如 Grafana),并可结合 Loki 实现日志聚合。本文介绍其架构、部署及与 Docker 集成的监控方案。
852 122
基于docker搭建监控系统&日志收集
|
9月前
|
Prometheus 监控 Java
日志收集和Spring 微服务监控的最佳实践
在微服务架构中,日志记录与监控对系统稳定性、问题排查和性能优化至关重要。本文介绍了在 Spring 微服务中实现高效日志记录与监控的最佳实践,涵盖日志级别选择、结构化日志、集中记录、服务ID跟踪、上下文信息添加、日志轮转,以及使用 Spring Boot Actuator、Micrometer、Prometheus、Grafana、ELK 堆栈等工具进行监控与可视化。通过这些方法,可提升系统的可观测性与运维效率。
817 1
日志收集和Spring 微服务监控的最佳实践
|
9月前
|
存储 缓存 监控
用 C++ 红黑树给公司电脑监控软件的日志快速排序的方法
本文介绍基于C++红黑树算法实现公司监控电脑软件的日志高效管理,利用其自平衡特性提升日志排序、检索与动态更新效率,并结合实际场景提出优化方向,增强系统性能与稳定性。
243 4
|
监控 测试技术 Go
告别传统Log追踪!GOAT如何用HTTP接口重塑代码监控
本文介绍了GOAT(Golang Application Tracing)工具的使用方法,通过一个Echo问答服务实例,详细展示了代码埋点与追踪技术的应用。内容涵盖初始化配置、自动埋点、手动调整埋点、数据监控及清理埋点等核心功能。GOAT适用于灰度发布、功能验证、性能分析、Bug排查和代码重构等场景,助力Go项目质量保障与平稳发布。工具以轻量高效的特点,为开发团队提供数据支持,优化决策流程。
905 90
|
消息中间件 运维 监控
智能运维,由你定义:SAE自定义日志与监控解决方案
通过引入 Sidecar 容器的技术,SAE 为用户提供了更强大的自定义日志与监控解决方案,帮助用户轻松实现日志采集、监控指标收集等功能。未来,SAE 将会支持 istio 多租场景,帮助用户更高效地部署和管理服务网格。
721 51
|
数据采集 运维 监控
数据采集监控与告警:错误重试、日志分析与自动化运维
本文探讨了数据采集技术从“简单采集”到自动化运维的演进。传统方式因反爬策略和网络波动常导致数据丢失,而引入错误重试、日志分析与自动化告警机制可显著提升系统稳定性与时效性。正方强调健全监控体系的重要性,反方则担忧复杂化带来的成本与安全风险。未来,结合AI与大数据技术,数据采集将向智能化、全自动方向发展,实现动态调整与智能识别反爬策略,降低人工干预需求。附带的Python示例展示了如何通过代理IP、重试策略及日志记录实现高效的数据采集程序。
667 7
数据采集监控与告警:错误重试、日志分析与自动化运维
|
存储 监控 算法
基于 PHP 语言的滑动窗口频率统计算法在公司局域网监控电脑日志分析中的应用研究
在当代企业网络架构中,公司局域网监控电脑系统需实时处理海量终端设备产生的连接日志。每台设备平均每分钟生成 3 至 5 条网络请求记录,这对监控系统的数据处理能力提出了极高要求。传统关系型数据库在应对这种高频写入场景时,性能往往难以令人满意。故而,引入特定的内存数据结构与优化算法成为必然选择。
369 3
|
消息中间件 运维 监控
智能运维,由你定义:SAE自定义日志与监控解决方案
SAE(Serverless应用引擎)是阿里云推出的全托管PaaS平台,致力于简化微服务应用开发与管理。为满足用户对可观测性和运维能力的更高需求,SAE引入Sidecar容器技术,实现日志采集、监控指标收集等功能扩展,且无需修改主应用代码。通过共享资源模式和独立资源模式,SAE平衡了资源灵活性与隔离性。同时,提供全链路运维能力,确保应用稳定性。未来,SAE将持续优化,支持更多场景,助力用户高效用云。
|
运维 监控 虚拟化
除了实时性能监控,Hyper-V还支持日志记录和警报功能你知道吗?
Hyper-V不仅支持实时性能监控,还具备强大的日志记录和警报功能。通过事件查看器可访问详细的日志文件,涵盖虚拟机管理、配置及Hypervisor事件,帮助故障排查和性能分析。警报功能支持预定义和自定义规则,可通过多种方式通知管理员,确保及时响应问题,保障虚拟化环境的稳定运行。
|
SQL 分布式计算 Serverless
基于阿里云 EMR Serverless Spark 版快速搭建OSS日志分析应用
基于阿里云 EMR Serverless Spark 版快速搭建OSS日志分析应用
395 0

相关产品

  • 函数计算