lnmmp

为什么选择Nginx?因为它具有以下特点:

(1)更快

这表现在两个方面:一方面,在正常情况下,单次请求会得到更快的响应;另一方面, 在高峰期(如有数以万计的并发请求),Nginx可以比其他Web服务器更快地响应请求。

实际上,本书第三部分中大量的篇幅都是在说明Nginx是如何做到这两点的。

(2)高扩展性

Nginx的设计极具扩展性,它完全是由多个不同功能、不同层次、不同类型且耦合度极低的模块组成。因此,当对某一个模块修复Bug或进行升级时,可以专注于模块自身,无须 在意其他。而且在HTTP模块中,还设计了 HTTP过滤器模块:一个正常的HTTP模块在处 理完请求后,会有一串HTTP过滤器模块对请求的结果进行再处理。这样,当我们开发一个 新的HTTP模块时,不但可以使用诸如HTTP核心模块、events模块、log模块等不同层次 或者不同类型的模块,还可以原封不动地复用大量已有的HTTP过滤器模块。这种低耦合度 的优秀设计,造就了 Ngimc庞大的第三方模块,当然,公开的第三方模块也如官方发布的模 块一样容易使用。

Nginx的模块都是嵌入到二进制文件中执行的,无论官方发布的模块还是第三方模块都 是如此。这使得第三方模块一样具备极其优秀的性能,充分利用Nginx的高并发特性,因 此,许多高流量的网站都倾向于开发符合自己业务特性的定制模块。

(3)髙可靠性

高可靠性是我们选择Nginx的最基本条件,因为Nginx的可靠性是大家有目共睹的,很 多家高流量网站都在核心服务器上大规模使用Nginx。Nginx的高可靠性来自于其核心框架 代码的优秀设计、模块设计的简单性;另外,官方提供的常用模块都非常稳定,每个worker 进程相对独立,master进程在1个worker进程出错时可以快速“拉起”新的worker子进程


(4)低内存消耗

一般情况下,10 000个非活跃的HTTP Keep-Alive连接在Nginx中仅消耗2.5MB的内 存,这是Nginx支持髙并发连接的基础。

从第3章开始,我们会接触到Nginx在内存中为了维护一个HTTP连接所分配的对象, 届时将会看到,实际上Nginx—直在为用户考虑(尤其是在髙并发时)如何使得内存的消耗

更少。

(5)单机支持10万以上的并发连接

这是一个非常重要的特性!随着互联网的迅猛发展和互联网用户数量的成倍增长,各大 公司、网站都需要应付海量并发请求,一个能够在峰值期顶住10万以上并发请求的Server, 无疑会得到大家的青睐。理论上,Nginx支持的并发连接上限取决于内存,10万远未封顶。 当然,能够及时地处理更多的并发请求,是与业务特点紧密相关的,本书第811章将会 详细说明如何实现这个特点。


(6)热部署

master管理进程与worker工作进程的分离设计,使得Nginx能够提供热部署功能,即 可以在7X24小时不间断服务的前提下,升级Nginx的可执行文件。当然,它也支持不停止 服务就更新配置项、更换日志文件等功能。

(7)最自由的BSD许可协议

这是Nginx可以快速发展的强大动力。BSD许可协议不只是允许用户免费使用Nginx,它还允许用户在自己的项目中直接使用或修改Nginx源码,然后发布。这吸引了无数开发者 继续为Nginx贡献自己的智慧。


以上7个特点当然不是Nginx的全部,拥有无数个官方功能模块、第三方功能模块使得 Nginx能够满足绝大部分应用场景,这些功能模块间可以叠加以实现更加强大、复杂的功能, 有些模块还支持Nginx与Perl、Lua等脚本语言集成工作,大大提高了开发效率。这些特点 促使用户在寻找一个Web服务器时更多考虑Nginx。

当然,选择Nginx的核心理由还是它能在支持髙并发请求的同时保持髙效的服务。

如果Web服务器的业务访问量巨大,就需要保证在数以百万计的请求同时访问服务时, 用户可以获得良好的体验,不会出现并发访问量达到一个数字后,新的用户无法获取服务, 或者虽然成功地建立起了 TCP连接,但大部分请求却得不到响应的情况。

通常,高峰期服务器的访问量可能是正常情况下的许多倍,若有热点事件的发生,可能 会导致正常情况下非常顺畅的服务器直接“挂死”。然而,如果在部署服务器时,就预先针 对这种情况进行扩容,又会使得正常情况下所有服务器的负载过低,这会造成大量的资源浪 费。因此,我们会希望在这之间取得平衡,也就是说,在低并发压力下,用户可以获得高速 体验,而在髙并发压力下,更多的用户都能接入,可能访问速度会下降,但这只应受制于带 宽和处理器的速度,而不应该是服务器设计导致的软件瓶颈。事实上,由于中国互联网用户群体的数量巨大,致使对Web服务器的设计往往要比欧美 公司更加困难。例如,对于全球性的一些网站而言,欧美用户分布在两个半球,欧洲用户活 跃时,美洲用户通常在休息,反之亦然。而国内巨大的用户群体则对业界的程序员提出更高 的挑战,早上9点和晚上20点到24点这些时间段的并发请求压力是非常巨大的。尤其节假 日、寒暑假到来之时,更会对服务器提出极髙的要求。

另外,国内业务上的特性,也会引导用户在同一时间大并发地访问服务器。例如,许多 SNS网页游戏会在固定的时间点刷新游戏资源或者允许“偷菜”等好友互动操作。这些会导 致服务器处理髙并发请求的压力增大.

上述情形都对我们的互联网服务在大并发压力下是否还能够给予用户良好的体验提出了 更髙的要求。若要提供更好的服务,那么可以从多方面入手,例如,修改业务特性、引导用 户从高峰期分流或者把服务分层分级、对于不同并发压力给用户提供不同级别的服务等。但 最根本的是,Web服务器要能支持大并发压力下的正常服务,这才是关键。
快速增长的互联网用户群以及业内所有互联网服务提供商越来越好的用户体验,都促使 我们在大流量服务中用Nginx取代其他Web服务器^ Nginx先天的事件驱动型设计、全异步

的网络I/O处理机制、极少的进程间切换以及许多优化设计,都使得Nginx天生善于处理 髙并发压力下的互联网请求,同时Nginx降低了资源消耗,可以把服务器硬件资源“压榨” 到极致。




一、安装Nginx:

1、解决依赖关系

# yum groupinstall "Development Tools" "Server Platform Deveopment"
# yum install openssl-devel pcre-devel

2、安装

首先添加用户nginx,实现以之运行nginx服务进程:

# groupadd -r nginx
# useradd -r -g 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

说明:
1、Nginx可以使用Tmalloc(快速、多线程的malloc库及优秀性能分析工具)来加速内存分配,使用此功能需要事先安装gperftools,而后在编译nginx添加--with-google_perftools_module选项即可。
2、如果想使用nginx的perl模块,可以通过为configure脚本添加--with-http_perl_module选项来实现,但目前此模块仍处于实验性使用阶段,可能会在运行中出现意外,因此,其实现方式这里不再介绍。如果想使用基于nginx的cgi功能,也可以基于FCGI来实现,具体实现方法请参照网上的文档。

3、为nginx提供SysV init脚本:

新建文件/etc/rc.d/init.d/nginx,内容如下:

#!/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 start

Nginx的代码是由一个核心和一系列的模块组成, 核心主要用于提供Web Server的基本功能,以及Web和Mail反向代理的功能;还用于启用网络协议,创建必要的运行时环境以及确保不同的模块之间平滑地进行交互。不过,大多跟协议相关的功能和某应用特有的功能都是由nginx的模块实现的。这些功能模块大致可以分为事件模块、阶段性处理器、输出过滤器、变量处理器、协议、upstream和负载均衡几个类别,这些共同组成了nginx的http功能。事件模块主要用于提供OS独立的(不同操作系统的事件机制有所不同)事件通知机制如kqueue或epoll等。协议模块则负责实现nginx通过http、tls/ssl、smtp、pop3以及imap与对应的客户端建立会话。

Nginx的核心模块为Main和Events,此外还包括标准HTTP模块、可选HTTP模块和邮件模块,其还可以支持诸多第三方模块。Main用于配置错误日志、进程及权限等相关的参数,Events用于配置IO模型,如epoll、kqueue、select或poll等,它们是必备模块。

Nginx的主配置文件由几个段组成,这个段通常也被称为nginx的上下文,每个段的定义格式如下所示。需要注意的是,其每一个指令都必须使用分号(;)结束,否则为语法错误。

<section> {
   <directive> <parameters>;
}

2.1 配置main模块

下面说明main模块中的几个关键参数。

2.1.1 error_log

用于配置错误日志,可用于main、http、server及location上下文中;语法格式为:

error_log file | stderr [ debug | info | notice | warn | error | crit | alert | emerg ]

如果在编译nginx时使用了--with-debug选项,还可以使用如下格式打开调试功能。

