fgdfg 发表于 2018-11-9 08:20:06

用RHEL6.4(64bit)Nginx+Keepalived实现Nginx进程的主从、双主高可用

  一、Nginx理论
  传统上基于进程或线程模型架构的web服务通过每进程或每线程处理并发连接请求,这势必会在网络和I/O操作时产生阻塞,其另一个必然结果则是对内存或CPU的利用率低下。生成一个新的进程/线程需要事先备好其运行时环境,这包括为其分配堆内存和栈内存,以及为其创建新的执行上下文等。这些操作都需要占用CPU,而且过多的进程/线程还会带来线程抖动或频繁的上下文切换,系统性能也会由此进一步下降。
  在设计的最初阶段,nginx的主要着眼点就是其高性能以及对物理计算资源的高密度利用,因此其采用了不同的架构模型。受启发于多种操作系统设计中基于“事件”的高级处理机制,nginx采用了模块化、事件驱动、异步、单线程及非阻塞的架构,并大量采用了多路复用及事件通知机制。在nginx中,连接请求由为数不多的几个仅包含一个线程的进程worker以高效的回环(run-loop)机制进行处理,而每个worker可以并行处理数千个的并发连接及请求。
  如果负载以CPU密集型应用为主,如SSL或压缩应用,则worker数应与CPU数相同;如果负载以IO密集型为主,如响应大量内容给客户端,则worker数应该为CPU个数的1.5或2倍。
  Nginx会按需同时运行多个进程:一个主进程(master)和几个工作进程(worker),配置了缓存时还会有缓存加载器进程(cache loader)和缓存管理器进程(cache manager)等。所有进程均是仅含有一个线程,并主要通过“共享内存”的机制实现进程间通信。主进程以root用户身份运行,而worker、cache loader和cache manager均应以非特权用户身份运行。
  主进程主要完成如下工作:
  1. 读取并验正配置信息;
  2. 创建、绑定及关闭套接字;
  3. 启动、终止及维护worker进程的个数;
  4. 无须中止服务而重新配置工作特性;
  5. 控制非中断式程序升级,启用新的二进制程序并在需要时回滚至老版本;
  6. 重新打开日志文件;
  7. 编译嵌入式perl脚本;
  worker进程主要完成的任务包括:
  1. 接收、传入并处理来自客户端的连接;
  2. 提供反向代理及过滤功能;
  3. nginx任何能完成的其它任务;
  cache loader进程主要完成的任务包括:
  1. 检查缓存存储中的缓存对象;
  2. 使用缓存元数据建立内存数据库;
  二、主从模型
  我是在rhel-server-6.4(64位)上做的,这里nginx1和nginx2上面分别安装上nginx和keepalived。
  Nginx1
  Nginx2
  Vip1
  172.16.58.1
  172.16.58.6
  172.16.58.7
  1、安装yum库
  我这里编译安装nginx需要实现需要安装开发包组,在红帽5上我需要安装开发组包"DevelopmentTools"和"DevelopmentLibraries",在红帽6上我用yum包安装的开发环境和红帽5的不太一样,需要安装"Developmenttools","ServerPlatform Development",有时候还需要安装"Compatibility libraries"(兼容库),另外还有可能会使用"Desktop Platform Development"。我们这里安装的光盘是rhel-server-6.4-x86_64-dvd,安装过程红帽5一样。
# mkdir /mnt/cdrom    ###创建cdrom目录  
# mount /dev/cdrom /mnt/cdrom###挂载光盘(当场有效,开机无效)
  
# vim /etc/fstab###在配置文件中挂载光盘(当场无效,开机有效)
  
/dev/cdrom            /mnt/cdrom            ext3    defaults      0 0
  
# cd /etc/yum.repos.d/###进入yum.repos.d目录下面
  
# vim server.repo###编辑server.repo
  

  
name=Server
  
baseurl=file:///mnt/cdrom/Server
  
enabled=1
  
gpgcheck=0
  2、解决依赖关系
  Nginx某些功能可能还要依赖pcre所以我还要安装pcre-devel这个包。Pcre是perl兼容的正则表达式库。
# yumgroupinstall "Server Platform Development" "Development tools"–y  
# yum -y installpcre-devel    ###安装pcre-devel
  3、安装nginx
  我这里已经把软件包下载到本地nginx-1.4.1.tar.gz和keepalived-1.2.7.tar,下载完成后我首先要同步一下时间,如果系统时间比软件包的时间要靠前的话,系统就认为这个软件包是未来的,所以软件包是使用不了的。我知道nginx是轻量级的web服务器。
# date   ###查看一下时间  
# update 172.16.0.1   ###同步服务器时间
  
