准备重用 WebSocket 连接服务器,需要 Redis/ZeroMQ 后端



我需要水平可扩展的WebSocket连接服务器来像系统一样聊天,其中连接到不同WebSocket服务器的浏览器客户端在单独的聊天室中交换消息。

Clients    HaProxy  WebSocket server1   WebSocket server2    Redis/ZeroMQ
             |             |                 |                   |
client A ----=------------>o<----------------|------------------>|
             |             |                 |                   |
client B ----=-------------|---------------->o<----------------->|
             |             |                 |                   |

在这里,client Aclient B通过HaProxy连接到两个不同的WebSocket servers,它们通过后端交换消息Redis/ZeroMQ就像那个问题一样。

想到构建这种架构,我想知道是否已经有一个开源模拟。您建议考虑哪个这样的项目?

查看 Plezi Ruby 框架。我是作者,它内置了自动 Redis 可扩展性。

(您只需使用 Redis URL 设置ENV['PL_REDIS_URL'](

至于实现这一点的架构,它相当简单......我认为。

每个服务器实例"订阅"两个通道:一个用于"广播"的全局通道(发送给所有用户或大型"系列"用户的消息(和一个用于"单播"的唯一通道(用于连接到服务器的特定用户的消息(。

每个服务器都管理其内部广播系统,以便将消息路由到特定用户、连接系列或所有用户,作为其目标受众。

您可以在此处找到源代码。Redis 集成使用此代码和 websocket 目标代码进行处理。

Web 套接字广播使用 websocket 对象on_broadcast回调进行处理。碘服务器使用 websocket 实现处理每个服务器实例中的内部广播。

我已经发布了内部进程架构详细信息作为这个问题的答案

我认为 socket.io 也有跨服务器支持。

编辑(一些代码(

由于评论,我想我会输入一些代码......如果您编辑问题并添加有关您正在寻找的功能的更多规范,我可以在此处编辑代码。

我使用术语"房间",因为这就是你提到的,虽然我没有设想 Plezi 只是一个"聊天"框架,但这是一个非常简单的用例来展示它的实时能力。

如果您使用的是 Ruby,则可以在irb终端中运行以下命令(确保先安装 Plezi(:

require 'plezi'
class MultiRoom
    def on_open
        return close unless params[:room] && params[:name]
        @name = params[:name]
        puts "connected to room #{params[:room]}"
        # # if you use JSON to get room data,
        # # you can use room arrays like so:
        # params[:room] = params[:room].split(',') unless params[:room].is_a?(Array)
    end
    def on_message data
        to_room = params[:room]
        # # if you use JSON you can try:
        # to_room = JSON.parse(data)['room'] rescue nil
        # # we can use class `broadcast`, to broadcast also to self
        MultiRoom.broadcast :got_msg, to_room, data, @name if to_room
    end
    protected
    def got_msg room, data, from
        write ::ERB::Util.html_escape("#{from}: #{data}") if params[:room] == room
        # # OR, on JSON, with room arrays, try something like:
        # write data if params[:room].include?(room)
    end
end
class EchoConnection
    def on_message data
        write data
        MultiRoom.broadcast "myroom", "Echo?", "system" if data == /^test/i
    end
end
route '/echo', EchoConnection
route '/:name/(:room)', MultiRoom
# # add Redis auto-scaling with:
# ENV['PL_REDIS_URL'] = "redis://:password@my.host:6389/0"
exit # if running in terminal, using irb

您可以通过连接到以下内容来测试它: ws://localhost:3000/nickname/myroom

要连接到多个"房间"(您需要重写 JSON 和多房间的代码(,请尝试: ws://localhost:3000/nickname/myroom,your_room

通过连接到 ws://localhost:3000/echo 来测试回声

请注意,echo 的作用不同,并允许您为不同的问题使用不同的 websocket - 即,使用JSON为更新和消息设置一个连接,为通过websockets使用原始二进制数据上传多个文件。

相关内容

  • 没有找到相关文章

最新更新