我的问题涉及以下用例:
用例 Actor
用例描述
当用户 A 的 livefeed 打开时,它的顶部会出现一个带有 1 个新 livefeed 项目的标签。
用户 A 收到类似于此 Facebook 示例的通知:
我想应用的解决方案(我认为 Pubnub 使用的)是为每个 geohash 创建一个主题。
在我的情况下,这意味着对于广播消息的每个用户,都需要将其发布到 geohash-topic,如果 geohash-topic 落入范围内,客户端(应用程序/网站用户)将通过 websocket 使用 geohash-topic定义的区域(半径)。 Ably 似乎使用 Web 套接字提供这种可扩展的服务。
我想它会简化为这样的:
所以这意味着需要从发送广播消息的当前位置提取 geohash。这个 geohash 应该具有足够小的粒度尺度,以便接收用户可以设置或多或少准确的广播区域。 (即,如果我们希望允许用户定义接收实时消息的广播区域,那么 geohash 应该具有足够的准确性,这意味着如果我们决定扩展,人们应该期待相当多的主题)。
选项 2 是为具有较小粒度(覆盖更大区域)的 geohash 创建主题,并让客户端根据随消息一起发送的 latlng 值处理准确性。
然后客户端将决定是否丢弃消息。然而,这意味着发送更多的消息(更多的开销)和更高的成本。
我没有这种架构的经验,并质疑这种方法的可行性/可扩展性。
您能否想到此问题的替代解决方案以达到预期的结果,或者提供有关如何整体解决此类问题的更多见解? (我也考虑过使用常规的 req-res 流,但这意味着向服务器发送垃圾邮件,这似乎也不是一个很好的解决方案)。
我确实查过。
给定一个 161.4 平方公里的区域(如布鲁塞尔区域),geohashs 按字符串长度的划分如下:
1 ≤ 5,000km × 5,000km
2 ≤ 1,250km × 625km
3 ≤ 156km × 156km
4 ≤ 39.1km × 19.5km
5 ≤ 4.89km × 4.89km
6 ≤ 1.22km × 0.61km
7 ≤ 153m × 153m
8 ≤ 38.2m × 19.1m
9 ≤ 4.77m × 4.77m
10 ≤ 1.19m × 0.596m
11 ≤ 149mm × 149mm
12 ≤ 37.2mm × 18.6mm
考虑到我们允许用户有高达 1.53 亿的可能不准确度(在用户可能希望订阅接收本地广播消息的区域上),它需要的主题数量肯定已经太大了,甚至只能覆盖布鲁塞尔的整个地区。
所以我目前仍然有点停留在这个级别。
最佳答案
1. PubNub
PubNub 是目前唯一通过 websockets 提供开箱即用的 geohash pub-sub 解决方案的服务,但它们的定价非常高(500 个连接设备的成本约为 49 美元,2 万个设备的成本为 799 美元)更新:PubNub 更新了价格,现在无限设备。网站更新即将推出。
Pubnub 正在研究他们的定价模型,因为他们的一些客户为意外的流量高峰支付了很多费用。
但是,对于旨在对所有人开放的通用广播消息应用程序,它不是一个可行的解决方案,因此流量非常不可预测。
很遗憾,否则这项服务对我们来说是完美的解决方案。
2. 安利
Ably 提供了一个 pubsub 系统,通过 websockets 为自定义 channel 将数据流式传输到客户端。当客户端附加自己以便发布或订阅该 channel 时,会动态创建 channel 。
这里的主要问题是:
假设我们采用一个由 4 个字符的 geohash 表示的 channel ,跨越 39.1 x 19.5 公里的地理区域。
发送到该 channel 的任何帖子都将被多路复用给该区域内当前正在收听的每个人。
但是,假设我们的应用程序允许最大半径为 10 公里,并且一半的连接用户将其设置为 1 公里半径。
这意味着 2 公里半径之外的所有帖子将不必要地复用给这些用户,并且只会被丢弃而不再使用。
我们还应该考虑这种方法的可扩展性。对于生产者或消费者需要的每个 geohash,将创建另一个 channel 。
拥有一个需要基于全局地理哈希的主题的应用程序肯定比只需要基于主题的主题的应用程序更昂贵。
也就是说,在全局范围内采用时,主题数量急剧增加,因此价格也会增加。
另一个考虑是我们的应用程序需要额外数量的 channel :
尽管有一些对这种方法的乐观考虑:
当用户打开带有我们网站的浏览器窗口时 +
当用户使用移动设备并主动打开相关提要时
刷新提要后 20 秒
在这方面,一个非常重要的注意事项是 Ably 如何向其消费者收费,这可以充分利用我们的优势:
A channel is opened when any of the following happens:
- A message is published on the channel via REST
- A realtime client attaches to the channel. The channel remains active for the entire time the client is attached to that channel, so if you connect to Ably, attach to a channel, and publish a message but never detach the channel, the channel will remain active for as long as that connection remains open.
A channel that is open will automatically close when all of the following conditions apply:
There are no more realtime clients attached to the channel At least two minutes has passed since the last message was published. We keep channels alive for two minutes to ensure that we can provide continuity on the channel as part of our connection state recovery.
As an example, if you have 10,000 users, and at your busiest time of the month there is a single spike where 500 customers establish a realtime connection to Ably and each attach to one unique channel and one global shared channel, the peak number of channels would be the sum of the 500 unique channels per client and the one global shared channel i.e. 501 peak channels. If throughout the month each of those 10,000 users connects and attaches to their own unique channel, but not necessarily at the same time, then this does not affect your peak channel count as peak channels is the concurrent number of channels open at any point of time during that month.
乐观结论
最重要的结论是,我们应该考虑到,对于应用程序的第一个版本,此功能可能不如我们认为的那么重要。
尽管 Twitter、Facebook 等提供了接收实时更新的功能(并且用户已经开始期待它),但我们应用程序的有限规模的初始测试版可以在没有的情况下运行,即用户必须刷新才能接收新的更新。
在应用程序的首次启动期间,可以收集统计数据以更深入地了解详细的用户行为。这将使我们能够基于事实数据构建更可靠的基础设施和财务反射(reflection)。
关于websocket - 关于基于geohashes的pubsub主题划分的建议,用于巧妙的websocket连接服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50682331/