消息队列服务(下文均以 Message Service 命名)作为云计算 PaaS 领域的基础设施之一,其高并发、削峰填谷的特性愈发受到开发者关注。Message Service 对上承接消息生产者服务的请求,对下连接消费者服务。提到消费:那就不得不引入两个问题?
今天就来聊聊如何在阿里云上基于 Serverless 计算服务 + Message Service 构建这样一套系统。
阿里云函数计算是事件驱动的全托管 Serverless 计算服务。通过函数计算,您无需管理服务器等基础设施,只需编写代码并上传。函数计算会为您准备好计算资源,以弹性、可靠的方式运行您的代码,更多产品细节可阅读官方文档[1]。
Connector 实现了大量数据的导入和导出。例如将 KAFKA topic 中数据导出到 stdout,或将本地文件中数据导入到 RocketMQ。Connector 简化了数据在不同系统间复制和传输的复杂度,本文探讨的消息服务和计算服务的连接同样依赖 Connector 实现。
事件总线是 Connector 的产品化服务,支持阿里云服务、自定义应用、SaaS 应用等以标准化、中心化的方式接入,并能够以标准化协议在这些应用之间路由事件,帮助您轻松构建松耦合、分布式的事件驱动架构,更多产品细节可阅读官方文档[2]。
传统的数据消费架构如下图左:
1)数据源将产生的数据写入到消息系统;
2)开发者借助 Message Service 提供的 OpenAPI/SDK 或 Proxy 服务客户端从 Message Service 读取数据;
3)根据消息数据处理业务逻辑,也就是我们所谓的消费消息,将消息消费的业务结果写入到目标服务;如此架构开发者会面临以下几个问题:
1、如何并发安全的从 Message Service 读取数据?
2、数据消费能力小于生产能力时,如何快速提升消费吞吐?
3、目标服务资源成为瓶颈时,如何快速扩容?当流量波峰过后,面对空闲的机器成本,您又如何处理?
4、如何保证消费实时性、顺序性?
5、如何实现容错、缓存、降级、限流等高可用保护手段?
6、如何监控链路状态或异常?
面对上面多个琐碎又复杂的问题,相信总有几个会击中您的痛点。为了同时解决提到的所有问题,阿里云开发 Connector Service(如上图右)打通 Message Service 和 Serverless 计算服务的数据链路,您只需声明上游的消息服务实例和下游的消费算子,便可一键部署上线,连接器同时提供了丰富的流计算框架具备的数据处理能力和监控能力,总结如下:
Transform:以 UDF 方式自定义数据清洗逻辑,同时支持 JsonPath 语法简单提取数据;
Window:提供窗口能力,可按照消息数量和间隔时间对消息做聚合推送。可提升消息处理吞吐,降低消息处理成本;
Real Time:从 Message Service 拉取消息到推送目标服务延时毫秒级别;
自定义并发消费能力:并发安全的消费消息,提升吞吐能力;
弹性计算资源:下游计算服务根据负载自动扩缩容,无需关心服务器资源水位问题;
Monitoring + Logging + Tracing:提供了丰富的监控指标和日志分析助力开发者监控系统状态、定位异常;
完备的异常保障机制:自定义重试策略 + 容错机制 + 死信队列 + 限流 + 反压;
为让大家对功能有更深入的了解,下面我们详细介绍各个功能的益处和应用场景。
在大规模数据场景中,One Message Per Request 早已无法满足开发者需求。Window 本质是提供了一种消息攒批处理的能力,Connector 在产品层面提供两个可调配参数:
两个参数结合使用可极大提升数据传输效率,进而提升数据吞吐,同时可以解锁多种用户场景,例:
消息消费离不开数据处理,所谓数据处理,就是通过某个过程将原始数据转为目标数据,转换的过程即为 transform。通常原始数据是一个大而全的信息集合,而目标数据只是一个结构化的子集,关键在于如何嵌入数据的清洗和提取能力。对此 Connector 提供了多种转换能力:
# -*- coding: utf-8 -*-
# handle_message 为函数执行入口
# 服务提供方约定了入参 event 和 context 的数据格式
# 只需从 event 中解析消息体并做处理即可
def handle_message(event, context):
try:
new_message = transform(event)
except Exception as e:
raise e
return new_message
def transform(old_message):
# 自定义对数据的清洗和处理逻辑,并返回处理后的消息
return new_message
Filter 减少无用消息的后续处理,提升消息处理的效率,尤其和 Serverless 计算结合时,可减少调用次数,例如以下场景:
为覆盖足够多的业务场景,Connector 提供了前缀匹配、后缀匹配、数值匹配、IP 地址匹配等多种匹配模式,您可以根据业务需求选择适合的模式。
在流计算场景中,低延时消费是开发者比较关注的一个问题,Connector 在提供批处理能力的同时也兼顾了流处理场景,当时间攒批窗口设置为 0 时,系统将演变为实时消费行为。
以 KAFKA 为例,当 KAFKA 数据量增大时,用户通常借助 Topic Partition 的水平扩展能力提升投递和消费的速率,随着 Topic Partition 分区数的不断增加,Consumer 端仍沿用单线程消费所有 partition 数据的方案一定会遇到瓶颈,进而导致消息积压。为了解决此问题,Connector 开放了自定义并发消费线程数配置,您可以指定多个 consumer threads,多个 consumer threads 会均分 kafka 的多个 partition,避免消息积压问题。当 Topic Partition 数量和 Consumer 线程数相等时可达到最大吞吐(如下图3),同时可做到 Partition 粒度保序。
针对上面两种场景,系统均通过技术手段做了保护,技术细节暂不描述。
Connector 打通了消息服务和 Serverless 函数计算服务,您可能会担心一个问题:函数计算服务的算力能否实时适配上游消息规模的不断增长?答案是可以的。函数计算作为 Serverless 计算服务,底层的计算资源可以做到毫秒级伸缩,不论您的 consumer 端并发消费能力如何调整,投递消息的频率有多高,函数计算均可在 quota 范围内快速伸缩计算实例。
计算实例 Quota 是函数计算出于对业务方服务保护设置的最大并发运行实例数,如果实际业务规模大于此默认值,可以给函数计算团队提工单调高此值。
Connector 定义了数据从哪里复制到哪里,通过协调调度一系列 task 完成数据的传输工作,Task 根据职责不同可划分为以下几类:
Task 均可水平扩展,并发消费上游多 partition 数据,且并发将消息投递到下游处理。
当前 Connector 依赖阿里云 EventBridge 实现,更多能力可参考官方文档[3]
某广告平台每天将浏览的用户信息(个人信息、时间、登录设备等)投递至 kafka 中,从业务角度投递的数据格式并不完全相同,客户需将不同格式的数据清洗为相同格式的数据,并将清洗后的数据投递到 ClickHouse 服务,随着用户业务日益增长,预计未来几个月有几倍增长,且客户对实时性和成本都有要求,总结客户的几点关键需求如下:
函数计算恰好可以完美解决上述问题,下面结合如下数据链路介绍如何解决客户的几个需求:
通过下图可发现,kafka topic 的 partition 分区数、Poller 数量、Sink Task 的 worker 数量、函数计算的计算实例数都可实现任意水平扩展,且均可通过配置调整,因此当客户预判到业务增长时,只需修改相应的配置项即可实现水平扩容。
目前客户已将业务全量迁移到函数计算,迁移后的几个月内仅通过简单修改扩容配置轻松应对业务规模的数倍增长。
下文通过演示一个将 kafka 数据导入到函数计算的 demo,快速搭建一套消息消费系统:
a.创建函数计算的服务,并为服务命名,如下图:
b.在创建的服务下创建一个函数,函数是执行代码的最小单元,如下图:
c.在创建函数页面,为函数命名,并点击触发器配置,其中触发器类型选择 kakfa,将 step1 创建的资源(kakfa 实例、Topic、Group ID )填写到下图中,其他值可使用默认值。
d.(可选) 如需要验证攒批功能,可点击批量推送,并配置批量推送条数和批量推送间隔,此 demo 设置批量推送条数为 2 条,批量推送间隔为 10s,如下图:
e.上面流程完成后点击确定即部署成功。
3.编写函数,函数内的逻辑为输出接收到的消息数量和消息内容:
# -*- coding: utf-8 -*-
import logging
import json
def handler(event, context):
evt = json.loads(event)
logger = logging.getLogger()
logger.info(len(evt)) // 输出消息列表的长度
logger.info(evt)。 // 输出消息内容
return 'succ'
4.测试验证
a.到 kafka 控制台的 topic 中快速发送 3 条消息,如下图:
b.预期函数计算会收到 2 次请求,第 1 次请求由于触发推送条数条件包含 2 条消息,第 2 次请求在等待 10s 后触发推送间隔条件包含 1 条消息,如下图:
c.可通过函数日志查看所有请求日志,可以发现一共接收到 3 条消息,如下图:
基于 Serverless 函数计算,您可以快速搭建一套安全可靠的数据消费系统,总结系统优势如下:
随着云计算逐渐走向全面 Serverless 化,Message Service 和 Serverless 计算的连接会更加紧密,如今 Connector 的成熟更加降低了复杂系统的开发门槛,让您真正实现端到端全链路深度上云。
作者 | 柳下
原文链接
本文为阿里云原创内容,未经允许不得转载。