备注:
2013年5月29,初稿(基于LEMP+FastCGI+Xcache构建web开发平台),如有增加会做详细说明
2013年6月02,基于LEMP平台添加nginx提供负载均衡、健康状况监测功能
第一部分:《Nginx相关知识介绍,其内容参见搜索引擎及笔者理解》
第二部分:《LEMP+FastCGI+Xcache编译安装案例》
第一部分:
Nginx功能介绍:
Nginx是一个高性能的HTTP和反向代理服务器,本身是由一个核心和一系列的模块组成, 核心主要用于提供Web Service的基本功能,以及Web和 Mail反向代理的功能;还用于启用网络协议,创建必要的运行时环境以及确保不同的模块之间平滑地进行交互。 Nginx大多跟协议相关的功能和某应用特有的功能都是由nginx的模块实现的。这些功能模块大致可以分为事件模块、阶段性处理器、输出过滤器、 变量处理器、协议、upstream和负载均衡几个类别,这些共同组成了nginx的http功能。事件模块主要用于提供OS独立的(不同操作系统的事件机制有所不同) 事件通知机制如kqueue或epoll等。协议模块则负责实现nginx通过http、tls/ssl、smtp、pop3以及imap与对应的客户端建立会话。
Nginx的优势:
作为web服务器:Nginx处理静态文件、索引文件、自动索引的效率非常高 作为代理服务器:Nginx可以实现无缓存的反向代理加速,提高网站运行速度 作为负载均衡:Nginx即可在内部直接支持Rails和PHP,也可以支持HTTP代理服务器对外进行服务。 性能:Nginx是专门为性能优化所开发,最重要的是效率,它采用poll模型,可以支持更多的并发连接 稳定性:Nginx采用了分阶段资源分配技术,使得CPU与内存的占用率非常低 高可用:Nginx支持热部署,启动速度特别迅速,因此可以再不间断服务的情况下,对版本进行升级。
Nginx模块与工作:
Nginx是又内核和模块组成,模块通常分为三大模块: 核心模块、基础模块、第三方模块 核心模块:HTTP模块、EVENT模块、MAIL模块等 基础模块:HTTP Access模块、HTTP FastCGI模块、HTTP Proxy模块、HTTP Rewrite模块等 第三方模块:HTTP Upstream Request Hash模块、Notice模块、HTTP Access Key模块等 Nginx的模块从功能上分为三类: Handlers(处理器模块):处理用户请求,并进行输出内容和修改headers信息等操作。 Filters(过滤器模块):对处理器输出的内容进行过滤,然后交给nginx,由Nginx响应请求。 Proxies(代理类模块):主要与后端的服务进行交互,实现服务的代理和负载均衡等相关功能。 Nginx工作方式,默认工作在单工作进程模式下 单工作进程:除主进程外的一个进程,工作进程是单线程的 多工作进程:每个工作进程都包含更多的线程。
Nginx配置文件主要分为四个部分:
main(全局设置)、server(主机设置)、upstream(负载均衡服务器设置)、location(URL匹配特定位置的设置) main部分设置的指令将影响其他所有设置; server部分的指令主要用于指定主机和端口; upstream指令主要用于负载均衡,设置一系列的后端服务器; location部分用于匹配网页位置;
Nginx安装环境及模块的依赖性
准备开发环境"Development Tools" "Server Platform Deveopment" gzip模块需要->zlib 库 rewrite模块需要->pcre 库 ssl功能需要->openssl库
Nginx目前可分为三个版本:开发版、稳定版、历史稳定版
开发板:开发版更新较快,包含新功能及修复Bug,同时可能会产生新的Bug。 稳定版:稳定版更新较慢,各种功能健全,可用于生产环境。 历史版:历史版是稳定版的汇总,不包含开发版的新功能。
案例构建
第一步:准备开发环境、编译安装pcre(支持HTTP Rewrite功能)及解决编译安装Nginx所依赖的软件包
# yum groupinstall "Development Tools" "Server Platform Deveopment" -y # yum install openssl-devel pcre-devel # tar xf pcre-8.10.tar.gz # cd pcre-8.10 # ./configure # make && make install
第二步:源码编译安装Nginx
◆ 首先添加用户nginx,实现以之运行nginx服务进程:
# groupadd -r nginx # useradd -r -g nginx nginx
◆ 修改Nginx相关属性信息及编译安装Nginx
# ./configure \ --prefix=/usr \ --sbin-path=/usr/sbin/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 \ --lock-path=/var/lock/nginx.lock \ --user=nginx \ --group=nginx \ --with-http_ssl_module \ --with-http_flv_module \ --with-http_stub_status_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/ \ --http-uwsgi-temp-path=/var/tmp/nginx/uwsgi \ --http-scgi-temp-path=/var/tmp/nginx/scgi \ --with-pcre # make && make install
第三步:为Nginx提供编写SysV 脚本
#!/bin/sh # # nginx - this script starts and stops the nginx 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 nginx on # service nginx restart # netstat -tpln
◆测试Nginx是否提供WEB服务(test:Windows:192.168.0.39)
第四步:安装MySQL(这里采用通用二进制安装MySQL作为演示)
◆ 创建逻辑卷用于存放MySQL安装目录
# fdisk /dev/sda [/dev/sda5(type:8e)] # reboot # pvcreate /dev/sda5 # vgcreate myvg /dev/sda5 # lvcreate -L 1G -n mydata myvg # lvscan ##查看逻辑卷相关信息 # mkfs.ext4 /dev/myvg/mydata
◆ 创建目录用于挂载逻辑卷,用于存放mysql数据目录并创建mysql组和mysql用户,主要用于启动、停止mysqld进程
# mkdir /mydata # vim /etc/fstab ##开机自动挂载 /dev/myvg/mydata /mydata ext4 default 0 0 # mount -a ##重新读取/etc/fstab文件,并重新挂载 # mkdir /mydata/data # groupadd -g 3306 mysql # adduser -g 3306 -u 3306 -s /sbin/nologin mysql # chown -R mysql.mysql /mydata/data
◆ 下载mysql通用二进制,并解压,修改属主和数组,并完成初始化工作
# tar xf mysql-5.6.10-linux-glibc2.5-x86_64.tar.gz -C /usr/local/ # cd /usr/local # ln -sv mysql-5.6.10-linux-glibc2.5-x86_64 mysql # cd mysql # chown -R root.mysql ./* # scripts/mysql_install_db --user=mysql --datadir=/mydata/data/
◆ 将mysql本地变量改为环境变量
手动创建配置文件/etc/profile.d/mysql.sh,添加如下内容: export PATH=$PATH:/usr/local/mysql/bin # . /etc/profile.d/mysql.sh ##重读配置文件,使之生效
◆ 为mysql提供配置文件及SysV脚本
# pwd /usr/local/mysql # vim /etc/my.cnf ##添加如下内容 datadir = /mydata/data ##数据目录 innodb_file_per_table = ON # cp support-files/mysql.server /etc/rc.d/init.d/mysqld # chkconfig --add mysqld # service mysqld restart # netstat -tupln | grep 3306
◆ 导出头文件及库文件,主要用于二次编译开发所使用
导出头文件 # ln -sv /usr/local/include /usr/include/mysql 导出库文件,编辑配置文件: # vim /etc/ld.so.conf.d/mysql.conf添加如下内容 /usr/local/mysql/bin # ldconfig -v ##重新加载库文件 导出man文档,编辑配置文件: # vim /etc/man.config 添加如下内容 MANPATH /usr/local/mysql/man
◆ 连接mysql服务器,测试下:
第五步:源码编辑安装PHP,实现FastCGI
◆ 安装环境:可以到附件中下载安装
如果想让编译的php支持mcrypt、mhash扩展和libevent,需要安装以下软件包 libmcrypt-2.5.8-9.el6.x86_64.rpm libmcrypt-devel-2.5.8-9.el6.x86_64.rpm mcrypt-2.6.8-3.el6.x86_64.rpm mhash-0.9.9.9-3.el6.x86_64.rpm mhash-devel-0.9.9.9-3.el6.x86_64.rpm
◆ 编译安装php
# tar xf php-5.4.13.tar.bz2 # cd php-5.4.13 # ./configure --prefix=/usr/local/php \ --with-mysql=/usr/local/mysql --with-openssl --enable-fpm \ --enable-sockets --enable-sysvshm --with-mysqli=/usr/local/mysql/bin/mysql_config \ --enable-mbstring --with-freetype-dir --with-jpeg-dir --with-png-dir --with-zlib-dir \ --with-libxml-dir=/usr --enable-xml --with-mhash --with-mcrypt --with-config-file-path=/etc \ --with-config-file-scan-dir=/etc/php.d --with-bz2 --with-curl
注:由于平台环境不一样,可能在修改属性的时候,报各种各样的错误,大家可以根据错误信息进行排查,一般都可以解决。
笔者在安装的时候提示需要依赖这些软件包:libxml2-devel、zlib-devel、bzip2-devel、xml2-config、python-magic
◆ 下一步,编译及编译安装
# make && make install
◆ 为php提供主配置文件
# cp php.ini-production /etc/php.ini
◆ 为php-fpm提供Sysv init脚本,并将其添加至服务列表:
# pwd /root/php-5.4.13 # cp sapi/fpm/init.d.php-fpm /etc/rc.d/init.d/php-fpm # chmod +x /etc/rc.d/init.d/php-fpm # chkconfig --add php-fpm # chkconfig php-fpm on
◆ 为php-fpm提供配置文件:
# cp /usr/local/php/etc/php-fpm.conf.default /usr/local/php/etc/php-fpm.conf
◆ 编辑php-fpm的配置文件,配置fpm的相关选项为你所需要的值,并启用pid文件:
pm.max_children = 150 pm.start_servers = 8 pm.min_spare_servers = 5 pm.max_spare_servers = 10 pid = /usr/local/php/var/run/php-fpm.pid
◆ 启动php-fpm进程,并使用如下命令来验正(如果此命令输出有中几个php-fpm进程就说明启动成功了):
# service php-fpm restart # ps aux | grep php-fpm
◆ 编辑/etc/nginx/nginx.conf,整合nginx和php,并启用如下选项:
# vim /etc/nginx/nginx.conf ##启用如下选项: location ~ \.php$ { root html; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; include fastcgi_params; }
◆ 编辑/etc/nginx/fastcgi_params,将其内容更改为如下内容:
编辑/etc/nginx/fastcgi_params,将其内容更改为如下内容: fastcgi_param GATEWAY_INTERFACE CGI/1.1; fastcgi_param SERVER_SOFTWARE nginx; fastcgi_param QUERY_STRING $query_string; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param REQUEST_URI $request_uri; fastcgi_param DOCUMENT_URI $document_uri; fastcgi_param DOCUMENT_ROOT $document_root; fastcgi_param SERVER_PROTOCOL $server_protocol; fastcgi_param REMOTE_ADDR $remote_addr; fastcgi_param REMOTE_PORT $remote_port; fastcgi_param SERVER_ADDR $server_addr; fastcgi_param SERVER_PORT $server_port; fastcgi_param SERVER_NAME $server_name;
◆ 并在所支持的主页面格式中添加php格式的主页:
location / { root /web/htdocs; index index.php index.html index.htm; }
◆ 当配置文件发生变化时,需重新载入nginx的配置文件
# service nginx reload
◆ 创建php测试页面:
# mkdir /web/htdocs -pv # cat > /web/htdocs/index.php << EOF <h1>PHP Test Page</h1> <?php phpinfo(); ?>
◆ 通过window浏览器测试,看Nginx是否支持php页面:
第六步:PHP与MySQL结合,测试MySQL是否提供服务(提供测试页面)
◆ 设置MySQL的登录root密码及创建测试页面:
# mysqladmin -u root -h localhost password 'mysql' -p ##设置MySQL的root用户密码 编辑/web/htdocs/index.php,修改如下内容: <h1>PHP Test Page</h1> <?php $conn=mysql_connect('localhost','root','mysql'); if ($conn) echo "<h2> Mysql Working....</h2>"; else echo "<h2> Mysql not Working...</h2>"; phpinfo(); ?>
◆ 当前mysql进程处于运行状态,测试:
[root@master ~]# service mysqld status MySQL running (17494) [ OK ] [root@master ~]#
◆ 当前mysql进程处于停止状态,测试:
[root@master mysql]# /etc/init.d/mysqld stop Shutting down MySQL.. [ OK ]
注:以上测试,说明MySQL正常运行,而且属于工作状态!!!
第七步:、安装Xcache,为php加速:
◆ 编译安装Xcache
# tar xf xcache-3.0.1.tar.bz2 # cd xcache-3.0.1 # /usr/local/php/bin/phpize # ./configure --enable-xcache --with-php-config=/usr/local/php/bin/php-config # make && make install
◆ 编辑php.ini,整合php和xcache
首先将xcache提供的样例配置导入php.ini # mkdir /etc/php.d # cp xcache.ini /etc/php.d
◆ 编辑/etc/php.d/xcache.ini,找到extension开头的行,修改为如下行:
extension = /usr/local/php/lib/php/extensions/no-debug-non-zts-20100525/xcache.so
◆ 重新启动php-fpm进程
# service php-fpm restart # chkconfig php-fpm on
◆ 测试
一:添加upstream模块提供后端服务器负载均衡及健康状况监测:
环境:新增两台基于apache提供的web服务,基于安全因素、性能考虑,通过nginx反向代理upstream模块实现负载均衡及SSL功能:
◆ 两台web程序服务器IP地址分配情况:
webserver1 172.16.88.10/16 webserver2 172.16.88.11/16
◆ 安装http软件包提供测试页面
注:前提两台web应用程序服务器提供ssh互信及并将主机名与IP地址对应关系,添加到/etc/hosts文件中,否则在启动httpd进程会有警告信息。
webserver1 # yum install httpd -y # echo "webserver1.example.com" > /var/www/html/index.html # service httpd restart && chkconfig httpd on # ssh webserver2 'yum install httpd -y " # ssh webserver2 "echo "webserver2.example.com" > /var/www/html/index.html" # ssh webserver2 'service httpd restart && chkconfig httpd on'
◆ 修改nginx主配置文件,添加upstream模块来提供后端web应用程序负载均衡
# vim /etc/nginx/nginx.conf upstream services { server 172.16.88.10 weight=1 max_fails=2 fail_timeout=2; server 172.16.88.11 weight=1 max_fails=2 fail_timeout=2; } server { location / { proxy_pass http://services/; } } # nginx -t && service nginx reload ##检查语法并重新加载配置文件
◆ 相关知识点补充:
HTTP Upstream模块中,可以通过server指令来指定后端服务器的IP地址和端口,同时还可以设定每个后端服务器在负载均衡调度中的状态。 down:表示当前的server暂时不参与负载均衡 backup:预留的备份机器。当其他所有的非backup机器出现故障或者繁忙时,才会请求backup机器,因此backup机器的压力最轻。 max_fails:允许请求失败的最大次数,默认为1.当超过最大次数时,则返回proxy_next_upstream模块定义的错误。 fail_timeout:当max_fails失败后,所暂停服务器的时间。max_fails可以和fail_timeout一起使用。
◆ 测试(Windows-192.168.0.212):
在浏览器上输入:http://172.16.88.88/,nginx代理服务器会将请求发往后端web服务器组中的某台应用服务器,由后端的某台应用服务器给予响应。 因为两台web服务在同一个组中,而且权值一样,所以会平均提供web服务。当其中一台web服务发生故障,另一台正常提供web服务,不影响用户请求。当web服务从 故障状态转换为正常状态时,nginx会自动添加到组里面,并提供服务。
◆ 模拟其中一台web程序服务器宕机,然后在进行测试,我们会发现只有一台应用服务器提供web服务器
webserver1->172.16.88.10 # service httpd stop
◆ 如果两台web应用程序服务器都发生宕机,那该如何提供web响应页面呢:
那么只要添加一台备用服务器,接收用户请求并响应web错误页面给用户(这里使用nginx代理服务器本身作为backup服务器)
# vim /etc/nginx/nginx.conf 添加如下内容 server 127.0.0.1:8080 weight=1 backup; # nginx -t && service nginx reload
◆ 在niginx代理服务器上提供web服务器,并提供错误页面信息
# mkdir /web/erro # echo "Erro Page Please Try Later" > /web/erro/index.html
◆ 模拟天台web应用程序服务器宕机并测试
webserver1# service httpd stop # ssh webserver2 'service httpd stop'