keepalived实现高可用nginx反向代理(Web集群)

一、代理服务器概述

代理服务可简单的分为正向代理反向代理:

1)正向代理: 用于代理内部网络对Internet的连接请求(如VPN/NAT),客户端指定代理服务器,并将本来要直接发送给目标Web服务器的HTTP请求先发送到代理服务器上, 然后由代理服务器去访问Web服务器, 并将Web服务器的Response回传给客户端: 

2)反向代理:与正向代理相反,如果局域网向Internet提供资源,并让Internet上的其他用户可以访问局域网内资源, 也可以设置一个代理服务器, 它提供的服务就是反向代理. 反向代理服务器接受来自Internet的连接,然后将请求转发给内部网络上的服务器,并将Response回传给Internet上请求连接的客户端: 

 

1、反向代理(Reverse Proxy)方式是指以代理服务器来接受客户端的连接请求,然后将请求转发给网络上的web服务器(可能是apache、nginx、tomcat、iis等),并将从web服务器上得到的结果返回给请求连接的客户端,此时代理服务器对外就表现为一个服务器。

keepalived实现高可用nginx反向代理(Web集群)_第1张图片

从上图可以看出:反向代理服务器代理网站Web服务器接收Http请求,对请求进行转发。而且nginx作为反向代理服务器可以根据用户请求的内容把请求转发给后端不同的web服务器,例如静动分离,再例如在nginx上创建多个虚拟主机,这样就成功的做到了在浏览器中输入不同域名(url)的时候访问后端的不同web服务器或web群集。

 

2、反向代理的作用

1)保护网站安全:任何来自Internet的请求都必须先经过代理服务器;

keepalived实现高可用nginx反向代理(Web集群)_第2张图片

 

2)通过配置缓存功能加速Web请求:可以缓存真实Web服务器上的某些静态资源,减轻真实Web服务器的负载压力

keepalived实现高可用nginx反向代理(Web集群)_第3张图片

 

3)实现负载均衡:充当负载均衡服务器均衡地分发请求,平衡集群中各个服务器的负载压力;

keepalived实现高可用nginx反向代理(Web集群)_第4张图片

二、什么是keepalived

Keepalived的作用是检测服务器的状态,如果有一台web服务器宕机,或工作出现故障,Keepalived将检测到,并将有故障的服务器从系统中剔除,同时使用其他服务器代替该服务器的工作,当服务器工作正常后Keepalived自动将服务器加入到服务器群中,这些工作全部自动完成,不需要人工干涉,需要人工做的只是修复故障的服务器。


keepalived采用的是VRRP(虚拟路由冗余协议)热备份协议,VRRP路由器是指运行VRRP的路由器,是物理实体,虚拟路由器是指VRRP协议创建的,是逻辑概念。一组VRRP路由器协同工作,共同构成一台虚拟路由器。 Vrrp中存在着一种选举机制,用以选出提供服务的路由即主控路由,其他的则成了备份路由。当主控路由失效后,备份路由中会重新选举出一个主控路由,来继续工作,来保障不间断服务。

 

本章案例拓扑图如下:

keepalived实现高可用nginx反向代理(Web集群)_第5张图片

 

三、搭建后端web服务器池,确保后端web能够正常运行(web1操作)

1)安装http

 

[root@http1 ~]# yum install httpd -y

 

2)安装完成后启动httpd服务并导入测试页测试.

 

[root@http1 ~]# service httpd start
Starting httpd: httpd: apr_sockaddr_info_get() failed for http1
httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for ServerName
                                                           [  OK  ]
[root@http1 ~]# echo  "this is a http1" > /var/www/html/index.html
[root@http1 ~]# service iptables stop
iptables: Setting chains to policy ACCEPT: filter          [  OK  ]
iptables: Flushing firewall rules:                         [  OK  ]
iptables: Unloading modules:                               [  OK  ]

 


 

 

 

 

在web2服务器上也是同样的操作如下(web2操作)

1)安装httpd服务

 

[root@http2 ~]# yum install httpd -y

 

 

2)安装完成后启动httpd服务并写入测试页测试 如下:


 

到这里我们的后端web服务池能够正常运行!配置到此结束

 

四、安装Nginx

1)安装zlib-devel pcre-devel等依赖包(nginx-master操作)

 

[root@nginx-master ~]# yum -y install gcc gcc-c++ make libtool zlib zlib-devel pcre pcre-devel openssl openssl-devel

 

 

