阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

Nginx反向代理,负载均衡,Redis Session共享,Keepalived高可用

152次阅读
没有评论

共计 20653 个字符,预计需要花费 52 分钟才能阅读完成。

使用的资源:

nginx 主服务器一台,nginx 备服务器一台,使用 keepalived 进行宕机切换。
tomcat 服务器两台,由 nginx 进行反向代理和负载均衡,此处可搭建服务器集群。
redis 服务器一台,用于 session 的分离共享。
nginx 主服务器:192.168.50.133
nginx 备服务器:192.168.50.135
tomcat 项目服务器 1:192.168.50.137
tomcat 项目服务器 2:192.168.50.139
redis 服务器:192.168.50.140
注意访问时需要配置防火墙规则,或者关闭防火墙

首先进行的通用安装:

总的需要模拟五台服务器,使用 VMware,全部使用 CentOS 6.5 64 位,五台服务器全部安装 jdk,我使用的是 jdk1.8.

1. 安装 VMware 虚拟机,安装 Linux 系统,此处使用 CentOS 6.5 64 位,安装 Linux 命令行工具,上传文件工具,此处使用 SecureCRT,SecureFX。安装教程不再赘述。

Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

SecureCRT 连接 VirtualBox 中的 Ubuntu - 端口转发  http://www.linuxidc.com/Linux/2015-12/126258.htm

用 SecureCRT 实现 WIN7 与 Linux 双向通信的问题及文件互传问题解决 http://www.linuxidc.com/Linux/2014-08/105412.htm

如何使用 SecureCRT6.6.2 通过 SSH 方式登录 Ubuntu 系统 http://www.linuxidc.com/Linux/2011-03/33024p4.htm

SecureCRT 连接 Ubuntu http://www.linuxidc.com/Linux/2013-06/85824.htm

Ubuntu 12.04 + 虚拟机 VMware 9 + Secure CRT + EditPlus 本地 C ++ 开发环境搭建 http://www.linuxidc.com/Linux/2013-05/84820.htm

利用 SecureCRT 在 Linux 与 Windows 之间传输文件 http://www.linuxidc.com/Linux/2014-08/105413.htm

Ubuntu 14.10 安装 SecureCRT 7.3 http://www.linuxidc.com/Linux/2014-10/108709.htm

SecureCRT 的详细介绍:请点这里
SecureCRT 的下载地址:请点这里

2. 在 Linux 上安装 jdk:

安装 jdk:卸载 openjdk 版本,上传解压 jdk,配置环境变量 —- 参考:

CentOS7.2 安装 JDK1.7 http://www.linuxidc.com/Linux/2016-11/137398.htm

CentOS 搭建 JDK 环境  http://www.linuxidc.com/Linux/2015-06/118879.htm 

Ubuntu 14.04 安装 JDK1.8.0_25 与配置环境变量  http://www.linuxidc.com/Linux/2015-01/112030.htm 

Ubuntu 14.04 LTS 安装 Oracle JDK 1.8  http://www.linuxidc.com/Linux/2014-11/109216.htm 

CentOS 6.5 安装 JDK-1.7 详解  http://www.linuxidc.com/Linux/2016-12/138046.htm

CentOS6.3 安装 JDK 和环境配置 http://www.linuxidc.com/Linux/2012-09/70780.htm 

一、Nginx 反向代理与负载均衡:

架构图:

Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

此时需要用到三台服务器,一台 nginx 服务器,两台正式部署项目的服务器:选择的是 192.168.50.133 主 nginx 和 192.168.50.137,192.168.50.139 两台 tomcat 服务器

首先在两台服务器上安装 tomcat:这个也是简单,不多说

安装 tomcat:上传解压即可使用,bin 目录下 startup.sh 启动,shutdown.sh 关闭

配置防火墙端口:vim /etc/sysconfig/iptables 编辑,开放 8080 端口,80 端口等一些常用端口,当然后边有用到一些端口都是需要配置开放的,不建议关闭防火墙

Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

编辑好后 service iptables restart 重新加载防火墙配置

Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

如果是自己测试嫌配置麻烦,关闭防火墙:service iptables stop 重启后防火墙打开,即在此次开机状态下有效,完全关闭再使用 chkconfig iptables off , 即会在重启后也关闭防火墙,注意有时候服务都起了但访问出错,可能就是防火墙问题哦

启动 tomcat 访问:192.168.50.137:8080,192.168.50.139:8080,打开 tomcat 首页即成功。

然后编写测试项目,部署到两台 tomcat 上,eclipse 新建 web 项目,项目名为 testproject,在 webapp 下新建一个 jsp 页面为 index.jsp, 添加如下内容

Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

将项目中 web.xml 中的访问顺序 <welcome-file>index.jsp</welcome-file> 上移到第一个访问