# tar xf nginx-1.4.1.tar.gz###解压

  Nginx基本上都是以普通用户进行运行,所以我要在这里建立一个用户,创建完成后就开始编译和安装了。
# groupadd -r -g 109 nginx   ###创建组  
# useradd -r -g 109 -u 109 nginx###创建用户
  
# ./configure \
  
--prefix=/usr \    ###默认安装路径
  
--sbin-path=/usr/sbin/nginx \   ###nginx自身可执行程序的路径
  
--conf-path=/etc/nginx/nginx.conf \###主配置文件的路径
  
--error-log-path=/var/log/nginx/error.log \    ###错误日志文件路径
  
--http-log-path=/var/log/nginx/access.log \    ###访问日志文件路径
  
--pid-path=/var/run/nginx/nginx.pid \   ###pid文件路径
  
--lock-path=/var/lock/nginx.lock \   ###锁文件路径
  
--user=nginx \    ###用户名
  
--group=nginx \   ###组名
  
--with-http_ssl_module \    ###使用ssl模块
  
--with-http_flv_module \   ###使用flv模块
  
--with-http_stub_status_module \
  
--with-http_gzip_static_module \         ###使用gzip压缩模块
  
--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/ \   ###和fastcgi相关的
  
--http-uwsgi-temp-path=/var/tmp/nginx/uwsgi \   ###和uwsgi相关的
  
--http-scgi-temp-path=/var/tmp/nginx/scgi \   ###和scgi相关的
  
# make && make install
  说明:如果想使用nginx的perl模块,可以通过为configure脚本添加--with-http_perl_module选项来实现,但目前此模块仍处于实验性使用阶段,可能会在运行中出现意外,因此,其实现方式这里不再介绍。如果想使用基于nginx的cgi功能,也可以基于FCGI来实现,具体实现方法请参照网上的文档。
  4、提供服务脚本
  新建文件/etc/rc.d/init.d/nginx内容如下:
#!/bin/sh  
#
  
# nginx - this script starts and stops thenginx daemon
  
#
  
# chkconfig:   - 85 15
  
# description:Nginx is an HTTP(S) server, HTTP(S) reverse \
  
#               proxy and IMAP/POP3 proxy server
  
# processname: nginx
  
# config:      /etc/nginx/nginx.conf
  
# config:      /etc/sysconfig/nginx
  
# pidfile:   /var/run/nginx.pid
  
# Source function library.
  
. /etc/rc.d/init.d/functions
  
# Source networking configuration.
  
. /etc/sysconfig/network
  
# Check that networking is up.
  
[ "$NETWORKING" = "no"] && exit 0
  
nginx="/usr/sbin/nginx"
  
prog=$(basename $nginx)
  
NGINX_CONF_FILE="/etc/nginx/nginx.conf"
  
[ -f /etc/sysconfig/nginx ] && ./etc/sysconfig/nginx
  
lockfile=/var/lock/subsys/nginx
  
make_dirs() {
  
#make required directories
  
user=`nginx -V 2>&1 | grep "configure arguments:" | sed's/[^*]*--user=\([^ ]*\).*/\1/g' -`
  
options=`$nginx -V 2>&1 | grep 'configure arguments:'`
  
for opt in $options; do
  
if [ `echo $opt | grep '.*-temp-path'` ]; then
  
value=`echo $opt | cut -d"=" -f 2`
  
if [ ! -d "$value" ]; then
  
# echo "creating"$value
  
mkdir -p $value && chown-R $user $value
  
fi
  
fi
  
done
  
}
  
start() {
  
[-x $nginx ] || exit 5
  
[-f $NGINX_CONF_FILE ] || exit 6
  
make_dirs
  
echo -n $"Starting $prog: "
  
daemon $nginx -c $NGINX_CONF_FILE
  
retval=$?
  
echo
  
[$retval -eq 0 ] && touch $lockfile
  
return $retval
  
}
  
stop() {
  
echo -n $"Stopping $prog: "
  
killproc $prog -QUIT
  
retval=$?
  
echo
  
[$retval -eq 0 ] && rm -f $lockfile
  
return $retval
  
}
  
restart() {
  
configtest || return $?
  
stop
  
sleep 1
  
start
  
}
  
reload() {
  
configtest || return $?
  
echo -n $"Reloading $prog: "
  
killproc $nginx -HUP
  
RETVAL=$?
  
echo
  
}
  
force_reload() {
  
restart
  
}
  
configtest() {
  
$nginx -t -c $NGINX_CONF_FILE
  
}
  
rh_status() {
  
status $prog
  
}
  
rh_status_q() {
  
rh_status >/dev/null 2>&1
  
}
  
case "$1" in
  
start)
  
rh_status_q && exit 0
  
$1
  