结合proxy和upstream模块实现后端web负载均衡使用proxy模块实现静态文件缓存结合nginx默认自带的 ngx_http_proxy_module 模块 和ngx_http_upstream_module模块实现后端服务器的健康检查,也可以使用第三方模块nginx_upstream_check_module

使用nginx-sticky-module扩展模块实现Cookie会话黏贴(保持会话)
使用ngx_cache_purge实现更强大的缓存清除功能
上面提到的2个模块都属于第三方扩展模块,需要提前下好源码,然后编译时通过--add-moudle=src_path一起安装。

 

 

安装Nginx

 

 

 

[root@nginx-master ~]# groupadd www
[root@nginx-master ~]# useradd -g www www -s /sbin/nologin 

 

#添加www组

 

#创建nginx运行账户www并加入到www组,不允许www用户直接登录系统

 

[root@nginx-master ~]# tar zxf nginx-1.12.2.tar.gz 
[root@nginx-master ~]# tar zxf ngx_cache_purge-2.3.tar.gz 
[root@nginx-master ~]# tar zxf nginx-goodies-nginx-sticky-module-ng-08a395c66e42.tar.gz 
[root@nginx-master ~]# cd nginx-1.12.2/

 

 

./configure --prefix=/usr/local/nginx1.10 --user=www --group=www --with-http_stub_status_module --with-http_realip_module --with-http_ssl_module --with-http_gzip_static_module --http-client-body-temp-path=/var/tmp/nginx/client --http-proxy-temp-path=/var/tmp/nginx/proxy --http-fastcgi-temp-path=/var/tmp/nginx/fcgi --with-pcre --add-module=/root/ngx_cache_purge-2.3 --with-http_flv_module  --add-module=/root/nginx-goodies-nginx-sticky-module-ng-08a395c66e42

make && make install

注:nginx的所有模块必须在编译的时候添加,不能再运行的时候动态加载。

 

优化nginx程序的执行路径

 

[root@nginx-master nginx-1.12.2]# ln -s /usr/local/nginx1.10/sbin/nginx /usr/local/sbin/
[root@nginx-master nginx-1.12.2]# nginx -t
nginx: the configuration file /usr/local/nginx1.10/conf/nginx.conf syntax is ok
nginx: [emerg] mkdir() "/var/tmp/nginx/client" failed (2: No such file or directory)
nginx: configuration file /usr/local/nginx1.10/conf/nginx.conf test failed
[root@nginx-master nginx-1.12.2]# mkdir -p /var/tmp/nginx/client
[root@nginx-master nginx-1.12.2]# nginx -t
nginx: the configuration file /usr/local/nginx1.10/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx1.10/conf/nginx.conf test is successful

 

 

 

 

 

启动Nginx服务,并访问测试

keepalived实现高可用nginx反向代理(Web集群)_第6张图片

到这里nginx-master安装完成,nginx-slave的安装和master是一样的 所以可以参考以上操作进行安装

我这里已经安装好了如下:

keepalived实现高可用nginx反向代理(Web集群)_第7张图片

五、配置Nginx反向代理

1)nginx-sticky-module模块
这个模块的作用是通过cookie黏贴的方式将来自同一个客户端(浏览器)的请求发送到同一个后端服务器上处理,这样一定程度上可以解决多个backend servers的session同步的问题 —— 因为不再需要同步,而RR轮询模式必须要运维人员自己考虑session同步的实现。
另外内置的 ip_hash 也可以实现根据客户端IP来分发请求,但它很容易造成负载不均衡的情况,而如果nginx前面有CDN网络或者来自同一局域网的访问,它接收的客户端IP是一样的,容易造成负载不均衡现象。nginx-sticky-module的cookie过期时间,默认浏览器关闭就过期。
这个模块并不合适不支持 Cookie 或手动禁用了cookie的浏览器,此时默认sticky就会切换成RR。它不能与ip_hash同时使用。

 

upstream backend {
        server 192.168.146.120:80 weight=1;
        server 192.168.146.130:80 weight=1;
        sticky;
}

 

配置起来超级简单,一般来说一个sticky指令就够了。

 

 

 

 

2)负载均衡与健康检查:
严格来说,nginx自带是没有针对负载均衡后端节点的健康检查的,但是可以通过默认自带的 ngx_http_proxy_module 模块和 ngx_http_upstream_module 模块中的相关指令来完成当后端节点出现故障时,自动切换到下一个节点来提供访问。

 

upstream backend {
        sticky;
        server 192.168.146.120:80 weight=1 max_fails=2 fail_timeout=10s;
        server 192.168.146.130:80 weight=1 max_fails=2 fail_timeout=10s;
}
server {
   ……
location / {
            proxy_pass http://backend;
}
……
}

 