然后右键导出为 war 包,testproject.war,将该 war 包上传到两台服务器的 tomcat 的 webapps 中

Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

 然后修改 tomcat 的 server.xml 文件,在 tomcat conf 目录中:可以使用 notepad++ 的插件 NppFTP 直接连上 linux,然后使用 notepad++ 修改文件哦,保存记得使用 UTF- 8 无 BOM 格式,具体去百度吧,哈哈

修改 Engine 标签中,添加 jvmRoute,用于标识 nginx 访问的是哪个服务器 tomcat,137 服务器标识为 137Server1,139 服务器标识为 139Server2

Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

在两台 tomcat 的 server.xml 文件,Host 标签中添加:<Context path=”” docBase=”testproject”/>,path 标识访问路径,docBase 为项目名,表示访问项目

Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

此时,重新启动 tomcat,访问 192.168.50.137:8080,192.168.50.139:8080, 显示 index.jsp 内容:两台服务器访问显示如下

 Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

至此,两台 tomcat 服务器搭建完成。

在 nginx 主机 192.168.50.133 上安装 nginx:

 先使用 yum 命令安装 gcc,安装 pcre,zlib,openssl:

1
2
3
4
yum install -y gcc
yum install -y pcre pcre-devel
yum install -y zlib zlib-devel
yum install -y openssl openssl-devel

 在 /usr/local/ 目录下新建 nginx-src 目录,将 nginx-1.8.0.tar.gz 放到此处,解压 

1
tar -zxvf nginx-1.8.0.tar.gz

进入解压后目录

Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

依次执行命令:

1
2
3
4
5
./configure
 
make
 
mkae install

 此时 nginx 安装完毕,安装目录是 /usr/local/nginx,nginx 默认占用 80 端口

Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

其中,sbin 目录为 nginx 执行命令,conf 目录下的 nginx.conf 为默认加载的配置文件

启动 nginx:

1
./sbin/nginx

关闭 nginx:

1
./sbin/nginx -s stop

 启动 nginx 后访问 192.168.50.133:80 即可访问 nginx:显示 nginx 欢迎页

Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

 至此,nginx 安装完毕。

3. 反向代理与负载均衡配置

现有两台服务器,一台为 192.168.50.137,一台为 192.168.50.139,服务器上各有一台 tomcat,端口均为 8080,在 192.168.50.133 上有 nginx,经过配置 nginx,当访问 192.168.50.133:80 时,即可访问 192.168.50.137:8080,192.168.50.139:8080 中随机一台,此时 192.168.50.133:80 被 nginx 监听,当有请求时,代理到 192.168.50.137:8080,192.168.50.139:8080 随机一台即可,即为 nginx 反向代理功能,同时此时可以通过 nginx 将请求进行转发,保证了一个入口,将所有请求转发到两台服务器上也减轻了任何一台的负载压力,当有大量请求时,可以搭建大量服务器,在入口代理服务器上使用 nginx 进行转发,即是负载均衡功能。

配置即是配置 nginx 安装目录中 conf 目录下的 nginx.conf 文件即可:具体配置如下,重点是红色部分

#Nginx 所用用户和组
#user  niumd niumd;

#工作的子进程数量(通常等于 CPU 数量或者 2 倍于 CPU)worker_processes  2;

#错误日志存放路径
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
error_log  logs/error.log  info;

#指定 pid 存放文件
pid        logs/nginx.pid;

events {
    #使用网络 IO 模型 linux 建议 epoll,FreeBSD 建议采用 kqueue
    #use epoll;
    
    #允许最大连接数
    worker_connections  1024;
}

http {
    include       mime.types;
    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"';

    #access_log  off;
    access_log  logs/access.log;

    client_header_timeout  3m;
    client_body_timeout    3m;
    send_timeout           3m;
 
    client_header_buffer_size    1k;
    large_client_header_buffers  4 4k;

    sendfile        on;
    tcp_nopush      on;
    tcp_nodelay     on;

    #fastcgi_intercept_errors on; 
   
    error_page 404  /404.html;

    #keepalive_timeout  75 20;

    gzip                 on;
    gzip_min_length      1000;
    gzip_types           text/plain text/css application/x-Javascript;

    #配置被代理的服务器
    upstream blank {
        #ip_hash;
        server 192.168.50.137:8080;
        server 192.168.50.139:8080;
    }

    server {
            #nginx 监听 80 端口,请求该端口时转发到真实目标
            listen       80;
            #配置访问域名
            server_name  192.168.11.133;                  
        
            location / {
                #这里配置代理是指上面定义的两个被代理目标,blank 名字必须一致
                proxy_pass http://blank;
                
                #proxy_redirect          off;
                # 非 80 端口使用,目的是将代理服务器收到的用户的信息传到真实服务器上,我也不是很理解
                proxy_set_header        Host $host;
                proxy_set_header        X-Real-IP $remote_addr;
                proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
                client_max_body_size    10m;
                client_body_buffer_size 128k;
                proxy_connect_timeout   300;
                proxy_send_timeout      300;
                proxy_read_timeout      300;
                proxy_buffer_size       4k;
                proxy_buffers           4 32k;
                proxy_busy_buffers_size 64k;
                proxy_temp_file_write_size 64k;
                add_header Access-Control-Allow-Origin *;
            }
            
            #此处定义 500 502 503 504 的错误页面
            error_page   500 502 503 504  /50x.html;
            #错误页面位置
            location = /50x.html {
            #root 表示路径 html 为 nginx 安装目录中的 html 文件夹
            #位于 /usr/local/nginx/html/ 下
               root   html;
            }        
    }
} 

