如何构建一个无服务器的WebSockets平台

190 阅读12分钟

How to build a serverless WebSockets platform

在构建现代网络应用程序时,能够通过事件驱动架构处理实时数据,将消息即时传播到所有连接的客户端,这一点越来越重要。

有几种协议可用,但WebSocket可以说是使用最广泛的,因为它为最小的开销和低延迟进行了优化。WebSocket协议支持客户端和服务器之间通过持久的单插槽连接进行双向、全双工通信。通过WebSocket连接,你可以消除轮询,并在事件发生时立即向客户端推送更新。

如何将WebSockets集成到你的堆栈中

你可以通过设置一个专门的WebSocket服务器,让客户端连接和接收更新,从而提供一个事件驱动的架构。然而,这种架构有几个缺点,包括需要管理和扩展服务器,以及从该服务器向客户发送更新所涉及的固有延迟,而客户可能分布在世界各地。

为了在全球范围内扩展你的硬件,你可以通过向云服务提供商租用来跳过责任和所有权成本。例如,你可以使用亚马逊ECS等托管云服务,也可以选择无服务器的WebSocket解决方案。

"无服务器应用程序是指在无人使用的情况下,你不需要花费任何费用来运行它,不包括数据存储成本。"

节省运营成本是考虑无服务器框架的一个很好的理由:你获得了规模和弹性的好处,但你不需要配置或管理服务器。

本文介绍了如何构建一个基本的无服务器WebSockets平台,它是聊天等简单应用的理想选择,使用AWS API Gateway来创建WebSocket端点,并使用AWS Lambda进行连接管理和后端业务逻辑。

无服务器WebSockets平台的基本架构

构建一个简单的无服务器WebSockets平台相对简单,使用AWS API Gateway构建出WebSockets API,并使用Lambda函数进行后端处理,将消息元数据存储在Amazon DynamoDB中。

AWS API网关

AWS API Gateway是一种创建和管理API的服务。您可以将其作为一个有状态的代理来终止持久的WebSocket连接,并在您的客户端和基于HTTP的后端(如AWS Lambda、Amazon Kinesis或任何其他HTTP端点)之间传输数据。

AWS Lambda

AWS Lambda是一种无服务器的计算服务,允许你在不配置或管理服务器的情况下运行代码。

例如,WebSocket API可以调用Lambda函数,以传递消息有效载荷进行进一步处理,然后将结果返回给客户端。Lambda函数仅在处理任何单独任务所需的时间内运行。对于客户端授权,连接请求必须包括凭证,由Lambda授权器函数验证,该函数返回适当的AWS IAM策略以获得访问权限。

例子:由无服务器WebSockets驱动的聊天应用

按照惯例,我们来看一个聊天应用的例子,以说明无服务器WebSockets解决方案如何为基本的实时应用提供动力。首先,考虑客户端WebSocket连接的建立和存储顺序。

  1. 客户端设备与AWS API Gateway建立了一个单一的WebSocket连接。每个活动的WebSocket连接在API Gateway中有一个单独的回调URL,用于将消息推送回相应的客户端。
  2. 连接消息被发送到API Gateway Authorizer Lambda函数,以确认设备有正确的凭证来连接到服务。
  3. 连接消息和元数据在经过验证后被发送到一个单独的AWS Lambda。
  4. Lambda处理程序检查元数据,并将适当的信息存储在AWS DynamoDB,一个NoSQL文档数据库。

How to build a serverless WebSockets platform

客户端建立一个WebSocket连接到API网关。

在一个聊天应用程序中,用户可能会参与许多涉及一个或多个参与者的对话。这是发布和订阅模式的一个典型用例。当用户向一个特定的对话或频道发送消息时,聊天应用程序会该消息发布给所有订阅该频道的其他用户。该频道的每个订阅者都会在他们的应用程序中收到该消息。