weight : 轮询权值也是可以用在ip_hash的,默认值为1
max_fails : 允许请求失败的次数,默认为1。当超过最大次数时,返回proxy_next_upstream 模块定义的错误。
fail_timeout : 有两层含义,一是在10s 时间内最多容许2 次失败;二是在经历了 2 次失败以后,10s时间内不分配请求到这台服务器。

 

 

3)nginx的proxy缓存使用:
缓存也就是将js、css、image等静态文件从后端服务器缓存到nginx指定的缓存目录下,既可以减轻后端服务器负担,也可以加快访问速度,但这样缓存及时清理成为了一个问题,所以需要 ngx_cache_purge 这个模块来在过期时间未到之前,手动清理缓存。
proxy模块中常用的指令时proxy_pass和proxy_cache.
nginx的web缓存功能的主要是由proxy_cache、fastcgi_cache指令集和相关指令集完成,proxy_cache指令负责反向代理缓存后端服务器的静态内容,fastcgi_cache主要用来处理FastCGI动态进程缓存。
http {
    #$upstream_cache_status记录缓存命中率
log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"'
                      '"$upstream_cache_status"';
access_log  logs/access.log  main;
proxy_buffering on;   #代理的时候,开启或关闭缓冲后端服务器的响应
proxy_temp_path /usr/local/nginx1.10/proxy_temp;
   proxy_cache_path /usr/local/nginx1.10/proxy_cache levels=1:2 keys_zone=my-cache:100m  inactive=600m max_size=2g;
    server {
        listen       80;
        server_name  localhost;
        root   html;
        index  index.php index.html index.htm;
        #ngx_cache_purge实现缓存清除
        location  ~/purge(/.*) {
           allow 127.0.0.1;
           allow 192.168.146.0/24;
           deny all;
           proxy_cache_purge my-cache $host$1$is_args$args;
        }
      location ~ .*\.(gif|jpg|png|html|htm|css|js|ico|swf|pdf)(.*) {
           proxy_pass  http://backend;
           proxy_redirect off;
           proxy_set_header Host $host;
           proxy_set_header X-Real-IP $remote_addr;
           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
           proxy_ignore_headers Set-Cookie;
proxy_hide_header Set-Cookie;
           proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
           proxy_cache my-cache;
           add_header Nginx-Cache $upstream_cache_status;
           proxy_cache_valid 200 304 301 302 8h;
           proxy_cache_valid 404 1m;
           proxy_cache_valid any 1d;
           proxy_cache_key $host$uri$is_args$args;
           expires 30d;
       }
相关选项说明:
proxy_buffering on; 代理的时候,开启或关闭缓冲后端服务器的响应。
当开启缓冲时,nginx尽可能快地从被代理的服务器接收响应,再将它存入缓冲区中。
proxy_temp_path : 缓存临时目录。后端的响应并不直接返回客户端,而是先写到一个临时文件中,然后被rename一下当做缓存放在 proxy_cache_path 。0.8.9版本以后允许temp和cache个目录在不同文件系统上(分区),然而为了减少性能损失还是建议把它们设成一个文件系统上。
proxy_cache_path: 设置缓存目录,目录里的文件名是 cache_key 的MD5值。
levels=1:2 keys_zone=my-cache:100m表示采用2级目录结构,第一层目录只有一个字符,是由levels=1:2设置,总共二层目录,子目录名字由二个字符组成。Web缓存区名称为my-cache,内存缓存空间大小为100MB,这个缓冲zone可以被多次使用。文件系统上看到的缓存文件名类似于 /usr/local/nginx1.10/proxy_cache/c/29/b7f54b2df7773722d382f4809d65029c 。
inactive=600 max_size=2g表示600分钟没有被访问的内容自动清除,硬盘最大缓存空间为2GB,超过这个大学将清除最近最少使用的数据。
需要在默认情况,nginx不缓存从后端响应的http头中带有Set-Cookie的对象。如果客户端发送的请求带有Cookie header,varnish将忽略缓存,直接将请求传递到后端。nginx中通过proxy_ignore_headers设置忽略它们,设置方法如下:
解决办法:  
proxy_ignore_headers Set-Cookie;
proxy_hide_header Set-Cookie;
proxy_cache : 引用前面定义的缓存区 my-cache
proxy_cache_key :定义如何生成缓存的键,设置web缓存的key值,nginx根据key值md5哈希存储缓存
proxy_cache_valid : 为不同的响应状态码设置不同的缓存时间,比如200、302等正常结果可以缓存的时间长点,而404、500等缓存时间设置短一些,这个时间到了文件就会过期,而不论是否刚被访问过。
add_header指令来设置response header, 语法: add_header name value;
$upstream_cache_status这个变量来显示缓存的状态,我们可以在配置中添加一个http头来显示这一状态,
$upstream_cache_status包含以下几种状态: 
•MISS 未命中,请求被传送到后端 
•HIT 缓存命中 
•EXPIRED 缓存已经过期请求被传送到后端 
•UPDATING 正在更新缓存,将使用旧的应答 
•STALE 后端将得到过期的应答
expires : 在响应头里设置Expires:或Cache-Control:max-age,返回给客户端的浏览器缓存失

下面的nginx.conf实现nginx在前端做反向代理服务器的完整配置文件的例子

 

user  www www;
worker_processes  1;
error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;
worker_rlimit_nofile 10240;
pid        logs/nginx.pid;
events {
    use epoll;
    worker_connections  4096;
}
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"'
                      '"$upstream_cache_status"';
access_log  logs/access.log  main;
server_tokens off;
    sendfile        on;
    #tcp_nopush     on;
    #keepalive_timeout  0;
    keepalive_timeout  65;
    #Compression Settings
    gzip on;
    gzip_comp_level 6;
    gzip_http_version 1.1;
    gzip_proxied any;
    gzip_min_length 1k;
    gzip_buffers 16 8k;
    gzip_types text/plain text/css text/javascript application/json application/javascript application/x-javascript application/xml;
    gzip_vary on;
    #end gzip
    # http_proxy Settings
    client_max_body_size   10m;
    client_body_buffer_size   128k;
    proxy_connect_timeout   75;
    proxy_send_timeout   75;
    proxy_read_timeout   75;
    proxy_buffer_size   4k;
    proxy_buffers   4 32k;
    proxy_busy_buffers_size   64k;
proxy_temp_file_write_size  64k;
proxy_buffering on;
    proxy_temp_path /usr/local/nginx1.10/proxy_temp;
    proxy_cache_path /usr/local/nginx1.10/proxy_cache levels=1:2 keys_zone=my-cache:100m max_size=1000m inactive=600m max_size=2g;
    #load balance Settings
    upstream backend {
        sticky;
        server 192.168.146.120:80 weight=1 max_fails=2 fail_timeout=10s;
        server 192.168.146.130:80 weight=1 max_fails=2 fail_timeout=10s;
    }
    #virtual host Settings
    server {
        listen       80;
        server_name  localhost;
        charset utf-8;
        location  ~/purge(/.*) {
           allow 127.0.0.1;
           allow 192.168.146.0/24;
           deny all;
           proxy_cache_purge my-cache $host$1$is_args$args;
        }
        location / {
            index  index.php index.html index.htm;
            proxy_pass        http://backend;
            proxy_redirect off;
            proxy_set_header  Host  $host;
            proxy_set_header  X-Real-IP  $remote_addr;
            proxy_set_header  X-Forwarded-For  $proxy_add_x_forwarded_for;
            proxy_ignore_headers Set-Cookie;
proxy_hide_header Set-Cookie;
            proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
        }
        location ~ .*\.(gif|jpg|png|html|htm|css|js|ico|swf|pdf)(.*) {
           proxy_pass  http://backend;
           proxy_redirect off;
           proxy_set_header Host $host;
           proxy_set_header X-Real-IP $remote_addr;
           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
           proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
           proxy_cache my-cache;
           add_header Nginx-Cache $upstream_cache_status;
           proxy_cache_valid 200 304 301 302 8h;
           proxy_cache_valid 404 1m;
           proxy_cache_valid any 1d;
           proxy_cache_key $host$uri$is_args$args;
           expires 30d;
        }
        location /nginx_status {
            stub_status on;
            access_log off;
            allow 192.168.146.0/24;
            deny all;
        }
    }
}

 

 

 

 

 

配置完成后加载Nginx并测试

 

 

keepalived实现高可用nginx反向代理(Web集群)_第8张图片

 

 

 

到这里我们的nginx-master反向代理已经配置成功,在nginx-slave主机上的配置和master是一样的,可以参考以上操作,这里我已经配置好了,如下:

 

六、安装keepalived

nginx-master主机操作

 

[root@nginx-master ~]# tar zxf keepalived-1.2.12.tar.gz 
[root@nginx-master ~]# cd keepalived-1.2.12/
[root@nginx-master keepalived-1.2.12]# ./configure --prefix=/ && make && make install

 

[root@nginx-master keepalived-1.2.12]# chkconfig --add keepalived
[root@nginx-master keepalived-1.2.12]# chkconfig keepalived on

 

 

 

nginx-slave主机操作

 

[root@nginx-slave ~]# tar zxf keepalived-1.2.12.tar.gz 
[root@nginx-slave ~]# cd keepalived-1.2.12/
[root@nginx-slave keepalived-1.2.12]# ./configure --prefix=/ && make && make install

 

[root@nginx-slave keepalived-1.2.12]# chkconfig --add keepalived
[root@nginx-slave keepalived-1.2.12]# chkconfig keepalived on


2)keepalived的配置

 