启动两台 tomcat,重新启动 nginx:

访问 192.168.50.133:80 将会随机访问 192.168.50.137:8080 和 192.168.50.139:8080 其中一台。(问题:每次刷新 nginx 服务器地址 sessionid 会变,session 不能共享。

Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

nginx 轮询策略:

nginx 负载均衡到多台服务器上时,默认采用轮询策略:

常见策略:

1、轮询

每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器 down 掉,能自动剔除。

2、weight
指定轮询几率,weight 和访问比率成正比,用于后端服务器性能不均的情况,数字越大命中率越高。
例如:轮询几率是 2:1
upstream bakend {
server 192.168.0.14 weight=2;
server 192.168.0.15 weight=1;
}

2、ip_hash
每个请求按访问 ip 的 hash 结果分配,这样每个访客固定访问一个后端服务器,可以解决 session 的问题。
例如:
upstream bakend {
ip_hash;
server 192.168.0.14:88;
server 192.168.0.15:80;
}

其他策略可以自行查询学习,nginx 还有很多其他可配置项,静态资源缓存,重定向等,想深入的童鞋请自行学习

nginx 配置详解:http://www.linuxidc.com/Linux/2016-12/138336.htm

实际问题:虽然解决了,但是不是很理解,记录一下

其中 192.168.50.133:80 是有外网映射的,外网 55.125.55.55:5555 映射到 192.168.50.133:80 上,此时使用 55.125.55.55:5555 访问,会映射到 192.168.50.133:80 上,然后会被转发到 192.168.50.137:8080 或 192.168.50.139:8080,但是此时却出现图片,js,css 等静态文件无法访问的情况,通过两种方法解决。

<1>. 映射非 80 端口

让 55.125.55.55:5555 映射 192.168.50.133 的非 80 端口,例如 55.125.55.55:5555 映射 192.168.50.133:5555,然后再在 nginx 配置文件中配置如下,注意红色加大部分:这地方不理解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
........ upstream blank {
        #ip_hash;
        server 192.168.50.137:8080;
        server 192.168.50.139:8080;
    }
 
    server {
        #nginx 监听 5555 端口,请求该端口时转发到真实目标
            listen      5555;
        # 配置访问域名
            server_name  192.168.11.133;             
         
            location / {
        # 这里配置代理是指上面定义的两个被代理目标,blank 名字必须一致
                proxy_pass http://blank;
                 
        #proxy_redirect          off;
        # 非 80 端口使用,目的是将代理服务器收到的用户的信息传到真实服务器上
        proxy_set_header        Host $host:5555;
        proxy_set_header        X-Real-IP $remote_addr;
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        client_max_body_size    10m;
        client_body_buffer_size 128k;
        proxy_connect_timeout  300;
        proxy_send_timeout      300;
        proxy_read_timeout      300;
        proxy_buffer_size      4k;
        proxy_buffers          4 32k;
        proxy_busy_buffers_size 64k;
        proxy_temp_file_write_size 64k;
        add_header Access-Control-Allow-Origin *;
            }........

 此时访问 55.125.55.55:5555,映射到 192.168.50.133:5555 上,然后转发到 192.168.50.137:8080 或 192.168.50.139:8080 上,此时静态文件均能访问。

 <2>. 使用域名在外网服务器上使用 nginx 进行转发

将 55.125.55.55 绑定域名为 test.baidubaidu.com,此时在 55.125.55.55 服务器上使用 nginx,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
........location / {
        # 加入判断,如果域名为 test.baidubaidu.com,转发到192.168.50.133:80,然后再进行转发,注意,此处未进行测试,貌似是这么写的,$hostname 为 nginx 变量,可以获取域名   
        if($hostname = "test.baidubaidu.com" ){
        proxy_pass http://192.168.50.133:80;
        }
                 
        #proxy_redirect          off;
        # 非 80 端口使用,目的是将代理服务器收到的用户的信息传到真实服务器上,我也不是很理解
        proxy_set_header        Host $host;
        proxy_set_header        X-Real-IP $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        client_max_body_size    10m;
        client_body_buffer_size 128k;
        proxy_connect_timeout  300;
        proxy_send_timeout      300;
        proxy_read_timeout      300;
        proxy_buffer_size      4k;
        proxy_buffers          4 32k;
        proxy_busy_buffers_size 64k;
        proxy_temp_file_write_size 64k;
        add_header Access-Control-Allow-Origin *;
            }........

 以上即 nginx 反向代理与负载均衡介绍,经过此次学习,发现 nginx 确实是博大精深,一个配置文件搞得我不要不要的。。。

二、session 共享问题:

由于 nginx 是随机分配请求,假设一个用户登录时访问网站登录时被分配到 192.168.50.137:8080 上,然后进行了登录操作,此时该服务器上就会有该用户登录的 session 信息,然后登陆后重定向到网站首页或个人中心时,此时如果被分配到 192.168.50.139:8080 上,那么这台服务器上没有该用户 session 信息,于是又会变成未登录状态,所以由于 nginx 的负载均衡会导致 session 共享的问题。

解决方法:

1.nginx 提供了 ip_hash 策略,可以保持用户 ip 进行 hash 值计算固定分配到某台服务器上,然后只要是该 ip 则会保持分配到该服务器上,保证用户访问的是同一台服务器,那么 session 问题就不存在了。这也是解决 session 共享的一种方式,也称为黏性 session。但是假设一台 tomcat 服务器挂了的话,那么 session 也会丢失。所以比较好的方案是抽取 session。

2.session 存在 memcache 或者 redis 中,以这种方式来同步 session,把 session 抽取出来,放到内存级数据库里面,解决了 session 共享问题,同时读取速度也是非常之快。

Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

本例中:

Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

Redis 解决 session 共享:

在 redis 服务器 192.168.50.140 上搭建 redis,redis 默认端口为 6379

Redis 搭建:

redis 依赖 gcc,先安装:

1
yum install -y gcc-c++

下载 redis,我使用的是 redis-3.2.1.tar.gz,上传至 linux /usr/local/redis-src/ 中,解压

进入解压后目录 redis-3.2.1,执行 make 命令进行编译

安装到目录 /usr/local/redis

执行:

1
make PREFIX=/usr/local/redis install

安装完成之后将 redis 配置文件拷贝到安装目录下,redis.conf 是 redis 的配置文件,redis.conf 在 redis 源码目录,port 默认 6379。

执行命令:

1
cp /usr/local/redis-src/redis-3.2.1/redis.conf /usr/local/redis/

在 redis 安装目录启动和关闭 redis:

启动:

1
./bin/redis-server ./redis.conf

Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

这种启动方式叫做前端启动,必须保持在当前窗口,如果 ctrl + c 退出,那么 redis 也就退出了,不建议使用

那么后端启动:

首先修改 redis.conf 中 daemonize 的值,打开可以看到默认是 no,修改为 daemonize yes,启动即可。也可以在该配置文件中修改 redis 默认端口 6379 为其他值。

Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

关闭 redis:

1
./bin/redis-cli shutdown

 至此,redis 服务器搭建完成。

 tomcat 与 redis 集成实现 session 共享:

环境为 tomcat7 + jdk1.6 的话:

所有 需要共享 session 的 服务器的 tomcat 中目录下:

lib 目录中添加以下三个 jar 包,注意版本最好一致,不然极容易出现错误,下边的测试是可用的:

Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

conf 目录中 content.xml 中加入:配置 redis 服务

1
2
3
4
5
6
<Valve className="com.radiadesign.catalina.session.RedisSessionHandlerValve"/> 
<Manager className="com.radiadesign.catalina.session.RedisSessionManager"
host="192.168.50.140"
port="6379"
database="0" 
maxInactiveInterval="60" />

环境为 tomcat7 + jdk1.7 或 1.8 的话:

所有 需要共享 session 的 服务器的 tomcat 中目录下:

lib 目录中添加以下三个 jar 包,测试通过:

Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

conf 目录中 content.xml 中加入:配置 redis 服务

1
2
3
4
5
6
<Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" />       
<Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"
host="192.168.50.140" 
port="6379" 
database="0"             
maxInactiveInterval="60"/>

根据我这测试,是 jkd1.8+tomcat7,在 137 和 139 两台 tomcat 中加入 jar 包且进行如上配置:

上传 jar 包

Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

 修改 content.xml

Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

启动 redis 服务,重新启动所有 tomcat,启动 nginx,刷新 nginx 页面, 两台 tomcat 页面可以看到 sessionid 值不变,关闭某台 tomcat,nginx 中 sessionid 不变,说明 session 是共享的。

问题:

有可能此时访问会报错,redis 无法访问,这是由于 redis 的安全机制,默认只有 127.0.0.1 才能访问,在 redis.conf 中可以找到 bind 127.0.0.1,你可以将此 ip 改为访问者 ip,

如果有多个访问者,也可以把 bind 127.0.0.1 注释掉,然后在配置文件中找到 protected-mode,修改 protected-mode yes 改为 protected-mode no 关闭 redis 保护模式即可

详细可以参考这:http://www.linuxidc.com/Linux/2016-12/138335.htm 

经过大牛指点:添加两个注意点:

1. 按照如上配置, 使用 redis 数据库, 放入 session 中的对象必须要实现 java.io.Serializable 接口,使用 memcache 的可以不用实现 Serializable 接口

原因是: 因为 tomcat 里使用的将 session 放置 redis 使用的工具类, 是使用的 jdk 序列化模式存储的,这一点也是很容易理解的,session.setAttribute(String key, Object value),存储 Object 类型

object 放入 redis 中又要能取出来,只能是序列化进行存储了,然后取出的时候进行反序列化。

所以我们在 session 中存储的任何对象,都必须实现序列化接口。

2. 按照如上配置, 使用 redis 做 session 存储空间时,web 应用的 session-time 的时间单位会变成[秒], 而不是原本的[分]

原因是: 因为 tomcat 里使用的将 session 放置 redis 使用的工具类, 在存储时为对 tomcat 容器时间做转换,

在 redis 中设置过期时间是使用秒作为单位的,有个命令叫 expire 可以设置 redis 键值过期时间,所以在 context.xml 配置文件中我们需要制定 session 过期时间(默认是 60 秒,配成 1800 即 30 分钟),这一点很重要。

请注意!!!!

context.xml 配置说明:

1
2
3
4
5
6
7
8
9
10
<Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" />     
<Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"
// 这里是 redis 服务器地址
host="192.168.50.140"
// 这里是 redis 端口,redis 默认端口是 6379
port="6379"
// 这里是 redis 数据库中的标识,标识第 0 个,默认使用 0 即可
database="0"           
// 需要注意的是这里由于 redis 过期时间默认设置为 60,单位是秒,session 过期时间为 30 分钟,所以需要设置为 1800 对应 30 分钟
maxInactiveInterval="1800"/>

三、keepalived 高可用:

架构图:

Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

上图画的不对称好难看,将就下吧

根据上边一路走来,已经是搭好了从 nginx 主到服务器的这条线的,那么同理,使用 nginx 备机 192.168.50.135 上再搭建 nginx,也是代理 192.168.137 和 139 两台服务器。搞了一次之后也就简单了

在 192.168.50.135 上安装 nginx,配置 nginx 配置即可,不再赘述,nginx 备机配置如下:

配置和上边的是一样的,只不过监听的地方的 ip 了而已

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
........upstream blank {
        #ip_hash;
        server 192.168.50.137:8080;
        server 192.168.50.139:8080;
}
     
    server {
        listen      80;
        server_name  192.168.50.135;
 
        #charset koi8-r;
 
        #access_log  logs/host.access.log  main;
 
        location / {
            proxy_pass http://blank;
            root  html;
            index  index.html index.htm;
        }........

那么现在就是相当于有两套 nginx 了,代理的服务器是一样的,为什么要搞两套?

假设只有一台 nginx 的话,这个 nginx 服务器挂了。那怎么办?

所以需要一台备份 nginx。

正常情况下,主 nginx 作为反向代理服务器即可,假设 nginx 服务器挂了的话,能够立即切换到备份机上,保证用户可以访问,然后运维人员把主 nginx 服务器故障修好之后,又能够自动切换到主 nginx 提供服务。通过 keepalived 来监测两台服务器,正常情况时,将 nginx 主服务器 ip(192.168.50.133)绑定到 keepalived 定义的一个虚拟 ip(我设置为 192.168.50.88)上,通过这个虚拟 IP 可以访问 nginx,然后备机(192.168.50.135)啥事不干,就是每隔一小段时间(设置为 1 秒)keepalived 会告诉备机,你不用管,我还活着呢,如果突然主机死了,那么就会超过一秒备机没有收到主机或者的消息,那么备机马上接管主机,keeplived 将虚拟 ip 绑定到备机身上,网站继续提供服务。

突然主机又复活了(运维人员排除故障了),那么备机又将收到主机的活着的消息,于是将管理权交回给主机,虚拟 ip 又绑到主机上,大概就是这么个过程,个人理解。

Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

 先在两台 nginx 服务器(主备)上都装上 keepalived:

 下载:这里使用 rpm 安装,是区分 32,64 位的,不要搞错了哦

keepalived-1.2.7-3.el6.x86_64.rpm

openssl-1.0.1e-30.el6_6.4.x86_64.rpm

要求必须是 openssl-1.0.1e 或以上才行、如果版本已经符合(因为安装 nginx 时已经安装 openssl,使用 yum 安装应该是符合的)、不用再安装 openssl,使用 rpm -q openssl 查看当前 openssl 版本,我这已经是 1.0.1e 48 的,所以就不安装了

Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

将两个 rpm 安装包上传到两台 nginx 服务器,进入上传到的目录,运行以下命令安装:–nodeps 是忽略依赖包,当然最好是把依赖包装上,去掉 –nodeps 可以看到错误,需要哪些依赖包

如果需要安装 openssl

1
rpm –Uvh --nodeps ./openssl-1.0.1e-30.el6_6.4.x86_64.rpm

 安装 keepalived:

1
 rpm -Uvh --nodeps ./keepalived-1.2.7-3.el6.x86_64.rpm

安装完毕后再 /etc/keepalived/ 目录下有个文件 keepalived.conf 即是本台服务器 keepalived 的核心配置文件了:

重点:keepalived 配置,配置文件上边部分按照下面的配置就行了,配置文件后面的内容可以不用管,还没有去研究其他部分

先配置主机 192.168.50.133 的 keepalived,按下边进行配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
! Configuration File for keepalived
 
# 这是全局配置
global_defs {
   # 指定 keepalived 在发生切换时需要发送 email 到的对象,一行一个
   notification_email {
     acassen@firewall.loc
     failover@firewall.loc
     sysadmin@firewall.loc
   }
   # 指定发件人
   notification_email_from Alexandre.Cassen@firewall.loc
   # 指定 smtp 服务器地址
   #smtp_server 192.168.200.1
   # 指定 smtp 连接超时时间
   #smtp_connect_timeout 30
   # 运行 keepalived 机器的一个标识
   router_id LVS_DEVEL
}
 
# 主备配置
vrrp_instance VI_1 {
    # 标示状态为 MASTER 备份机为 BACKUP
    state MASTER
    # 设置 keepalived 实例绑定的服务器网卡,一般为 eth0,linux 使用 ifconfig 命令可查看当前服务器网卡标识名
    interface eth0
    # 同一实例下(即同一组主备机下)virtual_router_id 必须相同
    virtual_router_id 51
    #MASTER 权重要高于 BACKUP,MASTER 为 100 则 BACKUP 最大为99
    priority 100
    #MASTER 与 BACKUP 负载均衡器之间同步检查的时间间隔,单位是秒,设置为 1
    advert_int 1
    # 设置认证
    authentication {
        # 主从服务器验证方式,PASS 为明文密码验证
        auth_type PASS
        # 密码
        auth_pass 1111
    }
    # 设置虚拟 IP,与我们的主备机在同一网段下,最后一位随便给就是拉,可以设置多个,换行即可
    virtual_ipaddress {
        192.168.50.88
    }
}

备机 192.168.50.135 的 keepalived 配置:

备机配置注意的地方:需要修改 state 为 BACKUP , priority 比 MASTER 低,virtual_router_id 和 master 的值一致

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
! Configuration File for keepalived
 
# 这是全局配置
global_defs {
   # 指定 keepalived 在发生切换时需要发送 email 到的对象,一行一个
   notification_email {
     acassen@firewall.loc
     failover@firewall.loc
     sysadmin@firewall.loc
   }
   # 指定发件人
   notification_email_from Alexandre.Cassen@firewall.loc
   # 指定 smtp 服务器地址
   #smtp_server 192.168.200.1
   # 指定 smtp 连接超时时间
   #smtp_connect_timeout 30
   # 运行 keepalived 机器的一个标识
   router_id LVS_DEVEL
}
 
# 主备配置
vrrp_instance VI_1 {
    # 备机为 BACKUP
    state BACKUP
    # 备机网卡标识,一般都是 eth0,先查询一下
    interface eth0
    #virtual_router_id 必须与主机相同
    virtual_router_id 51
    # 权重,备机必须比主机小
    priority 99
    #MASTER 与 BACKUP 负载均衡器之间同步检查的时间间隔,单位是秒,设置为 1
    advert_int 1
    # 认证,与主机一致
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    # 虚拟 IP,绑定的虚拟 ip 与主机一致
    virtual_ipaddress {
        192.168.50.135
    }
}

酱紫,keepalived 就配置完成了。

keeplived 启动关闭命令:

1
2
service keepalived start
service keepalived stop

启动两台 nginx,启动主机 keepalived,启动备机 keepalived 服务。

这时,nginx 主机在提供服务,备机是闲着的,虚拟 ip 是 192.168.50.88,在主机和备机上使用命令

1
ip addr

 可以发现:

主机:可以看到,192.168.50.133 带有虚拟 ip192.168.50.88,在浏览器中输入 192.168.50.88,即可访问到主 nginx192.168.50.133. 然后转发到 tomcat 服务器上

Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

浏览器访问虚拟 ip:192.168.50.88,效果如下

 Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

 备机:ip addr 命令执行:可以看到,备机 nginx 没有绑定虚拟 ip

Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

 以上是初始状态下的情况,也是正常服务的情况。

现在测试高可用,假设主机 nginx 服务器挂了,模拟为关闭 nginx 主机或者将 keepalived 服务停止,那么主机上 keepalived 死了就没办法告诉备机自己活着,而备机超过 1 秒没有接收到主机给自己的消息,马上接管虚拟 ip,同时在配置文件中配置切换主备机时发送邮件,此时开发团队收到邮件即知道主机挂了,马上去排除主机的故障。

将主机上的 keepalived 服务停止,service keepalived stop , 然后查看虚拟 ip 绑定情况,

主机挂了:可以看到虚拟 ip 就没有绑在主机上

Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

备机情况:虚拟 ip 已经绑定到备机,此时主机虽然挂了,但是切换到备机上了(发现故障和切换的时间差最大也就是 1 秒),虚拟 ip 也绑到备机上了,访问虚拟 ip,就会请求备机 nginx 然后转发到 web 服务器实现高可用。

 Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

 运维人员收到邮件后就去排除主机故障了,搞定之后(模拟为 keepalived 服务启动),这时主机告诉备机,我又活了,于是备机将管理权又交给主机(切换为主机 nginx 提供服务):

主机 keepalived 服务启动后,即吧主机维护好之后:可以看到,虚拟 ip 又自动绑到了主机上

 Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

 备机情况,主机活了之后,备机转交管理权,虚拟 ip 切换到主机上,备机不绑定虚拟 ip, 貌似启动 keepalived 服务之后并不能马上切回,应该是起服务需要点时间吧,但是不影响,这段时间还是备机绑定虚拟 IP 的

Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

 这就是 keepalived 高可用的模拟。

注意问题:

主机挂了之后,主机 nginx 恢复时,一定要将 nginx 也启动,否则即使虚拟 ip 切换到了主机上,但是主机 nginx 没起那也是没法转发的。所以要把nginx 启动要加在开机启动中。

四、Nginx 服务开机自启动:

在 linux 系统的/etc/init.d/ 目录下创建 nginx 文件,使用如下命令:(vim 命令不会的自己去学吧哈哈)

1
vi /etc/init.d/nginx

将如下内容搞到该文件中:注意红色部分修改成你的路径即可,nginxd值是启动 nginx 的 nginx 路径,nginx_config值是 nginx 配置文件 nginx.conf 路径,nginx_pid值是nginx.pid 所在路径,如果按照我方法安装的话,是在 nginx 安装目录的 logs 里边的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#!/bin/bash
# nginx Startup script for the Nginx HTTP Server
# it is v.0.0.2 version.
# chkconfig: - 85 15
# description: Nginx is a high-performance web and proxy server.
#              It has a lot of features, but it's not for everyone.
# processname: nginx
# pidfile: /usr/local/nginx/logs/nginx.pid
# config: /usr/local/nginx/conf/nginx.conf
nginxd=/usr/local/nginx/sbin/nginx
nginx_config=/usr/local/nginx/conf/nginx.conf
nginx_pid=/usr/local/nginx/logs/nginx.pid
RETVAL=0
prog="nginx"
# Source function library.
. /etc/rc.d/init.d/functions
# Source networking configuration.
. /etc/sysconfig/network
# Check that networking is up.
[${NETWORKING} = "no" ] && exit 0
[-x $nginxd] || exit 0
# Start nginx daemons functions.
start() {
if [-e $nginx_pid];then
   echo "nginx already running...."
   exit 1
fi
   echo -n $"Starting $prog:"
   daemon $nginxd -c ${nginx_config}
   RETVAL=$?
   echo
   [$RETVAL = 0 ] && touch /var/lock/subsys/nginx
   return $RETVAL
}
# Stop nginx daemons functions.
stop() {
        echo -n $"Stopping $prog:"
        killproc $nginxd
        RETVAL=$?
        echo
        [$RETVAL = 0 ] && rm -f /var/lock/subsys/nginx /var/run/nginx.pid
}
# reload nginx service functions.
reload() {
    echo -n $"Reloading $prog:"
    #kill -HUP `cat ${nginx_pid}`
    killproc $nginxd -HUP
    RETVAL=$?
    echo
}
# See how we were called.
case "$1" in
start)
        start
        ;;
stop)
        stop
        ;;
reload)
        reload
        ;;