当聊天应用程序启动到AWS API Gateway的WebSocket连接时,需要有一种方法来确定该连接被授权发布和订阅的渠道。客户端代码必须在连接元数据中发送这一信息。

现在让我们考虑一下用户发送消息,而另一个用户接收消息的情况:

  1. 客户端发送一个聊天信息,包括元数据,以确定要发布的特定渠道。
  2. 收到后,API Gateway会将其发送到相应的Lambda函数。
  3. 调用时,Lambda会检查订阅该频道的连接,并向API Gateway发送每个订阅者的ID和消息的有效载荷。
  4. API Gateway使用每个订阅者连接的回调URL,将有效载荷发送到已建立的WebSocket连接上的客户端。
  5. 断开连接后,会调用一个Lambda函数来清理数据存储。

How to build a serverless WebSockets platform

从一个客户端发送的消息会实时发布给该通道上的其他人

基本无服务器WebSockets的局限性

以上是一个使用无服务器WebSockets的实时、事件驱动应用程序的简单例子。其中的一些限制包括。

连接状态跟踪无法扩展:AWS API Gateway不跟踪连接元数据,这就是为什么它需要存储在一个数据库中,如Amazon DynamoDB,使用Lambda函数为每个连接/断开连接更新存储。对于大量的连接客户,你会遇到Lambda的扩展限制。你可以使用AWS集成到API网关来直接调用DynamoDB,但你需要注意相关的高水平的数据库使用。

我们没有解决的另一个方面是突然断开连接的问题。在客户端连接毫无预警地掉线的情况下,活动的WebSocket连接没有被正确地清理掉。数据库将有可能存储不再存在的连接标识符,这可能导致效率低下。

避免僵尸连接的一种方法是通过使用心跳机制(如TCP keepalives或ping/pong控制帧)定期检查连接是否 "活着"。发送心跳会对系统的可扩展性和可靠性产生负面影响,特别是在处理数百万个并发的WebSocket连接时,因为它会给系统带来额外的负载。

你不能向所有连接的客户端广播消息:在这个简单的设计中,没有办法同时向多个连接发送消息,正如你在标准的pub/sub通道或主题中所期望的那样。如果要通过向成千上万的客户端发布更新,你需要从数据库中获取连接ID,然后对每个连接进行API调用,这不是一个可扩展的方法。你也可以考虑用Amazon SNS来为你的应用程序添加发布/分发功能,但仍有局限性和额外复杂性的缺点。

对于一个聊天应用的例子,你可以假设典型的频道会有很低的订阅者数量,除非它们被用于有成千上万用户的互动直播会议。其他可以容忍缺乏广播的场景包括个别更新通知和逐项工作的互动功能。如果一个频道上有大量的用户接收最新的体育比分或新闻更新,实时数据扇出用例不能支持这种限制。

每秒允许的WebSocket连接数是有限制的:AWS API Gateway设置的每个区域限制为每个账户每秒500个新连接和10,000个同时连接。如果你计划扩展你的应用程序,这可能是不够的。

该解决方案被绑定到一个AWS区域:AWS API Gateway提供的WebSocket连接被绑定到一个区域,由于地理上远离该区域的客户端存在延迟,导致性能不佳。可以使用无服务器事件总线Amazon EventBridge,进行跨区域的事件路由,以复制事件。

构建生产就绪的无服务器WebSockets平台的挑战

上述架构如果用来构建一个简单的实时消息传递平台是有潜力的,尽管我们已经看到它在规模上有局限性。如果你需要一个可用于生产的系统,你将需要规模,但也需要考虑解决方案在性能、消息传递的完整性、容错性和回退支持方面的可靠性,所有这些都可能是复杂而耗时的问题。

性能方面

在一个分布式系统中,延迟越远越差,所以应该通过管理的数据中心和边缘加速点使数据尽可能接近用户。然而,仅仅将延迟降到最低还不够。用户体验需要将延迟的变化降到最低,以确保可预测性。