master主配置如下:

 

! Configuration File for keepalived

global_defs {
   router_id 146.100
}

vrrp_script chk_http_port {
    script "/opt/chk_nginx.sh"
    interval 2        #每2秒检测一次nginx的运行状态
    weight -5       #失败一次,将自己的优先级-5
}

vrrp_instance VI_1 {
    state MASTER		# 状态,主节点为MASTER,备份节点为BACKUP
    interface ens32		# 绑定VIP的网络接口,通过ifconfig查看自己的网络接口
    virtual_router_id 51	# 虚拟路由的ID号,两个节点设置必须一样
    priority 100               # 节点优先级,值范围0~254,MASTER要比BACKUP高
    advert_int 1               # 组播信息发送时间间隔,两个节点必须设置一样,默认为1秒
    authentication {           # 设置验证信息,两个节点必须一致
        auth_type PASS
        auth_pass 1111
    }
# 虚拟IP,两个节点设置必须一样。可以设置多个,一行写一个
    virtual_ipaddress {
        192.168.146.150/24
    }

track_script {
   chk_http_port           # nginx存活状态检测脚本
}
}

keepalived实现高可用nginx反向代理(Web集群)_第9张图片

 

 

 

 

 

slave主配置如下:

 

! Configuration File for keepalived

global_defs {
   router_id 146.110
}