error_log LOGFILE [debug_core | debug_alloc | debug_mutex | debug_event | debug_http | debug_imap];

要禁用错误日志,不能使用“error_log off;”,而要使用类似如下选项:

error_log /dev/null crit;

2.1.2 timer_resolution

用于降低gettimeofday()系统调用的次数。默认情况下,每次从kevent()、epoll、/dev/poll、select()或poll()返回时都会执行此系统调用。语法格式为:

timer_resolution interval

例如:

timer_resolution  100ms;

2.1.3 worker_cpu_affinity

通过sched_setaffinity()将worker绑定至CPU上,只能用于main上下文。语法格式为:

worker_cpu_affinity cpumask ...

例如:
worker_processes     4;
worker_cpu_affinity 0001 0010 0100 1000;

2.1.4 worker_priority

为worker进程设定优先级(指定nice值),此参数只能用于main上下文中,默认为0;语法格式为:

worker_priority number

2.1.5 worker_processes

worker进程是单线程进程。如果Nginx用于CPU密集型的场景中,如SSL或gzip,且主机上的CPU个数至少有2个,那么应该将此参数值设定为与CPU核心数相同;如果Nginx用于大量静态文件访问的场景中,且所有文件的总大小大于可用内存时,应该将此参数的值设定得足够大以充分利用磁盘带宽。

此参数与Events上下文中的work_connections变量一起决定了maxclient的值:
maxclients = work_processes * work_connections

2.1.6 worker_rlimit_nofile

设定worker进程所能够打开的文件描述符个数的最大值。语法格式:

worker_rlimit_nofile number

2.2 配置Events模块

2.2.1 worker_connections

设定每个worker所处理的最大连接数,它与来自main上下文的worker_processes一起决定了maxclients的值。

max clients = worker_processes * worker_connections

而在反向代理场景中,其计算方法与上述公式不同,因为默认情况下浏览器将打开2个连接,而nginx会为每一个连接打开2个文件描述符,因此,其maxclients的计算方法为:

max clients = worker_processes * worker_connections/4

2.2.2 use

在有着多于一个的事件模型IO的应用场景中,可以使用此指令设定nginx所使用的IO机制,默认为./configure脚本选定的各机制中最适用当前OS的版本。语法格式:

use [ kqueue | rtsig | epoll | /dev/poll | select | poll | eventport ]

2.3 一个配置示例

user nginx;
# the load is CPU-bound and we have 16 cores
worker_processes 16;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
events {
    use epoll;
    worker_connections 2048;
}


2.4 HTTP服务的相关配置

http上下文专用于配置用于http的各模块,此类指令非常的多,每个模块都有其专用指定,具体请参数nginx官方wiki关于模块部分的说明。大体上来讲,这些模块所提供的配置指令还可以分为如下几个类别。

客户端类指令:如client_body_buffer_size、client_header_buffer_size、client_header_timeout和keepalive_timeout等;
文件IO类指令:如aio、directio、open_file_cache、open_file_cache_min_uses、open_file_cache_valid和sendfile等;
hash类指令:用于定义Nginx为某特定的变量分配多大的内存空间,如types_hash_bucket_size、server_names_hash_bucket_size和variables_hash_bucket_size等;
套接字类指令:用于定义Nginx如何处理tcp套接字相关的功能,如tcp_nodelay(用于keepalive功能启用时)和tcp_nopush(用于sendfile启用时)等;

2.5 虚拟服务器相关配置

server {
   <directive> <parameters>;
}

用于定义虚拟服务器相关的属性,常见的指令有backlog、rcvbuf、bind及sndbuf等。

2.6 location相关的配置

location [modifier] uri {...} 或 location @name {…}

通常用于server上下文中,用于设定某URI的访问属性。location可以嵌套。

The prefix "@" specifies a named location. Such locations are not used during normal processing of requests, they are intended only to process internally redirected requests (see error_page, try_files). 如下面关于memcached的相关配置。

server {
  location / {
    set $memcached_key $uri;
    memcached_pass     name:11211;
    default_type       text/html;
    error_page         404 @fallback;
  }
  location @fallback {
    proxy_pass http://backend;
  }
}

三、Nginx反向代理

Nginx通过proxy模块实现反向代理功能。在作为web反向代理服务器时,nginx负责接收客户请求,并能够根据URI、客户端参数或其它的处理逻辑将用户请求调度至上游服务器上(upstream server)。nginx在实现反向代理功能时的最重要指令为proxy_pass,它能够将location定义的某URI代理至指定的上游服务器(组)上。如下面的示例中,location的/uri将被替换为上游服务器上的/newuri。

location /uri {
    proxy_pass http://www.magedu.com:8080/newuri;
}

不过,这种处理机制中有两个例外。一个是如果location的URI是通过模式匹配定义的,其URI将直接被传递至上游服务器,而不能为其指定转换的另一个URI。例如下面示例中的/forum将被代理为http://www.magedu.com/forum。

   location ~ ^/bbs {
       proxy_pass http://www.magedu.com;
   }

第二个例外是,如果在loation中使用的URL重定向,那么nginx将使用重定向后的URI处理请求,而不再考虑上游服务器上定义的URI。如下面所示的例子中,传送给上游服务器的URI为/index.php?page=<match>,而不是/index。

   location / {
       rewrite /(.*)$ /index.php?page=$1 break;
       proxy_pass http://localhost:8080/index;
   }

3.1 proxy模块的指令

proxy模块的可用配置指令非常多,它们分别用于定义proxy模块工作时的诸多属性,如连接超时时长、代理时使用http协议版本等。下面对常用的指令做一个简单说明

proxy_connect_timeout:nginx将一个请求发送至upstream server之前等待的最大时长;
proxy_cookie_domain:将upstream server通过Set-Cookie首部设定的domain属性修改为指定的值,其值可以为一个字符串、正则表达式的模式或一个引用的变量;
proxy_cookie_path: 将upstream server通过Set-Cookie首部设定的path属性修改为指定的值,其值可以为一个字符串、正则表达式的模式或一个引用的变量;
proxy_hide_header:设定发送给客户端的报文中需要隐藏的首部;
proxy_pass:指定将请求代理至upstream server的URL路径;
proxy_set_header:将发送至upsream server的报文的某首部进行重写;
proxy_redirect:重写location并刷新从upstream server收到的报文的首部;
proxy_send_timeout:在连接断开之前两次发送至upstream server的写操作的最大间隔时长;
proxy_read_timeout:在连接断开之前两次从接收upstream server接收读操作的最大间隔时长;

如下面的一个示例:

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;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 30;
proxy_send_timeout 15;
proxy_read_timeout 15;

3.2 upstream模块

与proxy模块结合使用的模块中,最常用的当属upstream模块。upstream模块可定义一个新的上下文,它包含了一组宝岛upstream服务器,这些服务器可能被赋予了不同的权重、不同的类型甚至可以基于维护等原因被标记为down。

upstream模块常用的指令有:
ip_hash:基于客户端IP地址完成请求的分发,它可以保证来自于同一个客户端的请求始终被转发至同一个upstream服务器;
keepalive:每个worker进程为发送到upstream服务器的连接所缓存的个数;
least_conn:最少连接调度算法;
server:定义一个upstream服务器的地址,还可包括一系列可选参数,如:
weight:权重;
max_fails:最大失败连接次数,失败连接的超时时长由fail_timeout指定;
fail_timeout:等待请求的目标服务器发送响应的时长;
backup:用于fallback的目的,所有服务均故障时才启动此服务器;
down:手动标记其不再处理任何请求;

例如:

    upstream backend {
      server www.magedu.com weight=5;
      server www2.magedu.com:8080       max_fails=3  fail_timeout=30s;
    }
upstream模块的负载均衡算法主要有三种,轮调(round-robin)、ip哈希(ip_hash)和最少连接(least_conn)三种。
此外,upstream模块也能为非http类的应用实现负载均衡,如下面的示例定义了nginx为memcached服务实现负载均衡之目的。
    upstream memcachesrvs {
        server 172.16.100.6:11211;
        server 172.16.100.7:11211;
    }
    server {
        location / {
        set $memcached_key "$uri?$args";
        memcached_pass memcachesrvs;
        error_page 404 = @fallback;
        }
        location @fallback {
                proxy_pass http://127.0.0.1:8080;
        }
    }

3.3 if判断语句

在location中使用if语句可以实现条件判断,其通常有一个return语句,且一般与有着last或break标记的rewrite规则一同使用。但其也可以按需要使用在多种场景下,需要注意的是,不当的使用可能会导致不可预料的后果。

location / {
    if ($request_method == “PUT”) {
        proxy_pass http://upload.magedu.com:8080;
    }
    if ($request_uri ~ "\.(jpg|gif|jpeg|png)$") {
        proxy_pass http://imageservers;
        break;
    }
}
upstream imageservers {
    server 172.16.100.8:80 weight 2;
    server 172.16.100.9:80 weight 3;
}

