光政的博客 2024年07月09日
用 serverless 开发一个 Chat 机器人提醒
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文讲述基于Serverless技术开发Chat机器人提醒应用的过程,包括业务需求、技术选型及具体方案,还提到了开发中遇到的问题及思考。

💡业务需求方面,为解决常规会议的痛点,开发自动提醒机器人,具有定时发送消息、定时轮换owner名单等功能,且根据工作日和周末进行不同设置。

📋技术选型时,考虑系统要求和资源需求,列出多个方案。Local machine + Disk方案在本地部署,调试管理方便但可用性受限;Cloud VM + Disk方案需购买云服务器,费用较高;Serverless方案则兼顾可用性和成本。

🚀Serverless方案中,利用无服务器计算执行定时任务,发送消息给Chat Webhook服务器。因其基础设施由云服务商提供,可用性有保证且价格便宜,但需搭配云服务商的存储服务来存储人员轮换名单。

📊总结部分强调了serverless的易用性和潜力,提及业界对其开发流程和核心缺陷的完善,展望了其广阔前景。

本文描述了笔者基于 Serverless 技术开发 Chat 机器人提醒应用的全流程,记录了开发遇到的一些问题和技术选择的思考。在开发完成后,有小伙伴想知道一些技术细节来做二次开发,于是有了这篇分享。

业务需求

最开始想开发一个 Chat 机器人提醒,是因为当时项目上的人很多,每天都需要轮换站会和 Code Review 的 Owner,导致每天的站会和 Code Review 时,都需要先花费几分钟时间确认今天的站会 Owner 是谁,接着确定后还要准备 Share 屏幕,最后还需要手动维护项目人员轮换名单,会议的体验很差。为了解决以下的常规会议的痛点:

所以有了第一个想法?,即做一个自动提醒的机器人,包括有如下功能来缓解痛点:

例如站会的提醒效果图如下所示:

技术选型

在业务需求确定后,首先需要判断系统是否要求高可用、可扩展或者性能是否有要求。在这个用例中,这些技术要求都可以不要,毕竟只是自用的辅助手段,就算偶尔挂了也无所谓。这也为后续的技术选型打开了道路。

其次需要预估该功能的资源需求,该功能每天定时发送的请求给 Chat 一般不超过 10 条,所以假设 Request / Day = 10。存储的话需要存储会议的轮换名单,名字占用很少,所以预估最大就是 1KB Size of storage = 1KB

得到技术需求和资源预估后,就能在后续技术选型时有比较明确的方向。首先列出几个可以完成这个功能的方案:

Local machine & Disk

首先我们尝试使用 Python 或者任意语言在本地环境进行 Schedule 定时,直接使用本地环境进行部署运行,因为不要求高可用,偶尔的服务宕机可以接受,所以在追求最简单的方式来实现也未尝不可。

方案是使用 Python schedule 库或者任意语言定时发送消息,使用本地文件来存储轮换名单。优点是在本地部署调试和管理起来比较方便,不需要额外的花费,缺点是必须保证 Python 定时进程存活和网络可用,一旦电脑关机或者你请假时就不可用了?。如下代码 Demo 是从同目录下 code_review.txt 文件中拿到当前会议 Owner 名字和下一个 Owner 的名字,一起发送 Code Review 提醒给企业微信。

from posixpath import splitfrom corpwechatbot.chatbot import CorpWechatBotimport scheduleimport timefrom datetime import datetimemessage = """Code Review马上开始啦-----------------------------ZOOM URL: https://xxx.zoom.us/j/xxx ID: xxx Passcode: xxx-----------------------------今天的 host 是: {current_owner}明天的 host 是: {next_owner}"""def get_code_review_owner_name(): f = open('code_review.txt', 'r', encoding='utf-8') name_array = f.read().split() current_owner = name_array[0] next_owner = name_array[1] name_array.insert(len(name_array), name_array.pop(0)) write_txt = ' '.join(name_array) f = open('code_review.txt', 'w', encoding='utf-8') f.write(write_txt) f.close return current_owner, next_ownerdef send_notification(): current_owner, next_owner = get_code_review_owner_name() send_message = message.format(current_owner=current_owner, next_owner=next_owner) bot = CorpWechatBot(key='key providerd by wechat work') bot.send_text(content=send_message, mentioned_list=['@all'])schedule.every().monday.at("17:00").do(send_notification)schedule.every().tuesday.at("17:00").do(send_notification)schedule.every().wednesday.at("17:00").do(send_notification)schedule.every().thursday.at("17:00").do(send_notification)schedule.every().friday.at("17:00").do(send_notification)while True: schedule.run_pending() time.sleep(1)

Cloud VM & Disk

第二个方案使用云服务器来运行定时进程,和第一个方案使用的技术栈和代码相同,可以用任意语言定时发送消息,只需要注意服务器时区问题即可。区别在于该方案需要购买云服务器来部署,不用在意关机或者不可用问题,但是在目前这种技术需求和资源需求下,去买一个云服务器完成该功能肯定是不划算的。

以上两种方案都有各自的优缺点,一种是可用性不高,一种是费用高,所以接下来最后一种 Serverless 方案,即是可以解决这两种问题的方案,也是我们今天主要需要讲的方案。

Serverless

最后一种也是今天主要聊的方案,即使用无服务器计算的方式来完成定时计算,发送消息给 Chat Webhook 服务器。

