websocket - 关于基于geohashes的pubsub主题划分的建议,用于巧妙的websocket连接服务

标签 websocket publish-subscribe geohashing ably-realtime

我的问题涉及以下用例:

用例 Actor

  • 用户 A:设置广播区域并查看带有实时帖子的流的用户。
  • 用户B:在用户A设置的广播区域内第一个发送广播消息的用户。
  • 用户C:从用户A设置的广播区域内发送广播消息的第二个用户。

  • enter image description here

    用例描述
  • 用户A选择一个广播区域,在该区域内他希望接收直播消息的边界(半径)。
  • 用户 A 打开实时供稿并请求一组初始的实时供稿项目。
  • 用户 B 从用户 A 的广播区域内广播一条消息,而用户 A 的直播仍处于打开状态。
    当用户 A 的 livefeed 打开时,它的顶部会出现一个带有 1 个新 livefeed 项目的标签。
  • 当用户 C 从用户 A 的所选广播区域内发布另一个实时馈送帖子时,标签计数器会增加。

  • 用户 A 收到类似于此 Facebook 示例的通知:
    enter image description here

    我想应用的解决方案(我认为 Pubnub 使用的)是为每个 geohash 创建一个主题。
    在我的情况下,这意味着对于广播消息的每个用户,都需要将其发布到 geohash-topic,如果 geohash-topic 落入范围内,客户端(应用程序/网站用户)将通过 websocket 使用 geohash-topic定义的区域(半径)。 Ably 似乎使用 Web 套接字提供这种可扩展的服务。

    我想它会简化为这样的:

    enter image description here

    所以这意味着需要从发送广播消息的当前位置提取 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 。

    这里的主要问题是:

  • 如果我们想要高 geohash 准确度,我们需要大量的 channel ,因此我们必须付出更多;
  • 如果我们使用低 geohash 精度,将会有很多冗余消息:
    假设我们采用一个由 4 个字符的 geohash 表示的 channel ,跨越 39.1 x 19.5 公里的地理区域。

  • 发送到该 channel 的任何帖子都将被多路复用给该区域内当前正在收听的每个人。

    但是,假设我们的应用程序允许最大半径为 10 公里,并且一半的连接用户将其设置为 1 公里半径。

    这意味着 2 公里半径之外的所有帖子将不必要地复用给这些用户,并且只会被丢弃而不再使用。

    我们还应该考虑这种方法的可扩展性。对于生产者或消费者需要的每个 geohash,将创建另一个 channel 。

    拥有一个需要基于全局地理哈希的主题的应用程序肯定比只需要基于主题的主题的应用程序更昂贵。

    也就是说,在全局范围内采用时,主题数量急剧增加,因此价格也会增加。

    另一个考虑是我们的应用程序需要额外数量的 channel :
  • 通过 geohash 和组:我们的应用程序允许创建基于地理位置的组(这相当于 Twitter 之类的 #hashtags)。
  • 按地点
  • 被关注的用户(高级功能)

  • 尽管有一些对这种方法的乐观考虑:
  • 仅当新闻源处于事件状态时才需要流式传输:
    当用户打开带有我们网站的浏览器窗口时 +
    当用户使用移动设备并主动打开相关提要时
  • 可以做进一步的优化,例如仅从 10 点开始流式传输
    刷新提要后 20 秒
  • 根据当前事件,按地点/跟随用户进行流式传输可能会有很高的流量,但许多地点 channel 也会空闲

  • 在这方面,一个非常重要的注意事项是 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/

    相关文章:

    elasticsearch - Kibana 3 GeoJSON 与 Kibana4 Geohash

    mysql - Laravel-4 本地服务器上用户的实时内容更新

    jms - Kafka 有持久订阅功能吗?

    javascript - 当发布和订阅位于两个单独的文件中时,Amplify.js 发布订阅不起作用

    java - Lagom 使用 Kafka 发布消息

    swift - Firestore 查询 geohash 过滤

    algorithm - Geohashes - 为什么需要交错索引值?

    heroku - WebSocket 推送数据库更新

    python - Websocket/event-source/... 实现将双向 RPC 暴露给 python/django 应用程序

    javascript - Socket IO 1.2 查询参数