;;
  
stop)
  
rh_status_q || exit 0
  
$1
  
;;
  
restart|configtest)
  
$1
  
;;
  
reload)
  
rh_status_q || exit 7
  
$1
  
;;
  
force-reload)
  
force_reload
  
;;
  
status)
  
rh_status
  
;;
  
condrestart|try-restart)
  
rh_status_q || exit 0
  
;;
  
*)
  
echo $"Usage: $0{start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}"
  
exit 2
  
esac
  
# chmod +x /etc/rc.d/init.d/nginx   ###赋予执行权限
  
# chkconfig --add nginx    ###加入服务列表中
  
# chkconfig --list nginx    ###查看状态
  
# service nginx start   ###启动服务器
  提示:这里有可能会报错,因为在不同的系统上,它们所指定的路径可能不一样,尤其是/var/tmp/nginx/下面,尤其是在这些路径下面没有这些文件目录的话可能会出错,如果出错了告诉你没有这些目录,我们要手动建立这些文件目录就行了。

  5、测试网页

6、安装keepalived
  这里我是编译安装keepalived,和上面我们yum安装的不一样,不过和nginx一样需要在nginx1和nginx2上都需要安装。我们可能在编译安装的时候会出错,这时候可能依赖的库时popt,我们需要用yum来安装,安装完成后我们在进行上面一步。
# tar xf keepalived-1.2.7.tar.gz    ###解压  
# cd keepalived-1.2.7
  
# ./configure --prefix=/usr/
  
# yum install -y popt-devel   ###安装popt-devel
  
# ./configure --prefix=/usr/
  
# make && make install
  
# cp /usr/etc/rc.d/init.d/keepalived/etc/rc.d/init.d/keepalived    ###复制服务脚本

# vim keepalived
  (1)在nginx1上面(主服务器)上修改配置文件并测试
# vim /etc/keepalived/keepalived.conf   ###配置文件  
! Configuration File for keepalived
  
global_defs {
  
notification_email {
  
linuxedu@foxmail.com
  
mageedu@126.com
  
}
  
notification_email_from kanotify@magedu.com
  
smtp_connect_timeout 3
  
smtp_server 127.0.0.1
  
router_id LVS_DEVEL
  
}
  
vrrp_script chk_nginx{
  
script "killall -0 nginx"
  
interval 2
  
# check every 2 seconds
  
weight -2
  
# if failed, decrease 2 of the priority
  
fall 2
  
# require 2 failures for failures
  
rise 1
  
# require 1 sucesses for ok
  
}
  
vrrp_script chk_schedown {
  
script "[[ -f /etc/keepalived/down ]] && exit 1 || exit0"
  
interval 2
  
weight -2
  
}
  
vrrp_instance VI_1 {
  
interface eth0
  
# interface for inside_network, bound by vrrp
  
state MASTER
  
# Initial state, MASTER|BACKUP
  
# As soon as the other machine(s) come up,
  
# an election will be held and the machine
  
# with the highest "priority" will become MASTER.
  
# So the entry here doesn't matter a whole lot.
  
priority 101
  
# for electing MASTER, highestpriority wins.
  
# to be MASTER, make 50 more than other machines.
  
virtual_router_id 56
  
# arbitary unique number 0..255
  
# used to differentiate multiple instances of vrrpd
  
# running on the same NIC (and hence same socket).
  
garp_master_delay 1
  
authentication {
  
auth_typePASS
  
auth_pass password
  
}
  
track_interface {
  
eth0
  
}
  
# optional, monitor these as well.
  
# go to FAULT state if any of these go down.
  
virtual_ipaddress {
  
172.16.58.7/16 dev eth0 label eth0:1
  
}
  
#addresses add|del on change to MASTER, to BACKUP.
  
#With the same entries on other machines,
  
#the opposite transition will be occuring.
  
#/ brd devscopelabel
  
track_script {
  
chk_nginx
  
chk_schedown
  
}
  
notify_master "/etc/keepalived/notify.sh master"
  
notify_backup "/etc/keepalived/notify.sh backup"
  
notify_fault"/etc/keepalived/notify.sh fault"
  
}
  
#vrrp_instance VI_2 {
  
#   interface eth0
  
#   state MASTER# BACKUP for slaverouters
  
#   priority 101# 100 for BACKUP
  
#   virtual_router_id 52
  
#   garp_master_delay 1
  
#
  
#   authentication {
  
#       auth_typePASS
  
#       auth_pass password
  
#   }
  
#   track_interface {
  
#      eth0
  
#   }
  
#   virtual_ipaddress {
  
#       172.16.58.2/16 dev eth0 label eth0:1
  
#   }
  
#   track_script {
  
#       chk_nginx
  
