前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【swoole4.0】分布式广播实现

【swoole4.0】分布式广播实现

作者头像
桶哥
发布2019-06-04 18:32:48
1.3K0
发布2019-06-04 18:32:48
举报
文章被收录于专栏:PHP饭米粒PHP饭米粒PHP饭米粒

源起

群里的一个提问

问题

这是一个比较典型的场景,当用户发展到一定程度后,单机的支撑能力是有上限的,这个时候必需用多台机器进行水平扩展了,那针对长连接这种有状态的情况下,就必需面临以下2个问题?

  1. 怎么分配用户到哪台机器上?
  2. 同一房间的用户被分配到不同机器上,如何广播和相互通讯

万变不离其宗,我们先看单机的场景下如何处理

单机的广播场景

如果要进行全局广播,那非常easy, 可以用swoole内置的方法:

foreach($server->connections as $fd)
{
    $server->send($fd, "hello");
}

echo "当前服务器共有 ".count($server->connections). " 个连接\n";

(PS: 广播可以放到task进程,避免堵塞worker进程)

这个只是所有的广播,如果我想做组播怎么办?

单机组播

以聊天室为例,广播就相当于整个系统是一个大聊天室,但实际情况往往是需要多个聊天室,相互之间不影响,对某一个聊天室进行广播,称之为组播,那需要怎么做呢? 实现想来也非常简单,这个时候,我们可以引入redis,以房间Id做为key,创建一个list,进入该房间时,用户加入到这个list中,退出房间时,从list删除, 相关伪代码如下:

单机场景下,服务非常简单,就一个websocket server外加一个redis 时序图基本如下:

OK,现在我们回到最开始提到的问题,当一台机器变成N台机器之后,怎么办?

分配用户到哪台机器上?

这时,建议专门把登录服务提出来,这是一个http服务,用户登录成功之后,除了返回token之外,还返回一台聊天服务器的ip和端口,原因有:

  1. 登录服务无状态,可以水平扩展
  2. 返回哪台服务器的ip和端口就可以做很多灵活的策略,通常有以下
    1. 随机
    2. 轮询
    3. 跟据对应的服务器的负载状态
    4. ====
  3. 聊天服务器也可以水平扩展了

这里面还有一个关键的一步: 把用户的uid 和 对应的服务器ip/port 关系绑定,这有助于我们知道用户在哪台机器上

Proxy

除了要把登录服务单独拎出来,还需要一个proxy,专于来处理各服务之间的通信和redis的交互

如我们进入房间的操作,退出房间,都通过这个proxy把数据存放在redis里

聊天室广播

聊天服务器的核心代码如下:

proxy的关键代码如下:

通过引入中间的proxy层,可以很方便的进行server之间的转发,不管同一个房间的用户分散到哪,通过redis都能找到对应的关系

大致的思路如上,当然做好一个分布式聊天室的细节还非常多,有何问题,随时交流, 希望能给大家带来帮助。

----------伟大的分割线-----------

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-04-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 PHP饭米粒 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档