vrrp_script chk_http_port {         
    script "/opt/chk_nginx.sh"   
    interval 2                      
    weight -5                       
}

vrrp_instance VI_1 {
    state slave
    interface ens32
    virtual_router_id 51
    priority 50
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.146.150/24
    }

track_script {                     
   chk_http_port                 
}
}

keepalived实现高可用nginx反向代理(Web集群)_第10张图片

 

 

 

 

 

编写Nginx检测脚本

[root@nginx-master ~]# vim /opt/chk_nginx.sh

 

#!/bin/bash
A=`ps -C nginx --no-header |wc -l`
if [ $A -eq 0 ];then
   killall -9 keepalived
fi

 

 

 

启动keepalived服务,测试双机热备

master主机:

keepalived实现高可用nginx反向代理(Web集群)_第11张图片

以上图中可以看到VIP地址目前是在master主机上,当我们关闭Nginx服务后,keepalived也即将关闭,再次测试VIP地址

keepalived实现高可用nginx反向代理(Web集群)_第12张图片

以上图中显示,master主机已经挂掉,再次查看slave主机IP地址

keepalived实现高可用nginx反向代理(Web集群)_第13张图片

这也就是我们上面的那句话

Keepalived的作用是检测果服务器的状态,如有一台web服务器宕机,或工作出现故障,Keepalived将检测到,并将有故障的服务器从系统中剔除,同时使用其他服务器代替该服务器的工作,当服务器工作正常后Keepalived自动将服务器加入到服务器群中,这些工作全部自动完成,不需要人工干涉,需要人工做的只是修复故障的服务器。

接下来修复主服务器,再次查看VIP地址

keepalived实现高可用nginx反向代理(Web集群)_第14张图片

当我们修复了主服务器之后,主服务器正常的提供服务!

测试访问虚拟VIP地址

客户端访问http://192.168.146.150/显示如下:

keepalived实现高可用nginx反向代理(Web集群)_第15张图片

 

测试图片以及文本是否经过压缩以及缓存

上传图片测试

keepalived实现高可用nginx反向代理(Web集群)_第16张图片

keepalived实现高可用nginx反向代理(Web集群)_第17张图片

 

祝大家圣诞节快乐~

2017年倒计时!!!

    希望对您有所帮助,再见~

 

 

 

 

 

 

 

你可能感兴趣的:(Nginx,Linux,Linux集群架构,Linux入门到熟练)