【发布时间】:2014-06-18 21:27:42
【问题描述】:
我正在研究一种用于从远程嵌入式设备发送/接收消息的服务器架构,该设备将托管在 Windows Azure 上。前端服务器将与这些设备保持持久的 TCP 连接,我需要一种在后端与它们通信的方法。
问题事实:
- 设备:~10,000
- 设备向服务器发送消息的频率:1/分钟
- 来自服务器端的消息频率(例如,来自用户操作、预定触发器等):100 条/天
- 消息负载的平均大小:64 字节
向上沟通
设备非常频繁地发送消息(传感器读数)。由于我们可以以批处理方式聚合/插入这些传感器读数,并且它们不需要按顺序保证,因此该数据的约束不是很强。我认为处理它们的最佳方法是将它们放入存储队列中,并让工作进程定期轮询队列并转储该数据。当然,我必须小心确保工作进程足够频繁地执行此操作,以免队列无限备份。 Azure 存储队列的最大批量大小为 32,但我正在考虑可能会引入更多:例如每 1000 个读数或 30 秒发布到数据存储,以先到者为准。
向下沟通
服务器发送更新和通知的频率要低得多。这是一个稍微困难的问题,因为我可以在这里看到两个可行的范例(两者之间有一些混合)。可以:
- 为每台设备创建一个服务总线队列(或一个具有数千个订阅的队列 - 队列数限制为 10,000)
- 在数据库中保存一个状态表,其中包含设备将发送给它们的特定消息类型的最新“状态”
使用选项 1,应用程序服务器只需以即发即弃的方式将消息排入队列。然而,在前端服务器上,有很多事情必须发生。我可以看到的担忧包括:
- 监控 10k 队列(或队列外的许多订阅 - Azure SDK 显然重用了订阅相同的连接 队列)
- 连接管理
- 如果设备断开连接,则不应再监控队列。
- 如果设备长时间断开连接,则需要使消息过期(以便不备份队列)
- 需要启用某种类型的“刷新”机制,以便在设备重新联机时更新设备的完整状态
好消息是服务总线队列是持久的,并且会话可以安排消息以 FIFO 方式进入。
使用选项 2,数据库将包含一个表,该表将维护所有设备的状态。该表将由前端服务器定期检查(每隔几秒左右),以了解应用程序服务器写入它的状态更改。然后,前置服务器将分派给设备。这消除了对 FIFO 排队的要求,原因是该消息包含最新状态,并且不必与发往同一设备的其他消息竞争。该消息是短暂的:如果失败,则将在设备重新连接并请求刷新时重新发送,或者在前端服务器的下一次检查间隔时重新发送。
在这种情况下,似乎不需要队列,但数据库成为这里的瓶颈,我担心它没有那么可扩展。
这些都是可行的方法,我觉得这个问题已经变得太大了(尽管如果有必要我可以提供更多的描述)。只是想了解什么是可能的,通常会做什么,是否缺少一些基本的东西,以及我可以利用云中的哪些东西而不是重新发明轮子。
【问题讨论】:
-
对于传入的数据,考虑最初将这些数据存储到存储表中——这些可以支持非常高的吞吐量。通过工作角色异步处理数据(我相信你已经计划好了),也许利用队列来尽可能地并行化。对于传出数据,请查看通知中心。您必须弄清楚如何提供它并消除您的数据库作为瓶颈,但它可以管理大量连接。
-
@Jaxidian 让我确定我明白你在说什么。如果我将传入数据存储在存储表中,我可能会设置 ParitionKey = DeviceId 和 RowKey = TimeStamp。我必须保持一些关于上次处理时间的状态,然后查询以获取从那时起的新行。我会在每个设备上执行此操作,将自上次查询以来的批处理并将该批处理作为单个插入排队到队列中。然后,工作进程将出列并将这些批次插入数据存储(这是一个数据库)。
-
@Jaxidian 对于通知中心,我对其进行的所有研究都表明它仅适用于移动设备。此外,在某些情况下,向下发送的消息必须具有 FIFO 语义,或者设备需要存储消息类型的时间戳并丢弃比它们当前拥有的更旧的任何内容。不确定通知中心如何处理这个问题。最后,我找不到任何关于它发出的消息的及时性保证的文档/SLA。
标签: azure tcp embedded cloud azureservicebus