#       chk_mantaince_down
  
#   }
  
#
  
#   notify_master "/etc/keepalived/notify.sh master eth0:1"
  
#   notify_backup "/etc/keepalived/notify.sh backup eth0:1"
  
#   notify_fault "/etc/keepalived/notify.sh fault eth0:1"
  
#}
  (2)在nginx2上(从服务器)修改配置文件
  这里只需要设置这么多就行了。

  我这里自己设置的有脚本(实现健康检查),大家如果想配置,可使用下面这个脚本,如果没有这个脚本的话,我试验的时候还需要关闭keepalived服务,如果不关闭,仅关闭nginx,是不能实现地址飘移的,我们有了这个脚本,实现了为主从设备切换提供脚本,只要主服务器不在,就会实现地址飘移的。(上面有路径)脚本的内容如下:
#vim notify.sh  
脚本内容如下:
  
#!/bin/bash
  
# description:An example of notify script
  
#
  
ifalias=${2:-eth0:0}
  
interface=$(echo$ifalias | awk -F: '{print $1}')
  
vip=$(ip addrshow $interface | grep $ifalias | awk '{print $2}')
  
#contact='linuxedu@foxmail.com'
  
contact='root@localhost'
  
workspace=$(dirname$0)
  
notify() {
  
subject="$ip change to $1"
  
body="$ip change to $1 $(date '+%F%H:%M:%S')"
  
echo $body | mail -s "$1transition" $contact
  
}
  
case"$1" in
  
master)
  
notify master
  
exit 0
  
;;
  
backup)
  
notify backup
  
/etc/rc.d/init.d/httpd restart
  
exit 0
  
;;
  
fault)
  
notify fault
  
exit 0
  
;;
  
*)
  
echo 'Usage: $(basename $0){master|backup|fault}'
  
exit 1
  
;;
  
esac
  
# chmod +xnginx.sh

  7、编辑并测试网页:
  我们首先要查看一下配置文件,看一下我们的网页在什么地方,然后就创建网页,创建完成后,我们就重启服务器然后进行测试,看自己设置的网页是否有问题,然后在测试一下我用vip测试一下显示的页面,并以此判断我上面的设置是否正确。
# mkdir /etc/nginx/html  
# vim/etc/nginx/html/index.html
  
nginx1.shuaige.com
  
nginx2.shuaige.com
  
# servicenginx restart



  这个时候我将nginx1(主服务器)给停掉,我们这里看看虚拟ip是否会飘到从服务器上,我们可以从查看nginx1和nginx2的地址配置信息中得到(如果结果不变,我们有要多查看几次),如果还不信我们就用测试网页来检验我的实验是否正确。
# touch /etc/keepalived/down   ###停止主服务器上的  
# ifconfig


  三、双主模式
  1、规划
  Nginx1
  Nginx2
  Vip1
  Vip2
  172.16.58.1
  172.16.58.6
  172.16.58.7
  172.16.58.8
  在上面基于web服务的高可用集群中,我们把keepalived配置文件中的最下面#开头的行开启了,开启后我们还要进行编辑,在nginx1中将VI_2,我需要将state MASTER改为state BACKUP,我们把优先级改为100,只要比MASTER的优先级小就行。内容如下:
# vim /etc/keepalived/keepalived.conf  
vrrp_instance VI_2 {
  
interface eth0
  
state BACKUP# BACKUP for slaverouters
  
priority 100# 100 for BACKUP
  
virtual_router_id 58
  
garp_master_delay 1
  
authentication {
  
auth_typePASS
  
auth_pass password
  
}
  
track_interface {
  
eth0
  
}
  
virtual_ipaddress {
  
172.16.58.8/16 dev eth0 label eth0:1
  
}
  
track_script {
  
chk_nginx
  
chk_mantaince_down
  
}
  
notify_master "/etc/keepalived/notify.sh master eth0:1"
  
notify_backup "/etc/keepalived/notify.sh backup eth0:1"
  
notify_fault "/etc/keepalived/notify.sh fault eth0:1"
  
}
  我在nginx2中修改的部分(圈住的部分)如图所示:

# servicekeepalived restart   ###启动keepalived服务器  
#ifconfig
  2、查看HA1的IP地址配置:

  查看HA2的IP地址配置:

  3、测试:


  4、模拟nginx1发生故障
# cd/etc/keepalived/  
# touch down
  查看HA2上IP地址配置:

  5、测试一下:
  如果我测试的结果中,172.16.58.7(vip1)和172.16.58.8(vip2)显示的结果一样,那我就操作成功了。




页: [1]
查看完整版本: 用RHEL6.4(64bit)Nginx+Keepalived实现Nginx进程的主从、双主高可用