我在聊天项目中使用了Redis、NGINX 和 PHP-FPM。不是超级优雅,但它可以解决问题。这个难题有几个部分。
有一个非常简单的 PHP 脚本,它接收客户端命令并将它们放在一个巨大的 LIST 中。它还检查所有房间列表和用户私人列表,以查看是否有必须传递的消息。这是由一个用 jQuery 编写的客户端轮询的,每隔几秒钟就会完成一次。
有一个命令行 PHP 脚本在无限循环中运行服务器端,每秒 20 次,它检查这个列表,然后处理这些命令。脚本在脚本内存中处理谁在什么房间和权限,此信息不存储在 Redis 中。
Redis 为每个房间都有一个 LIST,每个用户都有一个 LIST,作为私有队列运行。对于用户所在的每个房间,它也有多个计数器。如果用户计数器小于房间中的消息总数,那么它会获取差值并将其发送给用户。
我无法对这个解决方案进行压力测试,但至少从我的基本基准测试来看,它可能每秒可以处理数千条消息。还有机会将其移植到 Node.js 之类的东西上以提高性能。Redis 也正在成熟,并且具有一些有趣的功能,例如 Pub/Subscribe 命令,这可能很有趣,可能会消除服务器端的轮询。
我研究了基于 Comet 的解决方案,但其中许多都很复杂,文档记录不充分,或者需要我学习一种全新的语言(例如 Jetty->Java、APE->C)等......有时也可以通过代理进行交付和通过成为彗星的问题。所以这就是我坚持投票的原因。
我想你可以用 MongoDB 做类似的事情。每个房间一个集合,每个用户一个集合,然后是一个维护计数器的集合。您仍然需要编写后端守护程序或脚本来处理这些消息的去向。您还可以使用 MongoDB 的“有限集合”,它可以保持文档排序并自动清除旧消息,但是维护适当的计数器可能会很复杂。