函数计算+日志服务 -- 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在监控领域的新玩法。

相关实践学习
基于函数计算一键部署掌上游戏机
本场景介绍如何使用阿里云计算服务命令快速搭建一个掌上游戏机。
建立 Serverless 思维
本课程包括: Serverless 应用引擎的概念, 为开发者带来的实际价值, 以及让您了解常见的 Serverless 架构模式
目录
相关文章
|
6天前
|
存储 运维 监控
【Docker专栏】Docker日志管理与监控的最佳方法
【5月更文挑战第7天】本文探讨了Docker容器的日志管理与监控,强调其在运维中的重要性。Docker默认使用`json-file`日志驱动,可通过`docker logs`命令查看。建议选择合适日志驱动,配置日志选项,并集成ELK Stack等工具进行高级分析。实时监控、设置警报、分析数据和审计日志是实践关键。最佳实践包括日志数据与容器数据分离、使用日志代理、保护敏感信息及遵守法规。关注新技术以提升系统稳定性和安全性。
【Docker专栏】Docker日志管理与监控的最佳方法
|
7天前
|
监控 安全 数据可视化
中间件应用日志记录和监控
中间件应用日志记录和监控
20 3
|
13天前
|
Prometheus 监控 Cloud Native
【Go语言专栏】Go语言中的日志记录与监控
【4月更文挑战第30天】Go语言在软件开发和运维中扮演重要角色,提供灵活的日志记录机制和与多种监控工具的集成。内置`log`包支持基本日志记录,而第三方库如`zap`、`zerolog`和`logrus`则扩展了更多功能。监控方面,Go应用可与Prometheus、Grafana、Jaeger等工具配合,实现系统指标收集、可视化和分布式追踪。健康检查通过HTTP端点确保服务可用性。结合日志和监控,能有效提升Go应用的稳定性和性能。
|
13天前
|
存储 监控 关系型数据库
PHP编写的电脑监控软件:用户登录日志记录与分析
使用PHP编写简单但功能强大的电脑监控软件,记录用户登录日志并进行分析。代码示例展示了如何获取并存储用户IP地址和登录时间到数据库,然后进行登录数据的分析,如计算登录频率和常见登录时间。此外,还介绍了如何通过定时任务自动将监控数据提交到网站,以便实时监控用户活动,提升系统安全性和稳定性。
39 0
|
13天前
|
Prometheus 监控 Kubernetes
Kubernetes 集群的监控与日志管理策略
【4月更文挑战第30天】 在微服务架构日益普及的当下,容器化技术与编排工具如Kubernetes成为了运维领域的重要话题。有效的监控和日志管理对于保障系统的高可用性和故障快速定位至关重要。本文将探讨在Kubernetes环境中实施监控和日志管理的最佳实践,包括选用合适的工具、部署策略以及如何整合这些工具来提供端到端的可见性。我们将重点讨论Prometheus监控解决方案和EFK(Elasticsearch, Fluentd, Kibana)日志管理堆栈,分析其在Kubernetes集群中的应用,并给出优化建议。
|
14天前
|
运维 Serverless 应用服务中间件
Serverless 应用引擎产品使用之在阿里云Serverless中函数计算FC nginx 部署上去之后放置静态页面如何解决
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
219 0
|
14天前
|
弹性计算 运维 Serverless
Serverless 应用引擎产品使用之在阿里函数计算中,使数据库和阿里云函数计算位于同一个内网中如何解决
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
989 0
Serverless 应用引擎产品使用之在阿里函数计算中,使数据库和阿里云函数计算位于同一个内网中如何解决
|
14天前
|
运维 监控 Serverless
Serverless 应用引擎产品使用之在阿里函数计算中,在response.send()之后继续执行其它代码如何解决
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
162 0
|
14天前
|
运维 负载均衡 Java
Serverless 应用引擎产品使用之在阿里函数计算中,创建了个关于 stable diffusion 的函数服务,总是很卡如何解决
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
143 0
|
14天前
|
人工智能 运维 Serverless
Serverless 应用引擎产品使用之在阿里函数计算中使用自定义字体如何解决
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
140 0

热门文章

最新文章

相关产品

  • 函数计算