云服务器搭建高可用keepalived+nginx+emqx集群


最近在搞服务器搭建keepalived+nginx+emqx高可用集群,在这里我分享一下我的搭建过程,以及踩到的一些坑,分享给大家,希望大家在搭建过程中顺利完成搭建。
在这里我想从几个方面依次进行搭建,希望能从各处细节上帮助到大家。
QAQ:本文采用的是centos7系统,其他系统请参考官网。配置一切以官网为主,以下仅供参考
官网地址:
emqx:https://mqttx.app/cn
nginx:http://nginx.org/en/download.html
keepalived:https://www.keepalived.org/index.html
此处为了大家方便,为大家提供了nginx+keepalived安装包的百度网盘链接:
链接:https://pan.baidu.com/s/1Ats1kAI91W8avquY4ZVYNw
提取码:jhu0
链接过期可以联系博主QQ:2421304206,搭建过程中遇到问题也可随时打扰,大家一起讨论。

一、高可用emqx集群搭建

1 单机搭建emqx

首先,我们参考一下官网搭建方法:
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

2 配置认证和鉴权插件

配置基于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

3 搭建emqx集群

首先,让我们看一下官网搭建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 = emqx1@192.168.85.100,emqx2@192.168.85.101,emqx3@192.168.85.102
 
#节点名
node.name = emqx1@192.168.85.100

二号节点:

#集群发现模式,静态发现,启动后不用输加入集群命令
cluster.discovery = static 
 
#集群列表,配合上面static发现策略使用
cluster.static.seeds = emqx1@192.168.85.100,emqx2@192.168.85.101,emqx3@192.168.85.102
 
#节点名
node.name = emqx2@192.168.85.101

三号节点:

#集群发现模式,静态发现,启动后不用输加入集群命令
cluster.discovery = static 
 
#集群列表,配合上面static发现策略使用
cluster.static.seeds = emqx1@192.168.85.100,emqx2@192.168.85.101,emqx3@192.168.85.102
 
#节点名
node.name = emqx3@192.168.85.102

修改完成后,分别重启三台emqx

emqx restart

查看三台emqx的集群状态

./bin/emqx_ctl cluster status

然后,你会看到
集群状态

此处,emqx集群环境搭建完成。

二、nginx搭建负载均衡

1 nginx下载安装

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模块,该模块默认不会自动安装,需要我们手动配置,以上过程已经完成。

2 配置nginx

接下来我们要对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)

三、Keepalived + Nginx 实现高可用负载均衡

1 配置nginx测试环境

将我们剩余的两台服务器按上述过程安装配置好nginx(注意修改80端口的监听地址),同时分别修改三台nginx的首页内容:

vim /usr/local/nginx/html/index.html

192.168.85.100修改为:
<h1>Welcome to nginx! 100</h1>

192.168.85.101修改为:
<h1>Welcome to nginx! 101</h1>

192.168.85.102修改为:
<h1>Welcome to nginx! 102</h1>

此处,我们最好将配置好的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时,会出现三个不同的界面。

2 安装keepalived

官网下载地址: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 {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
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 {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
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

访问高可用虚拟 VIP :80 显示如下:
在这里插入图片描述

关闭MASTER的keepalived和nginx(注意顺序,先关闭keepalived)
此时显示如下:
在这里插入图片描述
搭建成功!
注意:云服务器的高可用虚拟 VIP(HAVIP)需要申请,申请下来的HAVIP属于内网IP,需要绑定弹性公网IP才能使用。

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值