restart)
        stop
        start
        ;;
status)
        status $prog
        RETVAL=$?
        ;;
*)
        echo $"Usage: $prog {start|stop|restart|reload|status|help}"
        exit 1
esac
exit $RETVAL

然后设置该文件的访问权限:执行以下命令,意为所有用户可访问

1
chmod a+x /etc/init.d/nginx

 最后将 ngix 加入到 rc.local 文件中,这样开机的时候 nginx 就默认启动了

1
vi /etc/rc.local

 

添加

 

1
/etc/init.d/nginx start

 

 Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

保存并退出,下 次重启就会生效,nginx 的开机自启动。测试无误的。

 

 

四、解决 nginx 进程和 keepalived 不同时存在问题:

 

keepalived 是通过检测 keepalived 进程是否存在判断服务器是否宕机,如果 keepalived 进程在,但是 nginx 进程不在了,那么 keepalived 是不会做主备切换。因为是 nginx 挂了,然后无法做代理,keepalived 还在不会切换到备机。

所以一直检测 nginx 是否还在,如果不在,那么让 keepalived 也停止,同生共死。

注:只需要在主机上搞就行了,备机没必要检测 nginx,因为基本是主机在服务。

解决:写个脚本来监控 nginx 进程是否存在,如果 nginx 不存在就将 keepalived 进程杀掉。

