首先,我们参考一下官网搭建方法:
https://docs.emqx.cn/broker/v4.3/getting-started/install.html
接下来,我们来搭建emqx
安装方式:
1.1 shell脚本安装
curl https://repos.emqx.io/install_emqx.sh | bash
1.2 yum安装
安装所需依赖包
yum install -y yum-utils device-mapper-persistent-data lvm2
使用以下命令设置稳定存储库
yum-config-manager --add-repo https://repos.emqx.io/emqx-ce/redhat/centos/7/emqx-ce.repo
安装最新版本的 EMQ X Broker
yum install emqx
1.3 启动与运行
启动命令:
emqx start
查看emqx状态:
emqx_ctl status
停止emqx
emqx stop
卸载emqx
yum remove emqx
配置基于MySQL的认证和acl
这里我们使用的是官方提供的插件emqx_auth_mysql
编辑配置文件
vim /etc/emqx/plugins/emqx_auth_mysql.conf
配置文件需要修改的内容
## 服务器地址
auth.mysql.server = 127.0.0.1(你使用的数据库的IP地址):3306
## mysql用户名
auth.mysql.username = root
## 密码
auth.mysql.password = root
## 数据库名
auth.mysql.database = mqtt
## 认真比对以下认证sql是否和数据库一致
auth.mysql.auth_query = select password_hash as password from mqtt_user where username = '%u' limit 1
## 对比以下acl鉴权sql是否和数据库信息一致(默认无需修改)
auth.mysql.acl_query = select allow, ipaddr, username, clientid, access, topic from mqtt_acl where ipaddr = '%a' or username = '%u' or username = '$all' or clientid = '%c'
建立数据库mqtt,导入以下脚本
CREATE TABLE `mqtt_user` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(100) DEFAULT NULL,
`password` varchar(100) DEFAULT NULL,
`salt` varchar(35) DEFAULT NULL,
`is_superuser` tinyint(1) DEFAULT 0,
`created` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `mqtt_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 添加一个默认的连接账号
INSERT INTO `mqtt_user` ( `username`, `password`, `salt`, `is_superuser`)
VALUES
('root', 'root', NULL, 0);
CREATE TABLE `mqtt_acl` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`allow` int(1) DEFAULT 1 COMMENT '0: deny, 1: allow',
`ipaddr` varchar(60) DEFAULT NULL COMMENT 'IpAddress',
`username` varchar(100) DEFAULT NULL COMMENT 'Username',
`clientid` varchar(100) DEFAULT NULL COMMENT 'ClientId',
`access` int(2) NOT NULL COMMENT '1: subscribe, 2: publish, 3: pubsub',
`topic` varchar(100) NOT NULL DEFAULT '' COMMENT 'Topic Filter',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 所有用户不可以订阅系统主题
INSERT INTO mqtt_acl (allow, ipaddr, username, clientid, access, topic) VALUES (0, NULL, '$all', NULL, 1, '$SYS/#');
-- 允许 本机 上的客户端订阅系统主题
INSERT INTO mqtt_acl (allow, ipaddr, username, clientid, access, topic) VALUES (1, '127.0.0.1', NULL, NULL, 1, '$SYS/#');
到目前位置,我们需要去登陆控制台启动mysql鉴权插件
控制台:
http://(你的emqx所在的IP地址):18083/plugins
默认账号:admin 密码:public
首先,让我们看一下官网搭建emqx分布式集群:
https://docs.emqx.cn/broker/v4.3/getting-started/cluster.html
本次为了方便,我们以static策略进行搭建,有兴趣的小伙伴可以试试其他的。
首先,我们需要三台云服务器,并安装好emqx。
(此处我用的三台虚拟机,云服务器建议使用内网IP搭建)
接下来,我们编辑三台emqx的配置文件
vim /etc/emqx/emqx.conf
将三台服务器的配置文件分别修改为
一号节点:
#集群发现模式,静态发现,启动后不用输加入集群命令
cluster.discovery = static
#集群列表,配合上面static发现策略使用
cluster.static.seeds = [email protected],[email protected],[email protected]
#节点名
node.name = [email protected]
二号节点:
#集群发现模式,静态发现,启动后不用输加入集群命令
cluster.discovery = static
#集群列表,配合上面static发现策略使用
cluster.static.seeds = [email protected],[email protected],[email protected]
#节点名
node.name = [email protected]
三号节点:
#集群发现模式,静态发现,启动后不用输加入集群命令
cluster.discovery = static
#集群列表,配合上面static发现策略使用
cluster.static.seeds = [email protected],[email protected],[email protected]
#节点名
node.name = [email protected]
修改完成后,分别重启三台emqx
emqx restart
查看三台emqx的集群状态
./bin/emqx_ctl cluster status
此处,emqx集群环境搭建完成。
nginx官网下载地址:
http://nginx.org/en/download.html
以下是我安装的过程,大家可以参考一下:
# 安装gcc,编译NGINX依赖gcc环境
yum -y install gcc
# 安装pcre、pcre-devel,PCRE(Perl Compatible Regular Expressions) 是一个Perl库,包括 perl 兼容的正则表达式库。
# nginx 的 http 模块依赖 pcre 来解析正则表达式,pcre-devel 是基于 pcre 开发的一个二次开发库。nginx也需要此库
yum install -y pcre pcre-devel
# 安装zlib,zlib库提供了很多种压缩和解压缩方式,nginx使用zlib对http包的内容进行gzip
yum install -y zlib zlib-devel
# 安装openssl,NGINX要支持https依赖SSL协议
yum install -y openssl openssl-devel
cd /usr/local
wget http://nginx.org/download/nginx-1.18.0.tar.gz
# 解压安装包
tar -zxvf nginx-1.18.0.tar.gz
cd nginx-1.18.0
# 编译NGINX,编译时可以制定初始化模块的参数
sudo ./configure --with-http_stub_status_module --with-http_ssl_module --with-stream --with-stream_ssl_module
sudo make
# 安装
make install
# NGINX启停命令
cd /usr/local/nginx/sbin/
# 检查配置文件是否正确
./nginx -t
# 启动NGINX
./nginx
# 停止NGINX
./nginx -s stop
# 重新加载NGINX配置文件
./nginx -s reload
NGINX使用stream模块进行SSL连接时,需要安装ngx_stream_ssl_module模块,该模块默认不会自动安装,需要我们手动配置,以上过程已经完成。
接下来我们要对nginx进行配置,以下是我的nginx配置文件,供大家参考
vim /usr/local/nginx/conf/nginx.conf
# 指定Nginx Worker进程运行用户以及用户组
user root;
# 指定了Nginx要开启的进程数。每个Nginx进程平均耗费10M~12M内存。
worker_processes auto;
# 定义全局错误日志文件。日志输出级别有debug、info、notice、warn、error、crit,其中debug输出日志最为最详细,crit输出日志最少。
error_log logs/error.log warn;
# 用来指定进程pid的存储文件位置
pid logs/nginx.pid;
# 必选配置,配置nginx服务器或与用户的网络连接
events {
# 最大连接数,默认为512
worker_connections 1024;
# 设置网路连接序列化,防止惊群现象发生,默认为on
#accept_mutex on;
# 设置一个进程是否同时接受多个网络连接,默认为off
#multi_accept off;
}
# 配置tcp 要使用nginx的stream服务节点
stream {
# mqtt tcp连接配置
upstream emqx_broker_tcp {
#zone tcp_servers 64k;
# 如果emqx broker是集群部署的,必须按照mqtt客户端的ip分发到集群中指定的emqx broker服务器保持长连接
hash $remote_addr;
server 192.168.85.100:1883 max_fails=2 fail_timeout=10s weight=1;
server 192.168.85.101:1883 max_fails=2 fail_timeout=10s weight=1;
server 192.168.85.102:1883 max_fails=2 fail_timeout=10s weight=1;
}
# mqtt tcp连接
server {
listen 8888; #监听端口
proxy_connect_timeout 10s;
proxy_timeout 10s;
#反向代理地址
proxy_pass emqx_broker_tcp;
proxy_buffer_size 3M;
tcp_nodelay on;
}
}
http {
# 文件扩展名与文件类型映射表
include mime.types;
# 默认文件类型,默认为text/plain,这里设定默认类型为二进制流
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
log_format healthd '$msec"$uri"'
'$status"$request_time"$upstream_response_time"'
'$http_x_forwarded_for';
access_log logs/access.log main;
# 允许sendfile方式传输文件,默认为off,可以配置在http块,server块,location块
sendfile on;
#tcp_nopush on;
# 连接超时时间,默认为75s,可以配置在http,server,location块
keepalive_timeout 65;
# 开启GZIP压缩,实时压缩输出数据流
#gzip on;
# mqtt websocket连接负载均衡设置
upstream emqx_broker_websocket {
#zone tcp_servers 64k;
# 如果emqx broker是集群部署的,必须按照mqtt客户端的ip分发到集群中指定的emqx broker服务器保持长连接
hash $remote_addr;
server 192.168.85.100:8083 max_fails=2 fail_timeout=10s weight=1;
server 192.168.85.101:8083 max_fails=2 fail_timeout=10s weight=1;
server 192.168.85.102:8083 max_fails=2 fail_timeout=10s weight=1;
}
# 指定主机和端口
server {
# 监听端口
listen 80;
# #监听地址
server_name 192.168.85.100;
# 实现URL重定向
#rewrite ^(.*) https://$server_name$1 permanent; #http 转 https
access_log logs/access_122.log main;
error_log logs/error_122.log error;
# 请求的URL过滤,支持正则匹配,~为区分大小写,~*为不区分大小写
location /mqtt {
#反向代理地址
proxy_pass http://emqx_broker_websocket;
proxy_redirect off;
proxy_connect_timeout 60s;
proxy_send_timeout 3600s;
# websocket连接有效时间,在该时间内没有数据交互的话websocket连接会自动断开
proxy_read_timeout 3600s;
proxy_http_version 1.1;
# websocket连接的Upgrade必须设置为WebSocket,表示在取得服务器响应之后,使用HTTP升级将HTTP协议转换(升级)为WebSocket协议
proxy_set_header Upgrade $http_upgrade;
# websocket 的Connection必须设置为Upgrade,表示客户端希望连接升级
proxy_set_header Connection "Upgrade";
}
}
}
测试 Nginx 是否安装成功:
# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
启动nginx。
此时我们打开控制台,进入websocket,进行连接测试。
如图所示,连接成功。(云服务器在配置过程中建议使用内网IP)
将我们剩余的两台服务器按上述过程安装配置好nginx(注意修改80端口的监听地址),同时分别修改三台nginx的首页内容:
vim /usr/local/nginx/html/index.html
192.168.85.100修改为:
Welcome to nginx! 100
192.168.85.101修改为:
Welcome to nginx! 101
192.168.85.102修改为:
Welcome to nginx! 102
此处,我们最好将配置好的nginx设置为开机自动启动:
# 进入到/lib/systemd/system/目录
cd /lib/systemd/system/
# 创建nginx.service文件,并编辑
vim nginx.service
# 以下为编辑内容
[Unit]
Description=nginx service
After=network.target
[Service]
Type=forking
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s quit
PrivateTmp=true
[Install]
WantedBy=multi-user.target
# 加入开机自启动
systemctl enable nginx
# 操作命令
systemctl start nginx.service 启动nginx服务
systemctl stop nginx.service 停止服务
systemctl restart nginx.service 重新启动服务
systemctl list-units --type=service 查看所有已启动的服务
systemctl status nginx.service 查看服务当前状态
systemctl enable nginx.service 设置开机自启动
systemctl disable nginx.service 停止开机自启动
测试一下,当我们分别访问三台服务器的nginx时,会出现三个不同的界面。
官网下载地址:https://www.keepalived.org/download.html。
下载完成之后上传到三台服务器上,
在三台服务器上安装keepalived:
cd /usr/local/src
tar -zxvf keepalived-1.2.18.tar.gz
cd keepalived-1.2.18
./configure --prefix=/usr/local/keepalived
make && make install
此时安装未将keepalived安装到系统的默认安装路径,我们需要做以下配置
mkdir /etc/keepalived
cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/
复制 keepalived 服务脚本到默认的地址
cp /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/
cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/
ln -s /usr/local/sbin/keepalived /usr/sbin/
ln -s /usr/local/keepalived/sbin/keepalived /sbin/
修改 Keepalived 配置文件
此处进行说明:我本次使用192.168.85.100作为我的MASTER,其余两台为BACKUP
MASTER配置文件:
! Configuration File for keepalived
global_defs {
notification_email {
[email protected]
[email protected]
[email protected]
}
notification_email_from [email protected]
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id ziliang1
vrrp_skip_check_adv_addr
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_script chk_nginx {
script "/etc/keepalived/nginx_check.sh" ## 检测 nginx 状态的脚本路径
interval 2 ## 检测时间间隔
weight -10 ## 如果条件成立,权重-20
}
vrrp_instance VI_1 {
#注意主备参数选择
state MASTER # 设置初始状态为“主“
interface eth0 # 设置绑定 VIP 的网卡 例如 eth0
virtual_router_id 33 # 配置集群 virtual_router_id 值
nopreempt # 设置非抢占模式
preempt_delay 10
priority 100 # 设置优先级,值越大优先级越高
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
track_script {
chk_nginx ## 执行 Nginx 监控的服务
}
unicast_src_ip 192.168.85.100 # 设置本机内网 IP 地址
unicast_peer {
192.168.85.101
192.168.85.102 # 对端设备的 IP 地址
}
virtual_ipaddress {
192.168.85.100 # 设置高可用虚拟 VIP
}
notify_master "/etc/keepalived/nginx_check.sh MASTER"
notify_backup "/etc/keepalived/nginx_check.sh BACKUP"
notify_fault "/etc/keepalived/nginx_check.sh FAULT"
notify_stop "/etc/keepalived/nginx_check.sh STOP"
garp_master_delay 1 # 设置当切为主状态后多久更新 ARP 缓存
garp_master_refresh 5 # 设置主节点发送ARP报文的时间间隔
track_interface {
eth0 # 使用绑定 VIP 的网卡 例如 eth0
}
}
BACKUP 配置文件(一台为例):
! Configuration File for keepalived
global_defs {
notification_email {
[email protected]
[email protected]
[email protected]
}
notification_email_from [email protected]
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id ziliang2
vrrp_skip_check_adv_addr
vrrp_garp_interval 0.001
vrrp_gna_interval 0.001
}
vrrp_script chk_nginx {
script "/etc/keepalived/nginx_check.sh" ## 检测 nginx 状态的脚本路径
interval 2 ## 检测时间间隔
weight -10 ## 如果条件成立,权重-20
}
vrrp_instance VI_1 {
#注意主备参数选择
state BACKUP # 设置初始状态为“备“
interface eth0 # 设置绑定 VIP 的网卡 例如 eth0
virtual_router_id 33 # 配置集群 virtual_router_id 值
nopreempt # 设置非抢占模式
preempt_delay 10
priority 90 # 设置优先级,值越大优先级越高
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
track_script {
chk_nginx ## 执行 Nginx 监控的服务
}
unicast_src_ip 192.168.85.101 # 设置本机内网 IP 地址
unicast_peer {
192.168.85.100
192.168.85.102 # 对端设备的 IP 地址
}
virtual_ipaddress {
192.168.85.100 # 设置高可用虚拟 VIP
}
notify_master "/etc/keepalived/nginx_check.sh MASTER"
notify_backup "/etc/keepalived/nginx_check.sh BACKUP"
notify_fault "/etc/keepalived/nginx_check.sh FAULT"
notify_stop "/etc/keepalived/nginx_check.sh STOP"
garp_master_delay 1 # 设置当切为主状态后多久更新 ARP 缓存
garp_master_refresh 5 # 设置主节点发送ARP报文的时间间隔
track_interface {
eth0 # 使用绑定 VIP 的网卡 例如 eth0
}
}
编写 Nginx 状态检测脚本
vim /etc/keepalived/nginx_check.sh
#!/bin/bash
A=`ps -C nginx –no-header |wc -l`
if [ $A -eq 0 ];then
/usr/local/nginx/sbin/nginx
sleep 2
if [ `ps -C nginx --no-header |wc -l` -eq 0 ];then
killall keepalived
fi
fi
并给脚本附加权限
chmod +x /etc/keepalived/nginx_check.sh
启动keepalived并进行测试
service keepalived start
关闭MASTER的keepalived和nginx(注意顺序,先关闭keepalived)
此时显示如下:
搭建成功!
注意:云服务器的高可用虚拟 VIP(HAVIP)需要申请,申请下来的HAVIP属于内网IP,需要绑定弹性公网IP才能使用。