heimdallr是一个大型聊天应用服务器,受到 LINE+ 聊天服务架构的启发,基于 Akka 的 Actor 模型用 Scala 语言编写。它基于 Redis Pubsub 提供容错且可靠的横向扩展选项,支持从概念验证到企业就绪解决方案的扩展。经测试,对于大型系统,它的速度至少比 socket.io 快 100 倍。 heimdallr目前由现实世界的生产提供支持,并支持大量同时连接。该项目根据 Apache License v2.0 获得许可。
heimdallr的架构由 Akka HTTP Server、Streams 和 ChatRoomActor、UserActor、AggregationActor 组成。每个聊天室可以分布在多个服务器上。为了在服务器之间同步消息,我们使用Redis PubSub。 UserActor 是为每个 websocket 客户端创建的。
TODO:尚未实施。
下面的 HTTP 服务器测试是使用 wrk 基准测试工具在单个 m4.large 实例上使用 6 个线程和 10000 个连接完成的。
Node.js | heimdallr | |
---|---|---|
每秒请求数 | 14533.90 | 20675.89 |
平均。延迟 | 68.94 毫秒 | 13.35 毫秒 |
概括 | 1.00m 内有 873389 个请求,读取 108.36MB 套接字错误:连接 8981、读取 0、写入 0、超时 0 请求数/秒:14533.90 传输/秒:1.80MB | 1.00m 内有 1242244 个请求,读取 181.26MB 套接字错误:连接 8981、读取 0、写入 0、超时 0 请求数/秒:20675.89 传输/秒:3.02MB |
该表显示了事件广播的性能、消息到达 websocket 客户端的平均延迟。此测试是在与 HTTP 服务器测试相同的 m4.large 实例上完成的。
Socket.io (单节点) | heimdallr (单节点) | heimdallr星团 (2个节点) | heimdallr星团 (4个节点) | |
---|---|---|---|---|
10 间酒吧、1 间酒吧 | 43 毫秒 | 43 毫秒 | 16毫秒 | 20毫秒 |
100 个潜艇,5 个酒吧 | 62 毫秒 | 61 毫秒 | 53 毫秒 | 32毫秒 |
1000 个潜艇,10 个酒吧 | 496 毫秒 | 390 毫秒 | 129 毫秒 | 47 毫秒 |
1000 间酒吧,50 间酒吧 | 1304 毫秒 | 554 毫秒 | 141 毫秒 | 109 毫秒 |
1000 个潜艇,100 个酒吧 | 2242 毫秒 | 605 毫秒 | 202 毫秒 | 114 毫秒 |
克隆存储库并尝试使用 sbt 进行构建:
% sbt run
要设置 Websocket 负载均衡器,您可以将 HAProxy 或 Apache2 HTTPD 与代理模块结合使用。如果需要支持大并发,推荐使用AWS ALB或HAProxy。如果要使用 Apache2,请使用以下命令启用模块: sudo a2enmod rewrite proxy proxy_http proxy_wstunnel proxy_balancer lbmethod_byrequests
并编辑虚拟主机文件,如下所示:
<VirtualHost *:80>
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
<IfModule proxy_module>
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/
RewriteRule ^(.*)$ /$1 [P]
ProxyRequests Off
ProxyPass "/" balancer://mycluster/
<Proxy "balancer://mycluster">
BalancerMember ws://{ heimdallr _SERVER_ADDRESS_1}:8080
BalancerMember ws://{ heimdallr _SERVER_ADDRESS_2}:8080
</Proxy>
</IfModule>
</VirtualHost>
要启用 Redis PubSub,请打开 application.conf 文件并编辑 Redis IP 地址和端口,如下所示:
redis-ip = "{REDIS_IP_ADDRESS}"
和redis-port = 6379
在此示例中,使用了 Java-WebSocket 库。
public class WSClientSample extends WebSocketClient {
public WSClientSample ( URI serverURI ) {
super ( serverURI );
}
...
public static void main ( String [] args ) throws Exception {
String uri = ( "ws://APACHE_WEBSERVERR/{CHATROOMID}" );
WSClientSample c = new WSClientSample ( new URI ( uri ));
c . connect ();
}
}
要查看我们项目的演示,您可以使用heimdallr /src/main/web
中现成的 websocket 连接的 html 文件。
基本上遵循Scala 风格指南。