keepalived 不需要开机启动,假如开机自启的话,如果 keepalived 比 nginx 更快启动的话,脚本检测会把 keepalived 停掉的,所以没必要,只需要 nginx 开机启动,启动主机后自行手动的把 keepalived 服务启动即可。

在主 nginx 上编写 nginx 进程检测脚本(check_nginx_dead.sh), 在 keepalived 配置文件目录下创建脚本:

1
vi /etc/keepalived/check_nginx_dead.sh

把下边这些内容搞到脚本文件中,内容如下:

1
2
3
4
5
6
#!/bin/bash
# 如果进程中没有 nginx 则将 keepalived 进程 kill 掉
A=`ps -C nginx --no-header |wc -l`      ## 查看是否有 nginx 进程 把值赋给变量 A
if [$A -eq 0 ];then                    ## 如果没有进程值得为 零
       service keepalived stop          ## 则结束 keepalived 进程
fi

给访问权限:不然不行哦,这里卡了我半小时

1
chmod a+x /etc/keepalived/check_nginx_dead.sh

先测试一下脚本:

把 nginx 停了,此时 keepalived 还在运行,所以不会切换,虚拟 ip 无法访问到 web 服务器

Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

然后执行脚本:

主机脚本检测 nginx 不在了,把 keepalived 停掉,从输出可以看到确实停止了,主机虚拟没有绑定虚拟 ip

Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