信息完整性

当用户的连接下降并重新连接时,应用程序需要以最小的摩擦力从他们断开连接之前的点接上。任何错过的信息都需要在不重复已经处理的信息的情况下进行传递。整个体验必须是完全无缝的

容错和可扩展性

对服务的需求可能是不可预测的,要计划和提供足够的容量是具有挑战性的。一个实时解决方案必须在任何时候都是高度可用的,以支持数据的激增。面临的挑战是横向扩展,迅速吸收数以百万计的连接,而不需要预先提供。

你的解决方案还必须是容错的,即使一个组件出现故障也能继续运行。需要有多个组件能够在一些组件丢失的情况下维持系统。不应存在单点拥堵和单点故障。

后备传输

尽管有广泛的平台支持,但WebSocket协议并不为所有代理或浏览器所支持,一些企业防火墙甚至会阻止特定的端口,这可能会影响WebSocket的访问。您可以考虑支持后备传输,如XHR流、XHR轮询或长轮询。

功能蠕变

在生产就绪的系统中使用原始无服务器WebSockets的另一个挑战可能只有在产品首次迭代中成功使用后才会出现。虽然你已经添加了接收实时更新的基本功能,但功能蠕变往往意味着这些功能为共享实时体验和协作功能种下了额外的要求。

构建和维护一个专有的WebSocket解决方案以支持产品未来的实时需求可能是一个挑战。支撑系统的基础设施必须是稳定和可靠的,需要经验丰富的工程师来构建和维护。开发团队可能会发现,他们长期致力于支持实时解决方案,而不是专注于增强核心产品的功能。

Ably:无服务器WebSocket PaaS的规模化建设

采用第三方供应商提供的无服务器WebSocket解决方案,对许多企业来说更有经济意义。否则,你可能会花费几个月的时间和大量的资金。而且,你最终会因基础设施所有权的高成本、技术债务和对工程投资的持续需求而感到负担。

Ably拥有容错、高可用、有弹性的全球基础设施,可以毫不费力地进行扩展和降低复杂性。我们的无服务器WebSockets平台是围绕可靠性的四大支柱进行数学建模的。我们可以确保信息在安全、可靠的全球边缘网络上以低延迟传递。没有DevOps的开销,也没有基础设施需要管理。

Ably平台将构建实时解决方案的烦恼抽象化,这样你就可以优先考虑你的产品路线图,开发功能以保持竞争力。

虽然Ably的本地协议是WebSocket,但很少有放之四海而皆准的协议:不同的协议比其他协议更能满足不同的目的。Ably提供多种协议,如WebSocket、MQTT、SSE和原始HTTP。

为了支持实时体验,Ably增加了一些功能,如设备存在流历史通道倒退和处理突然断开连接,使构建丰富的实时应用程序变得更加容易。有一系列的webhook集成,用于触发实时的业务逻辑。我们提供了一个从你喜欢的云服务提供商那里获取无服务器功能的网关。你可以在你的整个堆栈中部署一流的工具,并使用你已经投资的生态系统构建事件驱动的应用程序。

How to build a serverless WebSockets platform

Ably扩展了一个基本的无服务器WebSockets解决方案,以增强您的产品。

Ably使您能够提供实时体验,而不会出现上市延误、成本失控或用户不满意的情况。使用Ably可以让您的工程团队专注于核心产品的创新,而无需配置和维护实时基础设施。我们的现有客户已经通过我们建立了大规模的实时应用程序,并快速进入市场,平均节省了50万美元的构建成本。

总结

在这篇文章中,我们回顾了使用亚马逊API网关和AWS Lambda的简单无服务器WebSockets平台的架构。我们还考虑了这种设计的一些局限性,如不支持广播、单区域部署和连接管理等。

我们介绍了Ably的无服务器WebSocket平台,它可以可靠地处理大规模实时数据分发到边缘的网络和移动应用程序。