前言
最近负责的一个项目需要使用 WebSocket 做前后端通信,我使用了Spring提供支持的STOMP协议,它可以解决 WebSocket 消息的语义化和集群状态下各集群节点之间消息共享的问题,例如用户连接了机器 A,但是机器 B需要知道该用户的在线状态和向这个用户推送消息。这是WebSocket集群状态下必然要面对的问题。
传统的做法是使用分布式session、redis或者通过消息队列来自己实现这些功能的支持。其实,Spring已经为我们提供了相关的功能。
开启这个功能,我们需要一个中继(relay),理论上任何实现STOMP协议的消息队列都可以做为中继,常用的是RabbitMQ和ActiveMQ。我选了 RabbitMQ。
在搭建 RabbitMQ 的时候,我们会遇到以下几个问题:
- erlang 运行时环境。RabbitMQ 是 erlang 写的,而且对版本有所要求,网上找的很多教程会出现erlang老是安装不上或者版本不对的问题。
- 非root用户启动。RabbitMQ安装完之后直接执行命令启动,会自动以rabbitmq用户启动进程,而使用该用户需要root权限
- 集群搭建。服务需要高可用,因此我们需要一个rabbitmq集群来支持。
下面是我摸索、使用并总结的安装和配置的完整教程,转载请注明出处:
安装包下载
erlang
从CentOS7/6无依赖的erlang GitHub release 页面中下载安装包:
CentOs6下载 erlang-21.2.2-1.el6.x86_64.rpm
CentOs7下载 erlang-21.2.2-1.el7.centos.x86_64.rpm
签名key文件
从 GitHub release 页面中下载 rabbitmq-release-signing-key.asc
rabbitmq rpm安装包
在 rabbitmq-server 的 GitHub release 页面中选择合适的版本并选择适合的安装包,当前最新的release版本是3.7.9 (2019年1月),则:
CentOs6下载 rabbitmq-server-3.7.9-1.el6.noarch.rpm
CentOs7下载 rabbitmq-server-3.7.9-1.el7.noarch.rpm
安装
安装包准备好之后,我们来安装(yum命令需要root权限)
# 安装 erlang
rpm -ivh erlang-21.1.4-1.el6.x86_64.rpm
# 导入签名
rpm --import rabbitmq-release-signing-key.asc
# 安装 rabbitmq
yum install -y rabbitmq-server-3.7.9-1.el6.noarch.rpm
如果在 install 的时候报下面的异常
- groupadd: cannot open /etc/group
- useradd: cannot open /etc/passwd
- useradd: cannot open /etc/shadow
则对应地执行这三条命令然后再 install 即可
chattr -i /etc/group
chattr -i /etc/passwd
chattr -i /etc/shadow
配置
管理插件
rabbitmq-plugins enable rabbitmq_management
开始管理插件后可以登录 http://localhost:15672 来管理rabbitmq, 默认账号密码都为 guest,只支持本地登录
STOMP 插件
rabbitmq-plugins enable rabbitmq_stomp
添加用户
格式: rabbitmqctl add_user <user> <password>
示例: rabbitmqctl add_user test Passw0rd
添加vhost
格式: rabbitmqctl add_vhost <hostname>
示例: rabbitmqctl add_vhost /wxkf
用户授权
角色
格式: rabbitmqctl set_user_tags <user> <role>
示例: rabbitmqctl set_user_tags test administrator
vhost授权
格式: rabbitmqctl set_permissions [-p <vhostpath>] <user> <conf> <write> <read>
示例: rabbitmqctl set_permissions -p /wxkf test ".*" ".*" ".*"
非 root 权限启动 rabbitmq
安装完成之后 rabbitmq 会在 /usr/sbin/ 目录下加入所需要的命令,如 rabbitmq-server,默认会以rabbitmq用户启动,而使用该用户需要root权限。但是我们在生产机器上不可能一直使用 root,因此使用普通用户启动 rabbitmq 非常有必要。
只需要两步就可以实现
- 删除 /usr/sbin/rabbitmq*
rm -f /usr/sbin/rabbitmq*
- 添加软链
# 注意:rabbitmq_server-3.7.9 换成你安装的对应版本
ln -s /usr/lib/rabbitmq/lib/rabbitmq_server-3.7.9/sbin/rabbitmqctl /usr/sbin/rabbitmqctl
ln -s /usr/lib/rabbitmq/lib/rabbitmq_server-3.7.9/sbin/rabbitmq-env /usr/sbin/rabbitmq-env
ln -s /usr/lib/rabbitmq/lib/rabbitmq_server-3.7.9/sbin/rabbitmq-server /usr/sbin/rabbitmq-server
ln -s /usr/lib/rabbitmq/lib/rabbitmq_server-3.7.9/sbin/rabbitmq-defaults /usr/sbin/rabbitmq-defaults
ln -s /usr/lib/rabbitmq/lib/rabbitmq_server-3.7.9/sbin/rabbitmq-diagnostics /usr/sbin/rabbitmq-diagnostics
ln -s /usr/lib/rabbitmq/lib/rabbitmq_server-3.7.9/sbin/rabbitmq-plugins /usr/sbin/rabbitmq-plugins
然后执行 rabbitmq 相关的命令就会以当前用户执行了
集群搭建
.erlang.cookie 文件
将第一台RabbitMQ的 ~/.erlang.cookie
文件复制替换掉其他的机器相同路径下的文件,以确保各个节点的cookie文件使用的是同一个值,节点之间通过cookie确定相互是否可通信。
注意:如果是直接修改cookie文件的内容,需要授权。 .erlang.cookie 文件默认权限是 400,即只有owner才有只读权限,执行 chmod +w .erlang.cookie
添加写权限,改完之后执行 chmod -w .erlang.cookie
改回原来的权限即可。
配置各节点的hosts文件
sudo vim /etc/hosts
# 格式:ip 节点名
xxx.xxx.xxx.xxx rmq-broker-test-1
xxx.xxx.xxx.xxx rmq-broker-test-2
xxx.xxx.xxx.xxx rmq-broker-test-3
注意:节点名称为机器的 hostname,可以通过执行 hostname 命令查看(如果全称包含 . 会被截断,只取 . 前面的部分,如hostname 为 bhj-185-73.os.org 则节点名称为bhj-185-73)。
组成集群
- 先启动任意一个节点,以 node1 为例,在 node1 机器上执行
rabbit-server -detached
- 再启动其他机器并加入集群,以 node2 为例,在 node2 机器上执行
# 启动 rabbit-server
rabbit-server -detached
# 停止rabbitmq服务(这命令只是停止对外服务,进程还在)
rabbitmqctl stop_app
# 加入集群,集群格式为 [email protected]节点名
rabbitmqctl join_cluster [email protected]
# 开启rabbitmq服务
rabbitmqctl start_app
集群搭建完成之后可以通过web管理界面查看集群集群信息,地址为任意节点的ip,端口号为 15672,如 http://locahost:15672
集群部分参考:CentOs7.3 搭建 RabbitMQ 3.6 Cluster 集群服务与使用