备机:成功绑定虚拟 ip

 Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

所以,只需要让该脚本一直执行,即一直检测 nginx 进程是否在,如果没得了,那么直接停止主机 keepalived,切换备机,保证能够访问 web 服务器。

按如下修改 keepalived 配置文件 keepalived.conf,添加脚本定义检测:

只需要在正确的位置添加红色部分即可:那么脚本则是两秒执行一次,一旦发现主机 nginx 不在了,keepalived 停止,切换备机

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
! Configuration File for keepalived
 
# 这是全局配置
global_defs {
   # 指定 keepalived 在发生切换时需要发送 email 到的对象,一行一个
   notification_email {
     acassen@firewall.loc
     failover@firewall.loc
     sysadmin@firewall.loc
   }
   # 指定发件人
   notification_email_from Alexandre.Cassen@firewall.loc
   # 指定 smtp 服务器地址
   #smtp_server 192.168.200.1
   # 指定 smtp 连接超时时间
   #smtp_connect_timeout 30
   # 运行 keepalived 机器的一个标识
   router_id LVS_DEVEL
}
 
vrrp_script check_nginx_dead {
    ## 监控脚本路径
    script "/etc/keepalived/check_nginx_dead.sh"
    ## 时间间隔,2
    interval 2
    ## 权重
    weight 2                                           
}
 