无服务器计算(serverless computing),是一种由云服务商(AWS,Azure 或 Cloudflare)负责通过动态分配资源来执行一段代码的执行模型,并且仅收取运行代码所使用资源的费用。该代码通常运行在无状态的容器中,能够被包括HTTP请求、调度事件(cron任务)等各种事件触发并运行。因为代码运行在无状态的容器中,所以无法存储数据,对此云服务商提供了不同类型的存储服务和 SDK,可以无缝衔接对应厂商提供的 Serverless。

在之前分析技术需求时,我们了解到该应用的 Request / Day < 10,每天所需的 CPU 时间很少,所以使用 serverless 来执行定时发送消息的任务非常的合适。主要原因一是基础设施由云服务商提供,可用性方面有一定的保证,二是价格非常便宜(这也是 serverless 普及的最重要的原因)。下面是各大云服务商提供的每月免费额度,我们这个项目每个月用不到免费额度的万分之一。

由于 serverless 是不提供存储功能的,所以需要存储人员轮换名单的话,光靠 serverless 的无状态容器就不够用了。需要用到各大云服务商提出的不同类型存储服务,比如有关系型数据库、NoSQL、KV,甚至是基于 SQLite 的 serverless database,例如 Cloudflare D1。回顾我们需要存储的数据,只是简单的团队人员名单,所以无需使用结构化的数据,只需要很简单的 KV 存储即可。如下面几个 KV 服务和其对应的云厂商的免费额度:

由于 Cloudflare 原生提供绑定域名和提供 serverless database,所以笔者比较喜欢使用 Cloudflare Workers (不过可用性方面个人认为不如 AWS,偶尔会定时无效)。这里就以 Cloudflare Workers 为例展示功能代码,代码主要分为两个 serverless application,也就是两个定时任务,一是定时发送消息给 Chat 提供的 webhook 地址,另一个是定时轮换主持会议的 owner 名单。

首先是定时发送消息给 Chat 提供的 webhook 地址,从 KV 中获取当前的会议 Owner,会议地址和消息,通过获取配置的 webhook 地址发送给对应的 Chat(企业微信或者 Google Chat)。

import { send_google_chat_message } from "./google_chat_notificaiton";import { send_wework_chat_message } from "./wework_chat_notificaiton";export default { async scheduled(controller, env, ctx) { var standup_owner_name = await get_owner_name(env, env.KV_STANDUP_OWNER_NAMES); var message = `今日的站会马上开始!!!\n今日站会 owner 是: ${standup_owner_name}\n会议地址是: https://zoom.us/j/xxxx`; if (env.MESSAGE_TYPE == 'GoogleChat'){ send_google_chat_message(env, message); } else if(env.MESSAGE_TYPE == 'WeworkChat') { send_wework_chat_message(env, message); } },};async function get_owner_name(env, type) { var namesString = await env.notification_namespace.get(type); var names = namesString.split(','); return names[0];}

二是定时轮换人员名单,这里主要是因为 owner 人员的轮换和会议主持时间可能不同步,例如每周轮换一次 Owner,明天发送 owner 主持的消息,所以需要单独的一个定时。下面代码实例展示周五发送轮换 owner 的消息。从 KV 中获取下一个 onwer 列表,轮换名单,并且 push 到 KV 中以便后续发送会议消息时拿到 owner 名单。

import { send_google_chat_message } from "./google_chat_notificaiton";import { send_wework_chat_message } from "./wework_chat_notificaiton";export default { async scheduled(controller, env, ctx) { var next_standup_owner_name = await getAndRotateOwners(env, env.KV_STANDUP_OWNER_NAMES); var message = `Happy Friday! 别忘记填写 timecard 哦!!!\n下周站会 owner 是: ${next_standup_owner_name}`; if (env.MESSAGE_TYPE == 'GoogleChat'){ send_google_chat_message(env, message); } else if(env.MESSAGE_TYPE == 'WeworkChat') { send_wework_chat_message(env, message); } },};async function getAndRotateOwners(env, type) { var namesString = await env.notification_namespace.get(type); var names = namesString.split(','); names.push(names.shift()); var storeNameString = names.join(','); await env.notification_namespace.put(type, storeNameString); return names[0];}

完整的项目代码放在这个 仓库 ?

总结

回顾整个开发流程,我们能很轻易的感受到 serverless 的易用性和潜力,像类似于 WebHook、数据统计分析、Trigger 及定时任务和 Chat 机器人等功能,借用于 serverless 可以轻易的实现和部署,完成系统的原型设计和想法的闭环。近几年业界也在不断完善 serverless 的开发流程和核心缺陷,例如 JVM 冷启动问题serverless 观测和调试增强,数据库 serverless 化如wunderbaseNeonplanetscaleD1 等项目。假以时日,当这些问题慢慢解决和优化,serverless 广阔的前景和强大将刷新人们的认知。

Reference

    https://sst.dev/chapters/zh/what-is-serverless.htmlhttps://blog.cloudflare.com/introducing-d1/https://aws.amazon.com/free/https://azure.microsoft.com/en-us/pricing/free-services/https://www.infoq.com/news/2022/12/aws-lambda-snapstart-accelerate/https://github.com/wundergraph/wunderbasehttps://www.sqlite.org/serverless.htmlhttps://github.com/neondatabase/neon

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

Serverless Chat机器人 技术选型 定时任务
相关文章