3.3.1 if语句中的判断条件

正则表达式匹配:
   ~:与指定正则表达式模式匹配时返回“真”,判断匹配与否时区分字符大小写;
   ~*:与指定正则表达式模式匹配时返回“真”,判断匹配与否时不区分字符大小写;
   !~:与指定正则表达式模式不匹配时返回“真”,判断匹配与否时区分字符大小写;
   !~*:与指定正则表达式模式不匹配时返回“真”,判断匹配与否时不区分字符大小写;

文件及目录匹配判断:
   -f, !-f:判断指定的路径是否为存在且为文件;
   -d, !-d:判断指定的路径是否为存在且为目录;
   -e, !-e:判断指定的路径是否存在,文件或目录均可;
   -x, !-x:判断指定路径的文件是否存在且可执行;

3.3.2 nginx常用的全局变量

下面是nginx常用的全局变量中的一部分,它们经常用于if语句中实现条件判断。

$args
$content_length
$content_type
$document_root
$document_uri
$host
$http_user_agent
$http_cookie
$limit_rate
$request_body_file
$request_method
$remote_addr
$remote_port
$remote_user
$request_filename
$request_uri
$query_string
$scheme
$server_protocol
$server_addr
$server_name
$server_port
$uri

四、反向代理性能优化

在反向代理场景中,nginx有一系列指令可用于定义其工作特性,如缓冲区大小等,给这些指令设定一个合理的值,可以有效提升其性能。

4.1 缓冲区设定

nginx在默认情况下在将其响应给客户端之前会尽可能地接收来upstream服务器的响应报文,它会将这些响应报文存暂存于本地并尽量一次性地响应给客户端。然而,在来自于客户端的请求或来自upsteam服务器的响应过多时,nginx会试图将之存储于本地磁盘中,这将大大降低nginx的性能。因此,在有着更多可用内存的场景中,应该将用于暂存这些报文的缓冲区调大至一个合理的值。

proxy_buffer_size size:设定用于暂存来自于upsteam服务器的第一个响应报文的缓冲区大小;
proxy_buffering on|off:启用缓冲upstream服务器的响应报文,否则,如果proxy_max_temp_file_size指令的值为0,来自upstream服务器的响应报文在接收到的那一刻将同步发送至客户端;一般情况下,启用proxy_buffering并将proxy_max_temp_file_size设定为0能够启用缓存响应报文的功能,并能够避免将其缓存至磁盘中;
proxy_buffers 8 4k|8k:用于缓冲来自upstream服务器的响应报文的缓冲区大小;



4.2 缓存
nginx做为反向代理时,能够将来自upstream的响应缓存至本地,并在后续的客户端请求同样内容时直接从本地构造响应报文。

proxy_cache zone|off:定义一个用于缓存的共享内存区域,其可被多个地方调用;缓存将遵从upstream服务器的响应报文首部中关于缓存的设定,如 "Expires""Cache-Control: no-cache""Cache-Control: max-age=XXX""private""no-store"等,但nginx在缓存时不会考虑响应报文的"Vary"首部。为了确保私有信息不被缓存,所有关于用户的私有信息可以upstream上通过"no-cache"or "max-age=0"来实现,也可在nginx设定proxy_cache_key必须包含用户特有数据如$cookie_xxx的方式实现,但最后这种方式在公共缓存上使用可能会有风险。因此,在响应报文中含有以下首部或指定标志的报文将不会被缓存。
Set-Cookie
Cache-Control containing "no-cache", "no-store", "private", or a "max-age"with a non-numeric or 0 value
Expires with a timeinthe past
X-Accel-Expires: 0
proxy_cache_key:设定在存储及检索缓存时用于“键”的字符串,可以使用变量为其值,但使用不当时有可能会为同一个内容缓存多次;另外,将用户私有信息用于键可以避免将用户的私有信息返回给其它用户;
proxy_cache_lock:启用此项,可在缓存未命令中阻止多个相同的请求同时发往upstream,其生效范围为worker级别;
proxy_cache_lock_timeout:proxy_cache_lock功能的锁定时长;
proxy_cache_min_uses:某响应报文被缓存之前至少应该被请求的次数;
proxy_cache_path:定义一个用记保存缓存响应报文的目录,及一个保存缓存对象的键及响应元数据的共享内存区域(keys_zone=name:size),其可选参数有:
levels:每级子目录名称的长度,有效值为1或2,每级之间使用冒号分隔,最多为3级;
inactive:非活动缓存项从缓存中剔除之前的最大缓存时长;
max_size:缓存空间大小的上限,当需要缓存的对象超出此空间限定时,缓存管理器将基于LRU算法对其进行清理;
loader_files:缓存加载器(cache_loader)的每次工作过程最多为多少个文件加载元数据;
loader_sleep:缓存加载器的每次迭代工作之后的睡眠时长;
loader_threashold:缓存加载器的最大睡眠时长;
例如:  proxy_cache_path  /data/nginx/cache/onelevels=1      keys_zone=one:10m;
proxy_cache_path  /data/nginx/cache/twolevels=2:2    keys_zone=two:100m;
proxy_cache_path  /data/nginx/cache/threelevels=1:1:2  keys_zone=three:1000m;
proxy_cache_use_stale:在无法联系到upstream服务器时的哪种情形下(如error、timeout或http_500等)让nginx使用本地缓存的过期的缓存对象直接响应客户端请求;其格式为:
proxy_cache_use_stale error | timeout | invalid_header | updating | http_500 | http_502 | http_503 | http_504 | http_404 | off
proxy_cache_valid [ code ...] time:用于为不同的响应设定不同时长的有效缓存时长,例如:proxy_cache_valid  200 302  10m;
proxy_cache_methods [GET HEAD POST]:为哪些请求方法启用缓存功能;
proxy_cache_bypass string:设定在哪种情形下,nginx将不从缓存中取数据;例如:
proxy_cache_bypass $cookie_nocache $arg_nocache $arg_comment;
proxy_cache_bypass $http_pragma $http_authorization;

4.2.1 使用示例

http {
    proxy_cache_path  /data/nginx/cache  levels=1:2    keys_zone=STATIC:10m
                                         inactive=24h  max_size=1g;
    server {
        location / {
            proxy_pass             http://www.magedu.com;
            proxy_set_header       Host $host;
            proxy_cache            STATIC;
            proxy_cache_valid      200  1d;
            proxy_cache_valid       301 302 10m;
            proxy_cache_vaild        any 1m;
            proxy_cache_use_stale  error timeout invalid_header updating
                                   http_500 http_502 http_503 http_504;
        }
    }
}


4.3 压缩

nginx将响应报文发送至客户端之前可以启用压缩功能,这能够有效地节约带宽,并提高响应至客户端的速度。通常编译nginx默认会附带gzip压缩的功能,因此,可以直接启用之。

http {
    gzip on;
    gzip_http_version 1.0;
    gzip_comp_level 2;
    gzip_types text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript application/json;
    gzip_disable msie6;
}

gzip_proxied指令可以定义对客户端请求哪类对象启用压缩功能,如“expired”表示对由于使用了expire首部定义而无法缓存的对象启用压缩功能,其它可接受的值还有“no-cache”、“no-store”、“private”、“no_last_modified”、“no_etag”和“auth”等,而“off”则表示关闭压缩功能。





五、配置示例

5.1 反向代理

server {
        listen       80;
        server_name  www.magedu.com;
        add_header X-Via $server_addr;
        location / {
            root   html;
            index  index.html index.htm;
            if ($request_method ~* "PUT") {
                proxy_pass http://172.16.100.12;
                break;
            }
        }
        location /bbs {
            proxy_pass http://172.16.100.11/;
        }
}

此例中,对http://www.magedu.com/bbs/的请求将被转发至http://172.16.100.11/这个URL,切记最后的/不应该省去;而/匹配的URL中请求方法为“PUT”时,将被转发至http://172.16.100.12/这个URL。

另外,add_header用于让nginx在响应给用户的报文中构造自定义首部,其使用格式为“add_header NAME VALUE”。

可以使用curl命令对配置好的服务进行请求,以验正其效果。如:

# curl -I http://www.magedu.com/bbs/
HTTP/1.1 200 OK
Server: nginx/1.4.1
Date: Tue, 14 May 2013 10:19:10 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 15
Connection: keep-alive
Last-Modified: Tue, 30 Apr 2013 09:34:09 GMT
ETag: "186e9f-f-b4076640"
X-Via: 172.16.100.107
Accept-Ranges: bytes


在后端服务器172.16.100.12上装载dav模块,并开放其dav功能,而后验正文件上传效果。开放dav功能的方法如下:

首先启用如下两个模块:
LoadModule dav_module modules/mod_dav.so
LoadModule dav_fs_module modules/mod_dav_fs.so

而后配置相应主机的目录如下所示,关键是其中的dav一行。
<Directory "/var/www/html">
   dav on
   Options Indexes FollowSymLinks
   Order allow,deny
   Allow from all
