Keeper
分布式 WebSocket 服务器。
注意事项
- IO 线程和业务线程分离:对于小业务,依旧放到 worker 线程中处理,对于需要和中间件交互的丢到业务线程池处理,避免 worker 阻塞。
- WebSocket 握手阶段支持参数列表。
插件
本服务功能插件化。
集群
project.plugin-config.enableCluster
属性决定是否启用 集群
模块。
project:
plugin-config:
enableCluster: true
如果启用集群模块,多个服务器将通过消息中间件同步消息,要求必须配置消息中间件。
用户
project.plugin-config.enableUser
属性决定是否启用 用户
模块。
project:
plugin-config:
enableUser: true
group
project.plugin-config.enableGroup
属性决定是否启用 群组
模块。
project:
plugin-config:
enableGroup: true
如果启用群组模块,则默认启用用户模块;否则以单机模式运行。
hearbeat
project.plugin-config.enableHearBeat
属性决定是否启用 心跳检测
模块,project.plugin-config.hearBeatCycle
控制心跳周期间隔时长,单位 s/秒。
project:
plugin-config:
enableHearBeat: false
hearBeatCycle: 15
eventloop
project.plugin-config.enableEventLoop
属性决定是否启用 事件周期处理
模块,project.plugin-config.eventLoopCycle
控制事件处理周期间隔时长,单位 s/秒。
project:
plugin-config:
enableEventLoop: false
eventLoopCycle: 15
环境配置需求
ulimit -n
Linux 对每个进程打开的文件句柄数量做了限制,如果超出:报错 "Too many open file"。
需要调大,如 65535,根据应用实际情况进一步调整。
堆内存
指定最小和最大堆大小,而且为了防止垃圾收集器在最小、最大之间收缩堆而产生额外的时间,通常把最大、最小设置为相同的值。
-Xms12G -Xmx12G
堆外内存
DirectByteBuffer 对象的回收需要依赖 Old GC 或者 Full GC 才能触发清理,我们需要通过 JVM 参数 -XX:MaxDirectMemorySize
指定堆外内存的上限大小,当堆外内存的大小超过该阈值时, 就会触发一次 Full GC 进行清理回收。
-XX:MaxDirectMemorySize=4G
一定要配置:-Xms、-Xmx 、-XX:MaxDirectMemorySize,它们的和不能超过 docker 的最大内存,否则当 docker 内存占满了会被 OOM kill。
G1
前台应用推荐使用 G1,G1 比 CMS 更适合大内存的垃圾收集。
-XX:+UseG1GC
使用 G1 时,不要使用 -Xmn、-XX:NewRatio 等其他相关显式设置年轻代大小的参数,它们会覆盖暂停时间的指标。
部署
Nginx 代理
location / {
proxy_pass http://webscoket;
proxy_set_header Host $host:$server_port;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
用 Nginx 反向代理某个业务,发现平均 1 分钟左右,就会出现 WebSocket 连接中断。 产生原因:Nginx 等待第一次通讯和第二次通讯的时间差,超过了它设定的最大等待时间,简单来说就是超时!
解决方法 1:
其实只要配置 nginx.conf 的对应 localhost 里面的这几个参数就好。
- proxy_connect_timeout;
- proxy_read_timeout;
- proxy_send_timeout;
http {
server {
location / {
root html;
index index.html index.htm;
proxy_pass http://webscoket;
proxy_http_version 1.1;
proxy_connect_timeout 4s; #配置点1
proxy_read_timeout 60s; #配置点2,如果没效,可以考虑这个时间配置长一点
proxy_send_timeout 12s; #配置点3
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
}
}
解决方法 2:
发心跳包,原理就是在有效地再读时间内进行通讯,重新刷新再读时间
proxy_read_timeout
这个参数是服务器对你等待最大的时间,也就是说当你 WebSocket 使用 Nginx 转发的时候,proxy_read_timeout
时间内没有通讯, 依然是会断开的,设置时间内有心跳或者有通信的话,是可以保持连接不中断的。