# 主备配置
vrrp_instance VI_1 {
    # 标示状态为 MASTER 备份机为 BACKUP
    state MASTER
    # 设置 keepalived 实例绑定的服务器网卡,一般为 eth0,linux 使用 ifconfig 命令可查看当前服务器网卡标识名
    interface eth0
    # 同一实例下(即同一组主备机下)virtual_router_id 必须相同
    virtual_router_id 51
    #MASTER 权重要高于 BACKUP,MASTER 为 100 则 BACKUP 最大为99
    priority 100
    #MASTER 与 BACKUP 负载均衡器之间同步检查的时间间隔,单位是秒,设置为 1
    advert_int 1
    # 设置认证
    authentication {
    # 主从服务器验证方式,PASS 为明文密码验证
        auth_type PASS
    # 密码
        auth_pass 1111
    }
     
    track_script {
    # 监控脚本
        check_nginx_dead     
    }
     
    # 设置虚拟 IP,与我们的主备机在同一网段下,最后一位随便给就是拉,可以设置多个,换行即可
    virtual_ipaddress {
        192.168.50.88
    }
}

保存后,重新启动主机 keepalived 服务即可。

测试:

回到负载均衡高可用的 初始状态,保证主、备上的 keepalived、nginx 全部启动。

停止主 nginx 服务:

主机查看 keepalived 进程,发现没有,说明已经停止了,虚拟 ip 也没有绑在主机上

Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

 备机:绑定虚拟 ip,切换成功。

 Nginx 反向代理,负载均衡,Redis Session 共享,Keepalived 高可用

 测试通过,如果主机 nginx 挂了之后,keepalived 也会随着挂掉,然后切换备机。

以上所有过程均是经过测试的,所以除去一些其他因素,例如人品,应该都是可以成功的。

本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-12/138334.htm

正文完
星哥说事-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-21发表,共计20653字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中