</Directory>
接着尝试访问代理服务器:

# curl -I -T /etc/inittab http://www.magedu.com/
HTTP/1.1 100 Continue
HTTP/1.1 201 Created
Server: nginx/1.4.1
Date: Tue, 14 May 2013 10:20:15 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 261
Location: http://172.16.100.107/inittab
Connection: keep-alive
X-Via: 172.16.100.107
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>201 Created</title>
</head><body>
<h1>Created</h1>
<p>Resource /inittab has been created.</p>
<hr />
<address>Apache/2.2.3 (Red Hat) Server at 172.16.100.12 Port 80</address>
</body></html>




5.2 启用缓存

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    proxy_cache_path /nginx/cache/first  levels=1:2   keys_zone=first:10m max_size=512m;
    server {
        listen       80;
        server_name  www.magedu.com;
        location / {
            root   html;
            index  index.html index.htm;
            if ($request_method ~* "PUT") {
                proxy_pass http://172.16.100.12;
                break;
            }
        }
        location /bbs {
            proxy_pass http://172.16.100.11/;
            proxy_cache first;
            proxy_cache_valid 200 1d;
            proxy_cache_valid 301 302 10m;
            proxy_cache_valid any 1m;
        }
    }
}

5.3 使用upstream

5.3.1 不启用缓存

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    upstream websrv {
        server 172.16.100.11 weight=1;
        server 172.16.100.12 weight=1;
        server 127.0.0.1:8080 backup;
    }
    server {
        listen       80;
        server_name  www.magedu.com;
        add_header X-Via $server_addr;
        location / {
            proxy_pass http://websrv;
            index  index.html index.htm;
            if ($request_method ~* "PUT") {
                proxy_pass http://172.16.100.12;
                break;
            }
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
    server {
        listen 8080;
        server_name localhost;
        root /nginx/htdocs;
        index index.html;
    }
}

测试效果:默认情况下,nginx对定义了权重的upstream服务器使用加权轮调的方法调度访问,因此,其多次访问应该由不同的服务器进行响应。如下所示。

# curl  http://172.16.100.107/
RS2.magedu.com

# curl  http://172.16.100.107/
RS1.magedu.com

根据上面的配置,如果172.16.100.11和172.16.100.12两个upstream服务器均宕机时,将由本地监听在8080端口的虚拟主机进行响应。
# curl  http://172.16.100.107/
Sorry...


5.3.2 为upstream启用缓存

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    proxy_cache_path /nginx/cache/first  levels=1:2   keys_zone=first:10m max_size=512m;
    upstream websrv {
        server 172.16.100.11 weight=1;
        server 172.16.100.12 weight=1;
        server 127.0.0.1:8080 backup;
    }
    server {
        listen       80;
        server_name  www.magedu.com;
        add_header X-Via $server_addr;
        add_header X-Cache-Status $upstream_cache_status;
        location / {
            proxy_pass http://websrv;
            proxy_cache first;
            proxy_cache_valid 200 1d;
            proxy_cache_valid 301 302 10m;
            proxy_cache_valid any 1m;
            index  index.html index.htm;
            if ($request_method ~* "PUT") {
                proxy_pass http://172.16.100.12;
                break;
            }
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
    server {
        listen 8080;
        server_name localhost;
        root /nginx/htdocs;
        index index.html;
    }
}

第一次访问某可缓存资源时,在本地缓存中尚未有其对应的缓存对象,因此,其一定为未命中状态。而第二次请求时,则可以直接从本地缓存构建响应报文。

# curl -I http://www.magedu.com/
HTTP/1.1 200 OK
Server: nginx/1.4.1
Date: Tue, 14 May 2013 10:53:07 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 15
Connection: keep-alive
Last-Modified: Tue, 30 Apr 2013 09:34:09 GMT
ETag: "186e9f-f-b4076640"
Accept-Ranges: bytes
X-Via: 172.16.100.107
X-Cache-Status: MISS
# curl -I http://www.magedu.com/
HTTP/1.1 200 OK
Server: nginx/1.4.1
Date: Tue, 14 May 2013 10:53:09 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 15
Connection: keep-alive
Last-Modified: Tue, 30 Apr 2013 09:34:09 GMT
ETag: "186e9f-f-b4076640"
X-Via: 172.16.100.107
X-Cache-Status: HIT
Accept-Ranges: bytes

六、nginx限速配置

nginx的限速功能通过limit_zone、limit_conn和limit_rate指令进行配置。首先需要在http上下文配置一个limit_zone,然后在需要的地方使用limit_conn和limit_rate 进行限速设置。下面是一个简单的例子。

http {
  limit_zone  first  $binary_remote_addr  10m;
  server {
    location /downloads/ {
      limit_conn   first  1;
      limit_rate 50k;
    }
  }
}

说明:
limit_zone:语法格式“limit_req_zone $variable zone=name:size rate=rate;”,实现针对每个IP定义一个存储session状态的容器。这个示例中定义了一个名叫first的10m大小的容器,这个名字会在后面的limit_conn中使用。
limit_conn first 1; 限制在first中记录状态的每个IP只能发起一个并发连接。
limit_rate 50k; 对每个连接限速50k. 注意,这里是对连接限速,而不是对IP限速。如果一个IP允许三个并发连接,那么这个IP就是限速为limit_rate×3,在设置的时候要根据自己的需要做设置调整,要不然会达不到自己希望的目的。



限制连接数的配置如下所示。

limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_conn_zone $server_name zone=perserver:10m;
server {
    ...
    limit_conn perip 10;
    limit_conn perserver 100;
}

七、一个完整配置例(生产环境中使用)

user                              nobody nobody;
worker_processes                  4;
worker_rlimit_nofile              51200;
error_log                         logs/error.log  notice;
pid                               /var/run/nginx.pid;
events {
  use                             epoll;
  worker_connections              51200;
}
http {
  server_tokens                   off;
  include                         mime.types;
  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;
  client_max_body_size          20m;
  client_body_buffer_size       256k;
  proxy_connect_timeout         90;
  proxy_send_timeout            90;
  proxy_read_timeout            90;
  proxy_buffer_size             128k;
  proxy_buffers                 4 64k;
  proxy_busy_buffers_size       128k;
  proxy_temp_file_write_size    128k;
  default_type                    application/octet-stream;
  charset                         utf-8;
  client_body_temp_path           /var/tmp/client_body_temp 1 2;
  proxy_temp_path                 /var/tmp/proxy_temp 1 2;
  fastcgi_temp_path               /var/tmp/fastcgi_temp 1 2;
  uwsgi_temp_path                 /var/tmp/uwsgi_temp 1 2;
  scgi_temp_path                  /var/tmp/scgi_temp 1 2;
  ignore_invalid_headers          on;
  server_names_hash_max_size      256;
  server_names_hash_bucket_size   64;
  client_header_buffer_size       8k;
  large_client_header_buffers     4 32k;
  connection_pool_size            256;
  request_pool_size               64k;
  output_buffers                  2 128k;
  postpone_output                 1460;
  client_header_timeout           1m;
  client_body_timeout             3m;
  send_timeout                    3m;
  log_format main                 '$server_addr $remote_addr [$time_local] $msec+$connection '
                                  '"$request" $status $connection $request_time $body_bytes_sent "$http_referer" '
                                  '"$http_user_agent" "$http_x_forwarded_for"';
  open_log_file_cache               max=1000 inactive=20s min_uses=1 valid=1m;
  access_log                      logs/access.log      main;
  log_not_found                   on;
  sendfile                        on;
  tcp_nodelay                     on;
  tcp_nopush                      off;
  reset_timedout_connection       on;
  keepalive_timeout               10 5;
  keepalive_requests              100;
  gzip                            on;
  gzip_http_version               1.1;
  gzip_vary                       on;
  gzip_proxied                    any;
  gzip_min_length                 1024;
  gzip_comp_level                 6;
  gzip_buffers                    16 8k;
  gzip_proxied                    expired no-cache no-store private auth no_last_modified no_etag;
  gzip_types                      text/plain application/x-javascript text/css application/xml application/json;
  gzip_disable                    "MSIE [1-6]\.(?!.*SV1)";
  upstream tomcat8080 {
    ip_hash;
    server                        172.16.100.103:8080 weight=1 max_fails=2;
    server                        172.16.100.104:8080 weight=1 max_fails=2;
    server                        172.16.100.105:8080 weight=1 max_fails=2;
  }
  server {
    listen                        80;
    server_name                   www.magedu.com;
    # config_apps_begin
    root                          /data/webapps/htdocs;
    access_log                    /var/logs/webapp.access.log     main;
    error_log                     /var/logs/webapp.error.log      notice;
    location / {
      location ~* ^.*/favicon.ico$ {
        root                      /data/webapps;
        expires                   180d;
        break;
      }
      if ( !-f $request_filename ) {
        proxy_pass                http://tomcat8080;
        break;
      }
    }
    error_page                    500 502 503 504  /50x.html;
      location = /50x.html {
      root                        html;
    }
  }
  server {
    listen                        8088;
    server_name                   nginx_status;
      location / {
          access_log                  off;
          deny                        all;
          return                      503;
      }
      location /status {
          stub_status                 on;
          access_log                  off;
          allow                       127.0.0.1;
          allow                       172.16.100.71;
          deny                        all;
      }
  }
}

          4、timer_resolution t;
               每次内核事件调用返回时,都会使用gettimeofday()来更新nginx缓存时钟;timer_resolution用于定义每隔多久才会由gettimeofday()更新一次缓存时钟;x86-64系统上,gettimeofday()代价已经很小,可以忽略此配置;

           5、worker_priority nice;
               -20,19之间的值;

       事件相关的配置
           1、accept_mutex [on|off]
               是否打开Ningx的负载均衡锁;此锁能够让多个worker进轮流地、序列化地与新的客户端建立连接;而通常当一个worker进程的负载达到其上限的7/8,master就尽可能不再将请求调度此worker;

           2、lock_file /path/to/lock_file;
               lock文件

           3、accept_mutex_delay #ms;
               accept锁模式中,一个worker进程为取得accept锁的等待时长;如果某worker进程在某次试图取得锁时失败了,至少要等待#ms才能再一次请求锁;

           4、multi_accept on|off;
               是否允许一次性地响应多个用户请求;默认为Off;

           5、use [epoll|rtsig|select|poll];
               定义使用的事件模型,建议让nginx自动选择;

           6、worker_connections #;
               每个worker能够并发响应最大请求数;

       用于调试、定位问题: 只调试nginx时使用
           1、daemon on|off;
               是否让ningx运行后台;默认为on,调试时可以设置为off,使得所有信息去接输出控制台;

           2、master_process on|off
               是否以master/worker模式运行nginx;默认为on;调试时可设置off以方便追踪;

           3、error_log /path/to/error_log level;
               错误日志文件及其级别;默认为error级别;调试时可以使用debug级别,但要求在编译时必须使用--with-debug启用debug功能;

       网络连接相关的设置:
           1、keepalive_timeout time;
               保持连接的超时时长;默认为75秒;

           2、keepalive_requests n;
               在一次长连接上允许承载的最大请求数;

           3、keepalive_disable [msie6 | safari | none ]
               对指定的浏览器禁止使用长连接;

           4、tcp_nodelay on|off
               对keepalive连接是否使用TCP_NODELAY选项;

           5、client_header_timeout time;
               读取http请求首部的超时时长;

           6、client_body_timeout time;
               读取http请求包体的超时时长;

           7、send_timeout time;
               发送响应的超时时长;

       对客户端请求的限制:
           1、limit_except method ... { ... }
               指定对范围之外的其它方法的访问控制;

               limit_except GET {
                   allow 172.16.0.0/16;
                   deny all;
               }

           2、client_max_body_size SIZE;
               http请求包体的最大值;常用于限定客户所能够请求的最大包体;根据请求首部中的Content-Length来检测,以避免无用的传输;

           3、limit_rate speed;
               限制客户端每秒钟传输的字节数;默认为0,表示没有限制;

           4、limit_rate_after time;
               nginx向客户发送响应报文时,如果时长超出了此处指定的时长,则后续的发送过程开始限速;

       文件操作的优化:
           1、sendfile on|off
               是否启用sendfile功能;

           2、aio on|off
               是否启用aio功能;

           3、open_file_cache max=N [inactive=time]|off
               是否打开文件缓存功能;
                   max: 缓存条目的最大值;当满了以后将根据LRU算法进行置换;
                   inactive: 某缓存条目在指定时长时没有被访问过时,将自动被删除;默认为60s;

               缓存的信息包括:
                   文件句柄、文件大小和上次修改时间;
                   已经打开的目录结构;
                   没有找到或没有访问权限的信息;

           4、open_file_cache_errors on|off
               是否缓存文件找不到或没有权限访问等相关信息;

           5、open_file_cache_valid time;
               多长时间检查一次缓存中的条目是否超出非活动时长,默认为60s;

           6、open_file_cache_min_use #;
               在inactive指定的时长内被访问超此处指定的次数地,才不会被删除;

       对客户端请求的特殊处理:
           1、ignore_invalid_headers on|off
               是否忽略不合法的http首部;默认为on; off意味着请求首部中出现不合规的首部将拒绝响应;只能用于server和http;

           2、log_not_found on|off
               是否将文件找不到的信息也记录进错误日志中;

           3、resolver address;
               指定nginx使用的dns服务器地址;

           4、resover_timeout time;
               指定DNS解析超时时长,默认为30s;

           5、server_tokens on|off;
               是否在错误页面中显示nginx的版本号;

       内存及磁盘资源分配:
           1、client_body_in_file_only on|clean|off
               HTTP的包体是否存储在磁盘文件中;非off表示存储,即使包体大小为0也会创建一个磁盘文件;on表示请求结束后包体文件不会被删除,clean表示会被删除;

           2、client_body_in_single_buffer on|off;
               HTTP的包体是否存储在内存buffer当中;默认为off;

           3、cleint_body_buffer_size size;
               nginx接收HTTP包体的内存缓冲区大小;

           4、client_body_temp_path dir-path [level1 [level2 [level3]]];
               HTTP包体存放的临时目录;
               client_body_temp_path /var/tmp/client/  1 2

           5、client_header_buffer_size size;
               正常情况下接收用户请求的http报文header部分时分配的buffer大小;默认为1k;

           6、large_client_header_buffers number size;
               存储超大Http请求首部的内存buffer大小及个数;

           7、connection_pool_size size;
               nginx对于每个建立成功的tcp连接都会预先分配一个内存池,此处即用于设定此内存池的初始大小;默认为256;

           8、request_pool_size size;
               nginx在处理每个http请求时会预先分配一个内存池,此处即用于设定此内存池的初始大小;默认为4k;



http核心模块的内置变量:
           $uri: 当前请求的uri,不带参数;
           $request_uri: 请求的uri,带完整参数;
           $host: http请求报文中host首部;如果请求中没有host首部,则以处理此请求的虚拟主机的主机名代替;
           $hostname: nginx服务运行在的主机的主机名;
           $remote_addr: 客户端IP
           $remote_port: 客户端Port
           $remote_user: 使用用户认证时客户端用户输入的用户名;
           $request_filename: 用户请求中的URI经过本地root或alias转换后映射的本地的文件路径;
           $request_method: 请求方法
           $server_addr: 服务器地址
           $server_name: 服务器名称
           $server_port: 服务器端口
           $server_protocol: 服务器向客户端发送响应时的协议,如http/1.1, http/1.0
           $scheme: 在请求中使用scheme, 如https://www.magedu.com/中的https;
           $http_HEADER: 匹配请求报文中指定的HEADER,$http_host匹配请求报文中的host首部
           $sent_http_HEADER: 匹配响应报文中指定的HEADER,例如$http_content_type匹配响应报文中的content-type首部;
           $document_root:当前请求映射到的root配置;



传统上基于进程或线程模型架构的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. 使用缓存元数据建立内存数据库;

cache manager进程的主要任务:
1. 缓存的失效及过期检验;

nginx的配置有着几个不同的上下文:main、http、server、upstream和location(还有实现邮件服务反向代理的mail)。配置语法的格式和定义方式遵循所谓的C风格,因此支持嵌套,还有着逻辑清晰并易于创建、阅读和维护等优势。


nginx的代码是由一个核心和一系列的模块组成, 核心主要用于提供Web Server的基本功能,以及Web和Mail反向代理的功能;还用于启用网络协议,创建必要的运行时环境以及确保不同的模块之间平滑地进行交互。不过,大多跟协议相关的功能和某应用特有的功能都是由nginx的模块实现的。这些功能模块大致可以分为事件模块、阶段性处理器、输出过滤器、变量处理器、协议、upstream和负载均衡几个类别,这些共同组成了nginx的http功能。事件模块主要用于提供OS独立的(不同操作系统的事件机制有所不同)事件通知机制如kqueue或epoll等。协议模块则负责实现nginx通过http、tls/ssl、smtp、pop3以及imap与对应的客户端建立会话。

在nginx内部,进程间的通信是通过模块的pipeline或chain实现的;换句话说,每一个功能或操作都由一个模块来实现。例如,压缩、通过FastCGI或uwsgi协议与upstream服务器通信,以及与memcached建立会话等。




应用实例: 搭建Lnmmp
一、安装nginx:

1、解决依赖关系

编译安装nginx需要事先需要安装开发包组"Development Tools"和 "Development Libraries"。同时,还需要专门安装pcre-devel包:

# yum -y install pcre-devel

2、安装

首先添加用户nginx,实现以之运行nginx服务进程:

# groupadd -r nginx
# useradd -r -g nginx nginx


接着开始编译和安装:

# ./configure \
  --prefix=/usr/local/nginx \
  --sbin-path=/usr/local/nginx/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


3、为nginx提供SysV init脚本:

新建文件/etc/rc.d/init.d/nginx,内容如下:

#!/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 start


nginx的http web功能:

       虚拟主机相关的配置:    
           1、server {}
               定义一个虚拟主机;nginx支持使用基于主机名或IP的虚拟主机;



           2、listen
               listen address[:port];
               listen port

               default_server:定义此server为http中默认的server;如果所有的server中没有任何一个listen使用此参数,那么第一个server即为默认server;
               rcvbuf=SIZE: 接收缓冲大小;
               sndbuf=SIZE: 发送缓冲大小;
               ssl: https server;

           3、server_name [...];
               server_name可以跟多个主机名,名称中可以使用通配符和正则表达式(通常以~开头);当nginx收到一个请求时,会取出其首部的server的值,而后跟众server_name进行比较;比较方式:
                   (1) 先做精确匹配;www.magedu.com
                   (2) 左侧通配符匹配;*.magedu.com
                   (3) 右侧通配符匹配;www.abc.com, www.*
                   (4) 正则表达式匹配: ~^.*\.magedu\.com$

           4、server_name_hash_bucket_size 32|64|128;
               为了实现快速主机查找,nginx使用hash表来保存主机名;

           5、location [ = | ~ | ~* | ^~ ] uri { ... }
              location @name { ... }
              功能:允许根据用户请求的URI来匹配指定的各location以进行访问配置;匹配到时,将被location块中的配置所处理;比如:http://www.magedu.com/images/logo.gif

              =:精确匹配;
              ~:正则表达式模式匹配,匹配时区分字符大小写
              ~*:正则表达式模式匹配,匹配时忽略字符大小写
              ^~: URI前半部分匹配,不检查正则表达式

                  http://www.magedu.com/index.html
                  http://www.magedu.com/
                  http://www.magedu.com/documents/index.html
                  http://www.magedu.com/images/index.html
                  http://www.magedu.com/images/a.png

                匹配优先级:
                    字符字面量最精确匹配、正则表达式检索(由第一个匹配到所处理)、按字符字面量

       文件路径定义:
           1、root path
               设置web资源路径;用于指定请求的根文档目录;
               location / {
                   root /www/htdocs;
               }

               location ^~ /images/ {
                   root /web;
               }

               root: root/URI/

                   http://www.magedu.com/images/b.html



2、alias path
只能用于location中,用于路径别名;路径别名;如下图所示;将访问/firefox/*能够访问物理路径下的/Mozilla/*

    location ^~ /firefox {
        alias /moziila;
}

wKiom1NaYWTDXioqAABxPbbrvUw787.jpg

[root@node5 moziila]# pwd
/moziila
[root@node5 moziila]# ls
b.html  firefox


3、index file ...;
定义默认页面,可参跟多个值;

index  index.html index.htm;


4、error_page code ... [=[response]] uri;
当对于某个请求返回错误时,如果匹配上了error_page指令中设定的code,则重定向到新的URI中。错误页面重定向;如果响应码为404则将页面转到/www/htdoc/404.htm   至于等于200;是为了不让它写入错误日志当中;

server {
        listen       80;
        server_name  localhost;
        error_page 404 =200 /404.html; ########################
        #charset koi8-r;
        #access_log  logs/host.access.log  main;
        location / {
            root   /www/htdoc;
            index  index.html index.htm;
        }
        location ^~ /firefox {
        alias /moziila;
}
[root@node5 nginx]# cd /www/htdoc/
[root@node5 htdoc]# pwd
/www/htdoc
[root@node5 htdoc]# ls
404.html  index.html
[root@node5 htdoc]# cat 404.html
<h1>This page not found<h1>

wKiom1NaZErydVauAACTlOYL0BA209.jpg

172.16.250.248 - - [25/Apr/2014:21:30:17 +0800] "GET /asdasdasd HTTP/1.1" 200 28 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.149 Safari/537.36"
172.16.250.248 - - [25/Apr/2014:21:30:18 +0800] "GET /favicon.ico HTTP/1.1" 200 0 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.149 Safari/537.36"
[root@node5 www]# cat /var/log/nginx/access.log



5、防盗链
(1) 定义合规的引用
valid_referers none | blocked | server_names | string ...;
(2) 拒绝不合规的引用
if  ($invalid_referer) {
rewrite ^/.*$ http://www.b.org/403.html
}

server {
        listen       80;
        server_name  www.baidu.org;
        #charset koi8-r;
        #access_log  logs/host.access.log  main;
        location / {
            root   /www/baidu.org/;
            index  index.html index.htm;
        }
        location /download/ {
        root /www/baidu.org/;
        autoindex on;
        rewrite ^/download/(.*\.(jpg|gif|jpeg|png))$ /images/$1 last;
        rewrite_log on;
}
############################################################### 如下:防盗链
        location ~* \.(jpg|png|gif|jpeg)$ {
            root /www/baidu.org;
            valid_referers none blocked www.baidu.org *.baidu.org;
            if ($invalid_referer) {
                rewrite ^/ http://www.baidu.org/403.html;
            }
        }
[root@node5 nginx]# cd /www/baidu.org/
[root@node5 baidu.org]# pwd
/www/baidu.org
[root@node5 baidu.org]# cat index.html
www.baidu.org
<img src="http://172.16.249.27/images/1.jpg">
#####################自己域内中的服务器使用####################
[root@node5 baidu.org]# cd /www/firefox.com/
[root@node5 firefox.com]# cat index.html
<h1>www.firefox.com<h1>
<img src="http://172.16.249.27/images/1.jpg">
####################不是属于本区域内的服务器###################

wKioL1NadaDiis4zAAdJYOzFm44188.jpg

wKiom1NaddvQdNQOAACy1ekAAh4222.jpg

6、URL rewrite
       rewrite regex replacement [flag];

   location / {
            root   /www/baidu.org/;
            index  index.html index.htm;
        }
        location /download/ {
        root /www/baidu.org/;
        autoindex on;
        rewrite ^/download/(.*\.(jpg|gif|jpeg|png))$ /images/$1 last;
        rewrite_log on;
}

  URL rewrite  注释:只要url路径开头指的是/download/.*jpg..... 都将它重写到/www/baidu.org/images/*.jpg

[root@node5 baidu.org]# pwd
/www/baidu.org
[root@node5 baidu.org]# ls
download  images  index.html
[root@node5 baidu.org]# ls download/
[root@node5 baidu.org]# ls images/
1.jpg  200832621323760509.jpg  2.jpg  3.jpeg  firefox.html

wKiom1Naa_nDYKopAAbDYMgzUn0619.jpg
last: 一旦被当前规则匹配并重写后立即停止检查后续的其它rewrite的规则,而后通过重写后的规则重新发起请求;
break: 一旦被当前规则匹配并重写后立即停止后续的其它rewrite的规则,而后继续由TenGine进行后续操作;
redirect: 返回302临时重定向;
permanent: 返回301永久重定向;

nginx最多循环10次,超出之后会返回500错误;
注意:一般将rewrite写在location中时都使用break标志,或者将rewrite写在if上下文中;
rewrite_log on|off
是否把重写过程记录在错误日志中;默认为notice级别;默认为off;

172.16.250.248 - - [25/Apr/2014:21:55:47 +0800] "GET /download/1.jpg HTTP/1.1" 200 104372 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.149 Safari/537.36"

return code:
用于结束rewrite规则,并且为客户返回状态码;可以使用的状态码有204, 400, 402-406, 500-504等;
if (condition) {
}

7、 启用压缩功能;

gzip on;
gzip_http_version 1.0;
gzip_comp_level 2;
gzip_types text/plain text/css images/jpeg application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript application/json;
gzip_disable msie6;


8、upstream使用注意:
1、只能用于http上下文;
2、各server只能直接使用IP或主机名,不要加协议;
server address [parameters];
weight=#: 设定权重
max_fails=#: 最大失败尝试次数,默认为1;
fail_timeout=time: 失败尝试超时时长;默认为10秒;

upstream webservers {
       server 172.16.249.109 weight=3 max_fails=2 fail_timeout=3;
       server 172.16.249.72 weight=1 max_fails=2 fail_timeout=3;
       server 127.0.0.1:8080 backup;
       #ip_hash;
       least_conn;
   }

 其中proxy_set_header作用是;后端服务器;显示真实客户端的IP地址;(least_conn)最少连接(least connected, lc), 加权最少连接(weighted least connection, wlc)——新的连接请求将被分配至当前连接数最少的RealServer;最小连接调度是一种动态调度算法,它通过服务器当前所活跃的连接数来估计服务器的负载情况。调度器需要记录各个服务器已建立连接的数目,当一个请求被调度到某台服务器,其连接数加1;当连接中止或超时,其连接数减一。

server {
        listen 80;
        server_name www.henhenlu.net;
        location / {
            proxy_pass http://webservers;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }
    server {
        listen 8080; ###################################################
        server_name 127.0.0.1;
        root /www/backup;
    }
}

   后端webserver需要将日志的格式修改

LogFormat "%{X-Real-IP}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined

   修改之前;

172.16.249.27 - - [28/Mar/2014:17:06:52 +0800] "GET / HTTP/1.0" 304 - "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0"

   修改之后;  

172.16.250.248 - - [28/Mar/2014:17:30:25 +0800] "GET / HTTP/1.0" 304 - "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0"

wKiom1NbCazTQqPNAABYvWjEjjY250.jpg

wKiom1NbCeHCRZTnAABT9yEoaKI028.jpg


使用add_header添加自定义的http首部信息;

server {
      listen 80;
      server_name www.henhenlu.net;
      add_header X-Via $server_addr;
      location / {
          proxy_pass http://webservers;
          proxy_set_header X-Real-IP $remote_addr;
      }
  }
Accept-Ranges:bytes
Connection:keep-alive
Content-Length:14
Content-Type:text/html; charset=UTF-8
Date:Fri, 25 Apr 2014 16:39:00 GMT
ETag:"e0569-e-4f718c607dcc2"
Last-Modified:Tue, 15 Apr 2014 18:14:40 GMT
Server:nginx/1.4.7
X-Via:172.16.249.27


9、使用nginx反向代理并缓存;

1、proxy指令:
proxy_pass URL;
2、proxy_set_header
3、proxy_hide_header
4、proxy_pass_header
5、proxy_pass_request_body: 是否将http请求报文的包体部分发往上游服务器;
6、proxy_pass_request_header: 是否将Http首部发往上游服务器;
7、proxy_redirect [default|off|redirect|replacement]
当上游服务器返回的响应是重定向或刷新请求时,proxy_redirect会重新设定http首部的location或refresh;
http://www.magedu.com/images/some/path, http://localhost:8080/imgs/some/path,
proxy_redirect http://localhost:8080/imgs
http://www.magedu.com/images

proxy_cache_path /cache/webserver levels=1:2 keys_zone=web:100m max_size=1g inactive=12h;
  server {
        listen 80;
        server_name www.henhenlu.net;
        add_header X-Via $server_addr;
        add_header X-Cache $upstream_cache_status;
        location / {
            proxy_pass http://webservers;
            proxy_cache web;
            proxy_cache_valid 200 2h;
            proxy_cache_valid 301 302 10m;
            proxy_cache_valid any 1m;
            #health_check uri=/.health.html match=webcheck;
            #health_check;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }

x-Cache是我们自定义的字段;查看服务器的缓存是否命中;HIT表示命中了;miss....表示没有命中

Connection:keep-alive
Date:Fri, 25 Apr 2014 17:06:48 GMT
ETag:"c0100-f-4f4796c66319a"
Last-Modified:Thu, 13 Mar 2014 09:17:33 GMT
Server:nginx/1.4.7
X-Cache:HIT
X-Via:172.16.249.27


10、使用Nginx反向代理;使网页文本;与图片分离;

server {
      listen 80;
      server_name www.henhenlu.net;
      add_header X-Via $server_addr;
      add_header X-Cache $upstream_cache_status;
      location / {
          proxy_pass http://172.16.249.72;
          proxy_cache web;
          proxy_cache_valid 200 2h;
          proxy_cache_valid 301 302 10m;
          proxy_cache_valid any 1m;
          #health_check uri=/.health.html match=webcheck;
          #health_check;
          proxy_set_header X-Real-IP $remote_addr;
      }
       location ~*\.(jpg|jpeg|png|gif)$ {
          proxy_pass http://172.16.249.168;
          proxy_cache web;
          proxy_cache_valid 200 2h;
          proxy_cache_valid 301 302 10m;
          proxy_cache_valid any 1m;
  }
      }

   后端server IP:172.16.249.72

[root@station145 html]# cat index.html
172.16.249.72
[root@station145 html]# ls
index.html

   后端server IP :172.16.248.168

[root@station20 html]# pwd
/var/www/html
[root@station20 html]# ls
1.jpg  2.jpg  3.jpeg  linux.jpg


11、使用Nginx反向代理;php-fpm;并缓存;

fastcgi模块的常用指令:
fastcgi_pass: 指定fastcgi服务监听端口、地址;也支持使用Unix sock;
fastcgi_bind: 指定联系fpm服务时使用的地址;
fastcgi_param: 定义传递给fpm服务器的参数;
fastcgi_index: php的主页面文件;
结果可以缓存,缓存空间使用fastcgi_cache_path定义,使用fastcgi_cache来调用;
fastcgi_cache_path 定义在全局配置文件当中;
fastcgi_cache : 使用fastcgi_cache来调用;
fastcgi_cache_valid 定义合法的时间;
fastcgi_connect_timeout: 连接fastcgi服务器的超时时长;

fastcgi_send_timeout: 向fastcgi服务传输数据的超时时长

1、编辑/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;
        }
2、编辑/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;


fastcgi_cache_path /cache/fastcgi  levels=1:2 keys_zone=fcgi:50m max_size=1g inactive=12h;
    server {
    listen 80;
    server_name www.henhenlu.net;
    add_header X-Via $server_addr;
    add_header X-Cache $upstream_cache_status;
    location / {
        root          /www/baidu.org  ;
        index          index.php index.html index.htm;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        include        fastcgi_params;
            fastcgi_cache fcgi;
            fastcgi_cache_valid 200 1h;
            fastcgi_cache_valid 301 302 5m;
            fastcgi_cache_valid any 1m;
    }
}
[root@node5 ~]# ab -n 1000 -c 100 http://172.16.249.27/index.php
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 172.16.249.27 (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests
Server Software:        nginx/1.4.7
Server Hostname:        172.16.249.27
Server Port:            80
Document Path:          /index.php
Document Length:        62358 bytes
Concurrency Level:      100
Time taken for tests:   0.565 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      62541000 bytes
HTML transferred:       62358000 bytes
Requests per second:    1769.37 [#/sec] (mean)
Time per request:       56.517 [ms] (mean)
Time per request:       0.565 [ms] (mean, across all concurrent requests)
Transfer rate:          108064.60 [Kbytes/sec] received
Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    3   5.0      0      66
Processing:    10   51  23.7     50     130
Waiting:        0   49  22.0     50     125
Total:         24   54  21.1     51     130
Percentage of the requests served within a certain time (ms)
  50%     51
  66%     54
  75%     57
  80%     61
  90%     89
  95%    107
  98%    125
  99%    128
 100%    130 (longest request)


二、安装 mariadb-10.0.10-linux-x86_64

# mkdir  /mydata/data -pv
# useradd  -r mysql
# chown  -R mysql.mysql /mydata/data/
# tar xf  mariadb-10.0.10-linux-x86_64.tar.gz  -C /usr/local
# cd /usr/local
# ln -sv mariadb-10.0.10-linux-x86_64/ mysql
# cd mysql/
# chown  -R root.mysql ./*
# scripts/mysql_install_db  --user=mysql --datadir=/mydata/data/
[root@localhost mysql]# mkdir  /etc/mysql
[root@localhost mysql]# cp support-files/my-large.cnf  /etc/mysql/my.cnf
[root@localhost mysql]# cp support-files/mysql.server  /etc/rc.d/init.d/mysqld
[root@localhost mysql]# chmod  +x  /etc/rc.d/init.d/mysqld
[root@localhost mysql]# chkconfig  --add mysqld
[root@localhost mysql]# chkconfig  mysqld on
# vim /etc/mysql/my.cnf
datadir= /mydata/data
innodb_file_per_table=ON

三、编译安装php-5.4.4
1、解决依赖关系

# yum -y groupinstall "Desktop Platform Development"
# yum -y install bzip2-devel libmcrypt-devel
# tar xf php-5.4.26.tar.bz2
# cd php-5.4.26
# ./configure --prefix=/usr/local/php  --with-openssl --enable-fpm --enable-sockets --enable-sysvshm  --with-mysql=mysqlnd --with-pdo-mysql=mysqlnd --with-mysqli=mysqlnd   --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
# make && make install

注释: 缺什么包;就安装那个包名或库名后面加上--devel就行啦;;!

为php提供配置文件:
# cp php.ini-production /etc/php.ini
为php-fpm提供Sysv init脚本,并将其添加至服务列表:
# 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的配置文件:
# vim /usr/local/php/etc/php-fpm.conf
配置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了:
# service php-fpm start
使用如下命令来验正(如果此命令输出有中几个php-fpm进程就说明启动成功了):
# ps aux | grep php-fpm




四、整合nginx和php5

1、编辑/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;
        }
2、编辑/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   html;
            index  index.php index.html index.htm;
        }

而后重新载入nginx的配置文件:
# service nginx reload

3、在/usr/html新建index.php的测试页面,测试php是否能正常工作:
# cat > /usr/html/index.php << EOF
<?php
phpinfo();
?>

接着就可以通过浏览器访问此测试页面了。

wKioL1NbVPbjwnunAAEV-9UVwFM723.jpg




五、安装xcache,为php加速:

1、安装

# tar xf xcache-2.0.0.tar.gz
# cd xcache-2.0.0
# /usr/local/php/bin/phpize
# ./configure --enable-xcache --with-php-config=/usr/local/php/bin/php-config
# make && make install

安装结束时,会出现类似如下行:
Installing shared extensions:     /usr/local/php/lib/php/extensions/no-debug-zts-20100525/

2、编辑php.ini,整合php和xcache:

首先将xcache提供的样例配置导入php.ini
# mkdir /etc/php.d
# cp xcache.ini /etc/php.d

说明:xcache.ini文件在xcache的源码目录中。

接下来编辑/etc/php.d/xcache.ini,找到zend_extension开头的行,修改为如下行:
extension =  /usr/local/php/lib/php/extensions/no-debug-non-zts-20100525/xcache.so

注意:如果xcache.ini文件中有多条extension指令行,要确保此新增的行排在第一位。
3、重新启动php-fpm
# service php-fpm restart
wKiom1NbVQ2z84QJAABKn1tDDb4753.jpg


六、补充说明

如果要在SSL中使用php,需要在php的location中添加此选项:

fastcgi_param HTTPS on;


Memcached是一款开源、高性能、分布式内存对象缓存系统,可应用各种需要缓存的场景,其主要目的是通过降低对Database的访问来加速web应用程序。它是一个基于内存的“键值对”存储,用于存储数据库调用、API调用或页面引用结果的直接数据,如字符串、对象等。

memcached是以LiveJournal旗下Danga Interactive 公司的Brad Fitzpatric 为首开发的一款软件。现在
已成为mixi、hatena、Facebook、Vox、LiveJournal等众多服务中提高Web应用扩展性的重要因素。

Memcached是一款开发工具,它既不是一个代码加速器,也不是数据库中间件。其设计哲学思想主要反映在如下方面:

1. 简单key/value存储:服务器不关心数据本身的意义及结构,只要是可序列化数据即可。存储项由“键、过期时间、可选的标志及数据”四个部分组成;
2. 功能的实现一半依赖于客户端,一半基于服务器端:客户负责发送存储项至服务器端、从服务端获取数据以及无法连接至服务器时采用相应的动作;服务端负责接收、存储数据,并负责数据项的超时过期;
3. 各服务器间彼此无视:不在服务器间进行数据同步;
4. O(1)的执行效率
5. 清理超期数据:默认情况下,Memcached是一个LRU缓存,同时,它按事先预订的时长清理超期数据;但事实上,memcached不会删除任何已缓存数据,只是在其过期之后不再为客户所见;而且,memcached也不会真正按期限清理缓存,而仅是当get命令到达时检查其时长;

Memcached提供了为数不多的几个命令来完成与服务器端的交互,这些命令基于memcached的协议实现。

存储类命令:set, add, replace, append, prepend
获取数据类命令:get, delete, incr/decr
统计类命令:stats, stats items, stats slabs, stats sizes
清理命令: flush_all

一、安装libevent

memcached依赖于libevent API,因此要事先安装之,项目主页:http://libevent.org/,读者可自行选择需要的版本下载。本文采用的是目前最新版本的源码包libevent-2.0.21-stable.tar.gz。安装过程:

# tar xf libevent-2.0.21-stable.tar.gz
# cd libevent-2.0.21
# ./configure --prefix=/usr/local/libevent
# make && make install
# echo "/usr/local/libevent/lib" > /etc/ld.so.conf.d/libevent.conf
# ldconfig

二、安装配置memcached

1、安装memcached
# tar xf memcached-1.4.15.tar.gz
# cd memcached-1.4.15
# ./configure --prefix=/usr/local/memcached --with-libevent=/usr/local/libevent
# make && make install


2、memcached SysV的startup脚本代码如下所示,将其建立为/etc/init.d/memcached文件:

#!/bin/bash
#
# Init file for memcached
#
# chkconfig: - 86 14
# description: Distributed memory caching daemon
#
# processname: memcached
# config: /etc/sysconfig/memcached
. /etc/rc.d/init.d/functions
## Default variables
PORT="11211"
USER="nobody"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS=""
RETVAL=0
prog="/usr/local/memcached/bin/memcached"
desc="Distributed memory caching"
lockfile="/var/lock/subsys/memcached"
start() {
        echo -n $"Starting $desc (memcached): "
        daemon $prog -d -p $PORT -u $USER -c $MAXCONN -m $CACHESIZE -o "$OPTIONS"
        RETVAL=$?
        [ $RETVAL -eq 0 ] && success && touch $lockfile || failure
        echo
        return $RETVAL
}
stop() {
        echo -n $"Shutting down $desc (memcached): "
        killproc $prog
        RETVAL=$?
        [ $RETVAL -eq 0 ] && success && rm -f $lockfile || failure
        echo
        return $RETVAL
}
restart() {
        stop
        start
}
reload() {
        echo -n $"Reloading $desc ($prog): "
        killproc $prog -HUP
        RETVAL=$?
        [ $RETVAL -eq 0 ] && success || failure
        echo
        return $RETVAL
}
case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  restart)
        restart
        ;;
  condrestart)
        [ -e $lockfile ] && restart
        RETVAL=$?
        ;;   
  reload)
        reload
        ;;
  status)
        status $prog
        RETVAL=$?
        ;;
   *)
        echo $"Usage: $0 {start|stop|restart|condrestart|status}"
        RETVAL=1
esac
exit $RETVAL


使用如下命令配置memcached成为系统服务:

# chmod +x /etc/init.d/memcached
# chkconfig --add memcached
# service memcached start

3、使用telnet命令测试memcached的使用

Memcached提供一组基本命令用于基于命令行调用其服务或查看服务器状态等。

# telnet 127.0.0.1 11211
add命令:
add keyname flag  timeout  datasize
如:
add mykey 0 10 12
Hello world!
get命令:
get keyname
如:get mykey
VALUE mykey 0 12
Hello world!
END

4、memcached的常用选项说

-l <ip_addr>:指定进程监听的地址;
-d: 以服务模式运行;
-u <username>:以指定的用户身份运行memcached进程;
-m <num>:用于缓存数据的最大内存空间,单位为MB,默认为64MB;
-c <num>:最大支持的并发连接数,默认为1024;
-p <num>: 指定监听的TCP端口,默认为11211;
-U <num>:指定监听的UDP端口,默认为11211,0表示关闭UDP端口;
-t <threads>:用于处理入站请求的最大线程数,仅在memcached编译时开启了支持线程才有效;
-f <num>:设定Slab Allocator定义预先分配内存空间大小固定的块时使用的增长因子;
-M:当内存空间不够使用时返回错误信息,而不是按LRU算法利用空间;
-n: 指定最小的slab chunk大小;单位是字节;
-S: 启用sasl进行用户认证;


三、安装Memcache的PHP扩展

①安装PHP的memcache扩展
# tar xf memcache-2.2.5.tgz
# cd memcache-2.2.5
/usr/local/php/bin/phpize
# ./configure --with-php-config=/usr/local/php/bin/php-config --enable-memcache
# make && make install

上述安装完后会有类似以下的提示信息如下:

Installing shared extensions:     /usr/local/php/lib/php/extensions/no-debug-non-zts-20090626/
②编辑/etc/php.ini,在“动态模块”相关的位置添加如下一行来载入memcache扩展:
extension=/usr/local/php/lib/php/extensions/no-debug-non-zts-20090626/memcache.so

wKioL1NbX-byFl8VAACCa0_Vj7Y110.jpg

# pwd
/www/baidu.org
[root@node5 baidu.org]# cat test.php
<?php
$mem = new Memcache;
$mem->connect("172.16.249.72", 11211)  or die("Could not connect");
$version = $mem->getVersion();
echo "Server's version: ".$version."<br/>\n";
$mem->set('hellokey', 'Hello World', 0, 600) or die("Failed to save data at the memcached server");
echo "Store data in the cache (data will expire in 600 seconds)<br/>\n";
$get_result = $mem->get('hellokey');
echo "$get_result is from memcached server.";     
?>

wKiom1NbYYeDLLRqAADdmD1eEXA174.jpg

如果有输出“Hello World is from memcached.”等信息,则表明memcache已经能够正常工作。



四、使用libmemcached的客户端工具:
访问memcached的传统方法是使用基于perl语言开发的Cache::memcached模块,这个模块在大多数perl代码中都能良好的工作,但也有着众所周知的性能方面的问题。libMemcached则是基于C语言开发的开源的C/C++代码访问memcached的库文件,同时,它还提供了数个可以远程使用的memcached管理工具,如memcat, memping,memstat,memslap等

1) 编译安装libmemcached
# tar xf libmemcached-1.0.2.tar.gz
# cd libmemcached-1.0.2
# ./configure
# make && make install
# ldconfig
2) 客户端工具
# memcat --servers=127.0.0.1:11211 mykey
# memping
# memslap
# memstat




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章