InfoQServerless 架构下如何实现日志的实时输出?( 二 )

plt.subplot(2,1,1)x_data = http://news.hoteastday.com/a/range(0, len(timeList))plt.plot(x_data, timeList)plt.subplot(2,1,2)plt.hist(timeList, bins=20)plt.show print(err)这是比较差的一段代码 , 耗时很久 , 可以考虑加入队列 , 一方面多进程在队列面加入执行的 RequestId , 一方面消费 RequestId , 进入到获取 Logs 的对象中 , 速度可以大大提升 。 但是无论如何 , 运行结果如下:
最大时间 31最小时间 0平均时间 17
InfoQServerless 架构下如何实现日志的实时输出?
本文插图
通过这个结果 , 我们发现日志输出有两个问题:

  • 时间频率不固定 , 通过数据可以看到 , 快的话可能几秒就出结果 , 慢的话可能十几秒 , 二十几秒 , 甚至三十几秒;
  • 日志普遍输出速度很慢 , 会严重影响定位问题;
就目前的腾讯云 Serverless 架构而言 , 如果要在本地开发一个项目 , 并在本地进行了初步的调试 , 就算一切正常 , 也并不能保证在线上完全可用 , 尤其在复杂的触发器环境下以及复杂的对象复用、内网资源使用的前提下 , 本地调试的难度非常大 , 很难完整模拟出线上的环境 。
以 API 网关触发器为例 , 当本地写完代码 , 调试完成部署线上 , 通过 API 网关触发一次 , 发现函数代码不能正常运行 , 这个时候的第一想法是什么?查看日志 , 看一下打印的日志有哪些问题 , 是不是通过日志可以判断出问题 。 很遗憾的告诉你 , 你可能要等几秒钟 , 十几秒钟 , 甚至二十几秒 , 三十秒 。
自建日志输出功能通过刚才的分析 , 我们可以知道 , 在线上触发函数的时候 , 日志入库的速度非常缓慢 , 而且极其不稳定 , 一定条件下会严重影响开发进度以及问题定位的进度 。 为了解决这个问题 , 我们可以通过 Serverless 架构 , 封装一套实时日志功能:
【InfoQServerless 架构下如何实现日志的实时输出?】
InfoQServerless 架构下如何实现日志的实时输出?
本文插图
在这个操作过程中 , 主要使用一个 API 网关作为 Websocket 与客户端建立链接 , 三个函数(注册函数 , 上报函数 , 清理函数)与 API 搭配使用 , 存储桶作为部分资源的临时存储 。
整个流程大概可以描述为:
  1. 客户端决定开启实时日志 , 并将要监控的函数信息(包括地域 , 命名空间 , 函数名)作为参数 , 与 API 网关建立 Websocket 链接;
  2. API 网关建立 Websocket 链接的时候 , 会触发注册函数 , 此时注册函数会将 RequestId(ConnectionId)与函数信息以 Key-Value 存储到对象存储中;
  3. 根据函数信息找到对应的函数 , 将回推地址以及 ConnectionId 写到函数环境变量中;
  4. 此时函数只要被触发 , 就会先读取环境变量 , 根据环境变量决定是否将函数日志上报到指定地址(即带着 connectionId 发送到回推地址);
  5. 上报函数收到业务函数传递过来的数据 , 将数据发送到指定的 ConnectionId 的客户端 , 实现实时日志的输出;
  6. 当客户端断开连接之后 , 会触发清理函数;
  7. 清理函数会清理掉业务函数中的回推地址和 ConnectionId 等信息 , 清理之后 , 业务函数再被触发 , 则会因为读取不到该参数 , 而不会上报数据;
  8. 将根据 RequestId(ConnectionId)从对象存储删除 , 至此完成一次日志实时输出功能;
由于腾讯云的 API 网关限制 , 所以该功能每次最长只能执行 900s , 900s 之后需要重新执行该程序 。


推荐阅读