Nginx的安装

Nginx的安装

准备工作

操作系统:centOS 6.X。

Nginx的下载地址:http://nginx.org/en/download.html。请下载stable的版本1.8.0。后续Nginx肯定还会有升级,官网上面会持续更新stable version。

最小必备组件:
yum -y install make zlib zlib-devel gcc gcc-c++ ssh libtool pcre

正式安装

  • 下载nginx1.8.0版本
    这里写图片描述

  • 解压nginx的tar文件
    这里写图片描述

  • 进行源码编译
    这里写图片描述

我们看到这时编译检查报错,报错写得很清楚,为了支持HTTP重写模块,Nginx需要PCRElib的支持。那我们到http://ncu.dl.sourceforge.net/project/pcre/pcre/8.37/pcre-8.37.tar.gz下载一个稳定的pcre版本编译安装即可(不一定是8.37版本)。

    • 再进行源码编译安装
      ./configure –prefix=/usr/nginx-1.8.0
      make && make install
      这里写图片描述

    • 整个验证、编译、安装过程不应该报任何错误。如果您使用prefix设置了安装目标目录,那么可能您还需要在/tec/profix文件中设置环境变量:
      这里写图片描述

安装验证和启动

下面介绍几个nginx常用的命令,如果您可以正常使用这些命令,那么说明nginx已经安装成功了。

nginx:直接在命令行键入nginx,就可以启动nginx。

nginx -t:检查配置文件是否正确。这个命令可以检查nginx.conf配置文件其格式、语法是否正确。如果配置文件存在错误,则会出现相应提示;如果nginx.conf文件正确,也会出现相应的成功提示。

nginx -s reload:重加载/重启nginx——以新的nginx.conf配置文件中的定义。

nginx -s stop:停止nginx。

 

进阶

Nginx在安装完成后,不用更改任何配置信息就可以直接运行。但是很显然这不会满足我们生产环境的要求。所以我们要重点介绍Nginx的配置文件,以及其中重要的配置项的含义。

重要配置项

如果您是按照本文的描述方式安装的Nginx,那么Nginx的主配置文件在:/usr/nginx-1.8.0/conf/nginx.conf的位置,如果您在编译安装的时候并没有指定安装目录,那么Nginx的主配置文件在:/usr/local/nginx/conf/nginx.conf的位置。当然您还可以在启动Nginx的时候使用 -c 的参数人为指定Nginx的配置文件位置(但是这种方式不建议)。

我们重新整理了Nginx的配置文件,将其分块,以便于讲解:

#================================以下是全局配置项
#指定运行nginx的用户和用户组,默认情况下该选项关闭(关闭的情况就是nobody)
#user  nobody nobody;     
#运行nginx的进程数量,后文详细讲解
worker_processes  1;      
#nginx运行错误的日志存放位置。当然您还可以指定错误级别
#error_log  logs/error.log;    
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;
#指定主进程id文件的存放位置,虽然worker_processes != 1的情况下,会有很多进程,管理进程只有一个
#pid        logs/nginx.pid;    

events {
    #每一个进程可同时建立的连接数量,后问详细讲解
    worker_connections  1024;   
    #连接规则,可以采用[kqueue rtsig epoll select poll eventport ],后文详细讲解
    use   epoll;    
}
#================================以上是全局配置项

http {
    #================================以下是Nginx后端服务配置项
    upstream backendserver1 {
        #nginx向后端服务器分配请求任务的方式,默认为轮询;如果指定了ip_hash,就是hash算法(上文介绍的算法内容)
        #ip_hash    
        #后端服务器 ip:port ,如果有多个服务节点,这里就配置多个
        server 192.168.220.131:8080; 
        server 192.168.220.132:8080;    
        #backup表示,这个是一个备份节点,只有当所有节点失效后,nginx才会往这个节点分配请求任务
        #server 192.168.220.133:8080 backup;        
        #weight,固定权重,还记得我们上文提到的加权轮询方式吧。
        #server 192.168.220.134:8080 weight=100;    
    }
    #================================以上是Nginx后端服务配置项

    #=================================================以下是 http 协议主配置
    #安装nginx后,在conf目录下除了nginx.conf主配置文件以外,有很多模板配置文件,这里就是导入这些模板文件
    include       mime.types;
    #HTTP核心模块指令,这里设定默认类型为二进制流,也就是当文件类型未定义时使用这种方式
    default_type  application/octet-stream;     
    #日志格式
    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '   
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    #日志文件存放的位置
    #access_log  logs/access.log  main;         

    #sendfile 规则开启
    sendfile        on;
    #指定一个连接的等待时间(单位秒),如果超过等待时间,连接就会断掉。注意一定要设置,否则高并发情况下会产生性能问题。
    keepalive_timeout  65;                      

    #开启数据压缩,后文详细介绍
    gzip  on;                                   
    #=================================================以上是 http 协议主配置

    #=================================================以下是一个服务实例的配置
    server {
        #这个代理实例的监听端口
        listen       80;
        #server_name 取个唯一的实例名都要想半天?
        server_name  localhost; 
        #文字格式
        charset utf-8;  
        #access_log  logs/host.access.log  main;    

        #location将按照规则分流满足条件的URL。"location /"您可以理解为“默认分流位置”。
        location / {
            #root目录,这个html表示nginx主安装目录下的“html”目录。
            root   html;   
            #目录中的默认展示页面
            index  index.html index.htm;        
        }

        #location支持正则表达式,“~” 表示匹配正则表达式。
        location ~ ^/business/ {   
            #方向代理。后文详细讲解。
            proxy_pass http://backendserver1;   
        }

        #redirect server error pages to the static page /50x.html
        #error_page  404              /404.html;
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
    #=================================================以上是一个服务实例的配置
}

以上是一个完整的nginx配置信息,可以直接粘贴使用,但不建议您这样做。因为上文中很多关键的配置属性都还没有讲解。这样粘贴复制不利于您的工作和学习。

use [ kqueue | rtsig | epoll | select | poll ]

科技在发展,社会在进步,满足摩尔定义的IT行业更是这样。以前所有的连接都是阻断式的(blocking I/O)也就是说一个TCP连接线程在发出Request后,代码就不会再往下执行了,直到得到远端的Response为止;服务器端也一样的,在处理完某一个客户端的Request之前,其他客户端的请求都会等待。这种处理方式使客户端和服务器端的通讯性能大打折扣。

很明显多线程貌似能够解决这个问题:一个线程处理不了,我可以再开线程来处理啊。但是多线程是有局限性的:

  • 创建一个线程会消耗有限的资源,以JAVA JVM为例,创建一个新的线程JVM会单独开放128K的内存空间(通过permsize参数可设置),您可以计算一下一个设置为4GB内存大小的JVM可以开多少个线程。

  • 单个进程在linux操作系统下,单个用户能够创建的线程和进程总数、整个操作系统能够创建的线程总数也是有限的。通过limit -a命令,您可以查看相关的内核参数。

  • 所以靠线程来解决bio的问题,是不可靠的,只能缓解问题。您可以想象一个并发10万的连接数是不可能创建10万个线程来解决问题的。

基于上面的描述,NIO(no blocking I/O)技术就这样诞生了。依靠event loop机制(想看这个机制的详细分析,请持续关注我的博客^_^),单个线程可以同时处理多个request请求,并在处理完产生response的时候,回调相关的远程事件。根据NIO实现机制的不同,技术名称也就不同了。我要说什么,您,应该懂了。

epoll、kqueue:NIO的实现,其中epoll在linux环境下可以使用,但限于linux2.6及以上版本。kqueue用在bsd上使用。
poll、select: BIO的实现

worker_processes和worker_connections

worker_processes:操作系统启动多少个工作进程运行Nginx。注意是工作进程,不是有多少个nginx工程。在Nginx运行的时候,会启动两种进程,一种是主进程master process;一种是工作进程worker process。例如我在配置文件中将worker_processes设置为4,启动Nginx后,使用进程查看命令观察名字叫做nginx的进程信息,我会看到如下结果:

这里写图片描述

图中可以看到1个nginx主进程,master process;还有四个工作进程,worker process。主进程负责监控端口,协调工作进程的工作状态,分配工作任务,工作进程负责进行任务处理。一般这个参数要和操作系统的CPU内核数成倍数。

worker_connections:这个属性是指单个工作进程可以允许同时建立外部连接的数量。无论这个连接是外部主动建立的,还是内部建立的。这里需要注意的是,一个工作进程建立一个连接后,进程将打开一个文件副本。所以这个数量还受操作系统设定的,进程最大可打开的文件数有关。网上50%的文章告诉了您这个事实,并要求您修改worker_connections属性的时候,一定要使用ulimit -n 修改操作系统对进程最大文件数的限制,但是这样更改只能在当次用户的当次shell回话中起作用,并不是永久了。接着您继续Google/百度,发现30%的文章还告诉您,要想使“进程最大可打开的文件数”永久有效,还需要修改/etc/security/limits.conf这个主配置文件,但是您应该如何正确检查“进程的最大可打开文件”的方式,却没有说。

下面本文告诉您全面的、正确的设置方式:

  • 更改操作系统级别的“进程最大可打开文件数”的设置
    首先您需要操作系统的root权限:

    叫您的操作系统管理员给您。

    修改limits.conf主配置文件

    vim /etc/security/limits.conf

    在主配置文件最后加入下面两句:

    * soft nofile 65535
    * hard nofile 65535

    注意“”是要加到文件里面的。这两句话的含义是soft(应用软件)级别限制的最大可打开文件数的限制,hard表示操作系统级别限制的最大可打开文件数的限制,“”表示所有用户都生效。保存这个文件(只有root用户能够有权限)。

    保存这个文件后,配置是不会马上生效的,为了保证本次shell会话中的配置马上有效,我们需要通过ulimit命令更改本次的shell会话设置(当然您如果要重启系统,我也不能说什么)。

    ulimit -n 65535

    执行命令后,配置马上生效。您可以用ulimit -a 查看目前会话中的所有核心配置:

    ulimit -a
    core file size (blocks, -c) 0
    data seg size (kbytes, -d) unlimited
    scheduling priority (-e) 0
    file size (blocks, -f) unlimited
    pending signals (-i) 7746
    max locked memory (kbytes, -l) 64
    max memory size (kbytes, -m) unlimited
    open files (-n) 65535
    pipe size (512 bytes, -p) 8
    POSIX message queues (bytes, -q) 819200
    real-time priority (-r) 0
    stack size (kbytes, -s) 10240
    cpu time (seconds, -t) unlimited
    max user processes (-u) 7746
    virtual memory (kbytes, -v) unlimited
    file locks (-x) unlimited

    请注意open files这一项。

  • 更改Nginx软件级别的“进程最大可打开文件数”的设置:
    刚才更改的只是操作系统级别的“进程最大可打开文件”的限制,作为Nginx来说,我们还要对这个软件进行更改。打开nginx.conf主陪文件。您需要配合worker_rlimit_nofile属性。如下:

    user root root;
    worker_processes 4;
    worker_rlimit_nofile 65535;

    #error_log logs/error.log;
    #error_log logs/error.log notice;
    #error_log logs/error.log info;

    #pid logs/nginx.pid;
    events {
    use epoll;
    worker_connections 65535;
    }

    这里只粘贴了部分代码,其他的配置代码和主题无关,也就不需要粘贴了。请注意代码行中加粗的两个配置项,请一定两个属性全部配置。配置完成后,请通过nginx -s reload命令重新启动Nginx。

  • 验证Nginx的“进程最大可打开文件数”是否起作用:

    那么我们如何来验证配置是否起作用了呢?在linux系统中,所有的进程都会有一个临时的核心配置文件描述,存放路径在/pro/进程号/limit。

    首先我们来看一下,没有进行参数优化前的进程配置信息:

    ps -elf | grep nginx
    1 S root 1594 1 0 80 0 - 6070 rt_sig 05:06 ? 00:00:00 nginx: master process /usr/nginx-1.8.0/sbin/nginx
    5 S root 1596 1594 0 80 0 - 6176 ep_pol 05:06 ? 00:00:00 nginx: worker process
    5 S root 1597 1594 0 80 0 - 6176 ep_pol 05:06 ? 00:00:00 nginx: worker process
    5 S root 1598 1594 0 80 0 - 6176 ep_pol 05:06 ? 00:00:00 nginx: worker process
    5 S root 1599 1594 0 80 0 - 6176 ep_pol 05:06 ? 00:00:00 nginx: worker process

    可以看到,nginx工作进程的进程号是:1596 1597 1598 1599。我们选择一个进程,查看其核心配置信息:

    cat /proc/1598/limits

    这里写图片描述

    请注意其中的Max open files ,分别是1024和4096。那么更改配置信息,并重启Nginx后,配置信息就是下图所示了:

    这里写图片描述

max client的计算方式:

这个小结我们主要来说明两个在网上经常说的公式:

  • max_client = worker_processes * worker_connections

  • max_client = worker_processes * worker_connections / 4

这两个公式分别说明,在Nginx充当服务器(例如nginx上面装载PHP)的时候,Nginx可同时承载的连接数量是最大工作线程 * 每个线程允许的连接数量;当Nginx充当反向代理服务的时候,其可同时承载的连接数量是最大工作线程 * 每个线程允许的连接数量 / 4。

第一个问题很好理解,关键是第二个问题:为什么会除以4。网上的帖子给出的答案是。浏览器->Nginx、Nginx->后端服务器、后端服务器->Nginx、Nginx->浏览器,所以需要除以四,我想说TCP协议是双向全双工协议,为什么需要这样建立连接呢?所以这个说法肯定是错误的。

在nginx官方文档上有这样一句话:

Since a browser opens 2 connections by default to a server and nginx uses the fds (file descriptors) from the same pool to connect to the upstream backend。

翻译成中文的描述就是,浏览器会建立两条连接到Nginx(注意两条连接都是浏览器建立的),Nginx也会建立对应的两条连接到后端服务器。这样就是四条连接了。

健康检查模块

在本小节我们介绍一个用于Nginx对后端UpStream集群节点健康状态检查的第三方模块:nginx_upstream_check_module(https://github.com/yaoweibin/nginx_upstream_check_module)。这个模块有资料介绍是TaoBao团队开发的,但是我在GitHua上试图求证时并没有找到直接证据。

这里需要说明的是,目前有很多Nginx模块实现Nginx对后端集群节点的健康监测,不止nginx_upstream_check_module。Nginx官方有一个模块healthcheck_nginx_upstreams也可以实现对后端节点的健康监测(https://github.com/cep21/healthcheck_nginx_upstreams有详细的安装和使用介绍)

我们回到对nginx_upstream_check_module的讲解,要使用这个第三方模块首先您需要进行下载,然后通过patch命令将补丁打入您原有的Nginx源码中,并且重新进行编译安装。下面我们来重点讲解一下这个模块的安装和使用。

下载nginx_upstream_check_module模块:

wget https://codeload.github.com/yaoweibin/nginx_upstream_check_module/zip/master

您也可以直接到GitHua上进行下载,还一个在linux系统上使用git命令进行下载。

解压安装,并补丁打入Nginx源码

# unzip ./nginx_upstream_check_module-master.zip

注意是将补丁打入Nginx源码,不是Nginx的安装路径:

# cd ./nginx-1.6.2

# patch -p1 < ../nginx_upstream_check_module-master/check_1.5.12+.patch

如果补丁安装成功,您将看到以下的提示信息:
patching file src/http/modules/ngx_http_upstream_ip_hash_module.c
patching file src/http/modules/ngx_http_upstream_least_conn_module.c
patching file src/http/ngx_http_upstream_round_robin.c
patching file src/http/ngx_http_upstream_round_robin.h

这里请注意:在nginx_upstream_check_module官网的安装说明中,有一个打补丁的注意事项:
If you use nginx-1.2.1 or nginx-1.3.0, the nginx upstream round robin
module changed greatly. You should use the patch named
'check_1.2.1.patch'.
If you use nginx-1.2.2+ or nginx-1.3.1+, It added the upstream
least_conn module. You should use the patch named 'check_1.2.2+.patch'.
If you use nginx-1.2.6+ or nginx-1.3.9+, It adjusted the round robin
module. You should use the patch named 'check_1.2.6+.patch'.
If you use nginx-1.5.12+, You should use the patch named
'check_1.5.12+.patch'.
If you use nginx-1.7.2+, You should use the patch named
'check_1.7.2+.patch'.

这里我们的Nginx的版本是1.6.2,那么就应该打入check_1.5.12+.patch这个补丁

重新编译安装Nginx:

注意重新编译Nginx,要使用add-module参数将这个第三方模块安装进去:

# ./configure --prefix=/usr/nginx-1.6.2/ --add-module=../nginx_upstream_check_module-master/

# make && make install

通过以上的步骤,第三方的nginx_upstream_check_module模块就在Nginx中准备好了。接下来我们讲解一下如何使用这个模块。首先看一下upstream的配置信息:

upstream cluster {
    # simple round-robin
    server 192.168.0.1:80;
    server 192.168.0.2:80;

    check interval=5000 rise=1 fall=3 timeout=4000;

    #check interval=3000 rise=2 fall=5 timeout=1000 type=ssl_hello;
    #check interval=3000 rise=2 fall=5 timeout=1000 type=http;
    #check_http_send "HEAD / HTTP/1.0\r\n\r\n";
    #check_http_expect_alive http_2xx http_3xx;
}

上面的代码中,check部分就是调用nginx_upstream_check_module模块的语法:

check interval=milliseconds [fall=count] [rise=count]
[timeout=milliseconds] [default_down=true|false]
[type=tcp|http|ssl_hello|mysql|ajp|fastcgi]

interval:必要参数,检查请求的间隔时间。

fall:当检查失败次数超过了fall,这个服务节点就变成down状态。

rise:当检查成功的次数超过了rise,这个服务节点又会变成up状态。

timeout:请求超时时间,超过等待时间后,这次检查就算失败。

default_down:后端服务器的初始状态。默认情况下,检查功能在Nginx启动的时候将会把所有后端节点的状态置为down,检查成功后,在置为up。

type:这是检查通信的协议类型,默认为http。以上类型是检查功能所支持的所有协议类型。

check_http_send http_packet

http_packet的默认格式为:"GET / HTTP/1.0\r\n\r\n"

check_http_send设置,这个设置描述了检查模块在每次检查时,向后端节点发送什么样的信息

check_http_expect_alive [ http_2xx | http_3xx | http_4xx | http_5xx ]

这些状态代码表示服务器的HTTP响应上是OK的,后端节点是可用的。默认情况的设置是:http_2xx | http_3xx

当您根据您的配置要求完成检查模块的配置后,请首先使用nginx -t 命令监测配置文件是否可用,然后在用nginx -s reload重启nginx。

 

检查Nginx状态

在正式介绍Nginx + Keepalived的配置前,我们首先介绍一下如何检查Nginx的状态。是的,这是为下一小节做准备。我们只有能够正确检查Nginx的状态,才说得上在Nginx节点出现问题的情况下,切换到另一台Nginx上接替其工作

Nginx为什么会停止响应呢?在我的工作经验中,无非有以下几种情况:

  • Nginx的所有进程被强行终止(或管理进程)。
    这种情况,是我们需要检查和切换的。无论什么情况下进程被终止了,如果它不能重启,我们就要切换到备机。

  • Nginx日志盘的挂载点崩溃或者磁盘写满。
    这个也是我们需要检查和切换的。

  • Nginx已经达到设置的最大连接数,暂时停止响应。
    这种情况下,我们不能进行备机切换,因为通过VIP:192.168.61.100连接过来的用户请求比较多(在我们优化参数后,可以达到65535 / 4的数量),一旦我们进行备机切换,这些用户请求将全部异常。这个问题的解决需要靠增加负载机器,而不是主备切换。

  • Nginx物理机异常关机。
    这个肯定是需要进行检查和切换的。

我们来看一段Linux脚本:

#!/bin/sh
if [ $(ps -C nginx --no-header | wc -l) -eq 0 ]; then
    /usr/nginx-1.6.2/sbin/nginx
fi

sleep 2
if [ $(ps -C nginx --no-header | wc -l) -eq 0 ]; then
    service keepalived stop
fi

 

我们大致讲解一下“ps -C nginx –no-header | wc -l”这个命令:
- ps 这个命令用来进行Linux中进程相关的查询,-C 意思是按照进程名称进行查询。查询出来后的结果如下:

[root@vm2 ~]# ps -C nginx
  PID TTY          TIME CMD
 3374 ?        00:00:00 nginx
 3375 ?        00:00:01 nginx
  • 如果要去掉统计出来的结果表的头部,那么要使用 –no-header参数,加上参数后,查询结果如下:

    [root@vm2 ~]# ps -C nginx  --no-header
     3374 ?        00:00:00 nginx
     3375 ?        00:00:01 nginx
    
  • “|”,这是Linux中的管道流命令,将上一个命令的输出结果作为下一个命令的输入。

  • wc 统计命令,-l 参数,代表按行数进行统计。所以整个命令的输出结果为:

    [root@vm2 ~]# ps -C nginx --no-header | wc -l
    2
    

清楚了其中最关键的命令,我们再来讲解一下整个脚本的含义:
第一个判断说明的是,如果当前nginx的进程数量 == 0,那么执行nginx的启动命令,试图重新启动nginx;接下来等待2秒(这是为了给nginx一定的启动时间),然后再次查看Nginx的进程数量,如果仍然 == 0,那么停止这台机器的keepalived服务,以便备用的Keepalived节点检查到Keepalived已经停止这个事件,并将浮动IP切换到备用服务器上。

注意,这段脚本是和我机器上的Nginx安装路径、Keepalived服务的状态有关的,您如果要用的话,请进行相应的更改

gzip

nginx对返回给浏览器的http response body是可以进行压缩的。虽然需要消耗一点cpu和内存资源,但是想到100KB的数据量可以压缩到60KB甚至更小进行传输,是否有一定的吸引力?这里我的建议是,不要为了节约成本将业务服务和负载层服务放在一台物理服务器上,这样做既影响性能又增加了运维难度。http返回数据进行压缩的功能在很多场景下都实用:

    • 如果浏览器使用的是3G/4G网络,那么流量对于用户来说就是money。

    • 压缩可节约服务器机房的对外带宽,为更多用户服务。按照目前的市场价良好的机房带宽资源的一般在200RMB/Mbps,而服务器方案的压力往往也来自于机房带宽。

    • 主要注意的是,不是Nginx开启了gzip功能,HTTP响应的数据就一定会被压缩,除了满足Nginx设置的“需要压缩的http格式”以外,客户端(浏览器)也需要支持gzip(不然它怎么解压呢),一个好消息是,目前大多数浏览器和API都支持http压缩。

      我们首先来讲解Nginx中的gzip的设置参数,然后我们讲解当开启压缩功能后,HTTP的交互过程和过程中关键的几个属性。我们首先来看看Nginx中开启gzip的属性(gzip的设置放置在HTTP主配置区域):

      #开启gzip压缩服务,
      gzip on;

      #gzip压缩是要申请临时内存空间的,假设前提是压缩后大小是小于等于压缩前的。例如,如果原始文件大小为10K,那么它超过了8K,所以分配的内存是8 * 2 = 16K;再例如,原始文件大小为18K,很明显16K也是不够的,那么按照 8 * 2 * 2 = 32K的大小申请内存。如果没有设置,默认值是申请跟原始数据相同大小的内存空间去存储gzip压缩结果。
      gzip_buffers 2 8k;

      #进行压缩的原始文件的最小大小值,也就是说如果原始文件小于5K,那么就不会进行压缩了
      gzip_min_length 5K;

      #gzip压缩基于的http协议版本,默认就是HTTP 1.1
      gzip_http_version 1.1;

      # gzip压缩级别1-9,级别越高压缩率越大,压缩时间也就越长CPU越高
      gzip_comp_level 5;

      #需要进行gzip压缩的Content-Type的Header的类型。建议js、text、css、xml、json都要进行压缩;图片就没必要了,gif、jpge文件已经压缩得很好了,就算再压,效果也不好,而且还耗费cpu。
      gzip_types text/HTML text/plain application/x-javascript text/css application/xml;

      设置完成后,重启nginx,即可生效。下面我们来看看浏览器和服务器进行gzip压缩的请求和处理返回过程(实际上在我的《标准Web系统的架构分层》文章中,已经有所提及):

 

  • 整个请求过程来看,开启gzip和不开启gip功能,其http的请求和返回过程是一致的,不同的是参数。这个可以看看我的另外一篇文章《标准Web系统的架构分层》http://blog.csdn.net/yinwenjie/article/details/46480485

  • 当开启HTTP的gzip功能时,客户端发出http请求时,会通过headers中的Accept-Encoding属性告诉服务器“我支持gzip解压,解压格式(算法)deflate,sdch为:”。Accept-Encoding:gzip,deflate,sdch

  • 注意,不是request说自己支持解压,Nginx返回response数据的时候就一定会压缩。这还要看本次Nginx返回数据的格式是什么,如果返回数据的原始数据格式,和设置的gzip_types相符合,这时Nginx才会进行压缩。

  • Nginx返回response headers是,如果数据被压缩了,就会在Content-Encoding属性中标示gzip,表示接下来返回的response content是经过压缩的;并且在Content-Type属性中表示数据的原始格式。

  • 最后返回经过压缩的response content给客户端,客户端再进行解压。这里注意一下,在客户端发送的headers里面,有一个deflate,sdch。这是两种压缩算法,如果读者感兴趣,可以查查相关的资料(我建议查查,了解哈弗曼压缩算法对扩展自己的架构思路很有帮助)

rewrite

本小结内容,假定读者了解正则表达式。如果您不清楚正则表达式,请首先Google或者百度,正则表达式不在我们讨论的范围内。

Nginx的强大在于其对URL请求的重写(重定位)。Nginx的rewrite功能依赖于PCRE Lib,请一定在Nginx编译安装时,安装Pcre lib。请参见我的上一篇文章《架构设计:负载均衡层设计方案(2)——Nginx安装》http://blog.csdn.net/yinwenjie/article/details/46620711

我们先从讲解rewrite的关键语法,然后出示几个示例,由示例进行讲解。先来说一下Nginx中几个关键的语法:

正在表达式匹配:

  • ~ 区分大小写进行正则表达式匹配
  • ~* 不区分大小写进行正则表达式匹配
  • !~ 区分大小写进行正则表达式不匹配
  • !~* 不区分大小写进行正则表达式不匹配

举例说明:

示例1:location ~* \.(jpg|gif|png|ioc|jpeg)$

location是Nginx中的关键字,代表当前的URL请求值。
以上表达式表示对URL进行不区分大小写的匹配,一旦URL以jpg或gif或png或ioc或jpeg结尾时,匹配成功。

示例2:$var1 ~ ^(\d+)$

var1是Nginx中使用set关键字定义的变量,以上语句代表var1和一个整数进行匹配。

Nginx中的全局变量:
从上面的各个实例中,我们已经发现Nginx是支持变量的,Nginx还内置了一些全局变量,这里列举一些比较重要的全局变量:

  • $content_length: 获取request中header部分的“Content_Length”值。
  • $content_type: 获取request中header部分的“Content_type”值。
  • $request_method: 请求方式,常用的有两种请求方式:POST、GET
  • $remote_addr: 发送请求的客户端ip
  • $remote_port: 发送请求的客户端端口
  • $request_uri: 含有参数的完整的初始URI
  • $server_addr: request到达的server的ip。
  • $server_port: 请求到达的服务器的端口号。

rewrite语法

rewrite regex replacement flag

#regex:表示当前匹配的正则表达式。只有$url大小写相关匹配regex正则表达式,这个$url才会被rewrite进行重定向。

#replacement:重定向目标规则。这个目标规则支持动态变量绑定,这个问题下文马上用示例来讲。

#flag:重定向规则。

rewrite中的Flag关键字

  • redirect:通知客户端重定向到rewrtie后面的地址。
  • permanent:通知客户端永久重定向到rewrtie后面的地址。
  • last:将rewrite后的地址重新在server标签执行。
  • break:将rewrite后地址重新在当前的location标签执行。

实际上针对客户端来说,其效果是一样的,都是由客户端重新发起http请求,请求地址重新定位到replacement规则的URL地址;这里关键要讲解最常用的last和break两个关键字:

所有的rewrite语句都是要在server中的location中书写的,如下:
server {
    。。。。。。
    。。。。。。
    location ... {
        if(...) {
            rewirte regex replacement flag;
        }
        rewirte regex replacement flag;
    }
}

那么,break关键字说明重写的replacement地址在当前location的区域马上执行。
last关键字说明重写的replacement地址在当前server所有的location中重新再做匹配。

下面我们结合rewrite关键字和rewrite flag关键字给出典型的示例进行讲解:

示例1:
location ~* ^/(.+)/(.+)\.(jpg|gif|png|jpeg)$ {
    rewrite ^/orderinfo/(.+)\.(jpg|gif|png|jpeg)$   /img/$1.$2   break;
    root   /cephclient;
}

location在不进行大小写区分的情况下利用正则表达式对$url进行匹配。当匹配成功后进行rewrite重定位。
rewrite进行重写url的规则是:regex表达式第一个括号中的内容对应$1,regex表达式第二个括号中的内容对应$2,以此类推。
这样重定位的意义就很明确了:将任何目录下的文件名重定位到img目录下的对应文件名,
并且马上在这个location中(注意是Nginx,而不是客户端)执行这个重写后的URL定位。


示例2:
server {
    。。。。
    。。。。
    location ~* ^/orderinfo/(.+)\.(jpg|gif|png|jpeg)$ {
        rewrite ^/orderinfo/(.+)\.(.+)$  /img/$1.$2   last;
    }

    location / {
        root   /cephclient;
    }
}

在server中,有两个location位置,当url需要访问orderinfo目录下的某一个图片时,rewrite将重写这个url,
并且重新带入这个url到server执行,这样“location /”这个location就会执行了,并找到图片存储的目录。

健康检查模块

在本小节我们介绍一个用于Nginx对后端UpStream集群节点健康状态检查的第三方模块:nginx_upstream_check_module(https://github.com/yaoweibin/nginx_upstream_check_module)。这个模块有资料介绍是TaoBao团队开发的,但是我在GitHua上试图求证时并没有找到直接证据。

这里需要说明的是,目前有很多Nginx模块实现Nginx对后端集群节点的健康监测,不止nginx_upstream_check_module。Nginx官方有一个模块healthcheck_nginx_upstreams也可以实现对后端节点的健康监测(https://github.com/cep21/healthcheck_nginx_upstreams有详细的安装和使用介绍)

我们回到对nginx_upstream_check_module的讲解,要使用这个第三方模块首先您需要进行下载,然后通过patch命令将补丁打入您原有的Nginx源码中,并且重新进行编译安装。下面我们来重点讲解一下这个模块的安装和使用。

下载nginx_upstream_check_module模块:

wget https://codeload.github.com/yaoweibin/nginx_upstream_check_module/zip/master

您也可以直接到GitHua上进行下载,还一个在linux系统上使用git命令进行下载。

解压安装,并补丁打入Nginx源码

# unzip ./nginx_upstream_check_module-master.zip

注意是将补丁打入Nginx源码,不是Nginx的安装路径:

# cd ./nginx-1.6.2

# patch -p1 < ../nginx_upstream_check_module-master/check_1.5.12+.patch

如果补丁安装成功,您将看到以下的提示信息:
patching file src/http/modules/ngx_http_upstream_ip_hash_module.c
patching file src/http/modules/ngx_http_upstream_least_conn_module.c
patching file src/http/ngx_http_upstream_round_robin.c
patching file src/http/ngx_http_upstream_round_robin.h

这里请注意:在nginx_upstream_check_module官网的安装说明中,有一个打补丁的注意事项:
If you use nginx-1.2.1 or nginx-1.3.0, the nginx upstream round robin
module changed greatly. You should use the patch named
'check_1.2.1.patch'.
If you use nginx-1.2.2+ or nginx-1.3.1+, It added the upstream
least_conn module. You should use the patch named 'check_1.2.2+.patch'.
If you use nginx-1.2.6+ or nginx-1.3.9+, It adjusted the round robin
module. You should use the patch named 'check_1.2.6+.patch'.
If you use nginx-1.5.12+, You should use the patch named
'check_1.5.12+.patch'.
If you use nginx-1.7.2+, You should use the patch named
'check_1.7.2+.patch'.

这里我们的Nginx的版本是1.6.2,那么就应该打入check_1.5.12+.patch这个补丁

重新编译安装Nginx:

注意重新编译Nginx,要使用add-module参数将这个第三方模块安装进去:

# ./configure --prefix=/usr/nginx-1.6.2/ --add-module=../nginx_upstream_check_module-master/

# make && make install

通过以上的步骤,第三方的nginx_upstream_check_module模块就在Nginx中准备好了。接下来我们讲解一下如何使用这个模块。首先看一下upstream的配置信息:

upstream cluster {
    # simple round-robin
    server 192.168.0.1:80;
    server 192.168.0.2:80;

    check interval=5000 rise=1 fall=3 timeout=4000;

    #check interval=3000 rise=2 fall=5 timeout=1000 type=ssl_hello;
    #check interval=3000 rise=2 fall=5 timeout=1000 type=http;
    #check_http_send "HEAD / HTTP/1.0\r\n\r\n";
    #check_http_expect_alive http_2xx http_3xx;
}

上面的代码中,check部分就是调用nginx_upstream_check_module模块的语法:

check interval=milliseconds [fall=count] [rise=count]
[timeout=milliseconds] [default_down=true|false]
[type=tcp|http|ssl_hello|mysql|ajp|fastcgi]

interval:必要参数,检查请求的间隔时间。

fall:当检查失败次数超过了fall,这个服务节点就变成down状态。

rise:当检查成功的次数超过了rise,这个服务节点又会变成up状态。

timeout:请求超时时间,超过等待时间后,这次检查就算失败。

default_down:后端服务器的初始状态。默认情况下,检查功能在Nginx启动的时候将会把所有后端节点的状态置为down,检查成功后,在置为up。

type:这是检查通信的协议类型,默认为http。以上类型是检查功能所支持的所有协议类型。

check_http_send http_packet

http_packet的默认格式为:"GET / HTTP/1.0\r\n\r\n"

check_http_send设置,这个设置描述了检查模块在每次检查时,向后端节点发送什么样的信息

check_http_expect_alive [ http_2xx | http_3xx | http_4xx | http_5xx ]

这些状态代码表示服务器的HTTP响应上是OK的,后端节点是可用的。默认情况的设置是:http_2xx | http_3xx

当您根据您的配置要求完成检查模块的配置后,请首先使用nginx -t 命令监测配置文件是否可用,然后在用nginx -s reload重启nginx。

不得不提的tengine

Tengine是由淘宝网发起的Web服务器项目。它在Nginx的基础上,针对大访问量网站的需求,添加了很多高级功能和特性。Tengine的性能和稳定性已经在大型的网站如淘宝网,天猫商城等得到了很好的检验。它的最终目标是打造一个高效、稳定、安全、易用的Web平台(http://tengine.taobao.org/)。

您应该懂了,我建议您根据业务的实际情况,适时在生产环境引入Tengine。但在本博客发布时,Tengine的2.X版本还不稳定,所以建议实用1.5.2的稳定版本。请记住Tengine就是经过升读改造后的Nginx

 

术语说明

  • TPS: 衡量业务层处理性能的重要指标(每秒钟request/事务的处理数量)。业务服务处理一个完整的业务过程,并向上层返回处理结果的过程就是一个 request/事务。那么在一秒钟内整个业务系统能够完成多少个这样的过程,其衡量单位就是TPS。TPS不但和系统架构有很大的关系(特别是业务层和业务通信层的架构祥泰),和物理环境、代码质量的关系也非常密切。

  • PV: 网页浏览数是评价网站流量最常用的指标之一,简称为PV。Page Views中的Page一般是指普通的html网页,也包含php、jsp等动态产生的html内容。注意是完整的显示一个Page成为一个PV。但是一个PV,一般需要多次HTTP请求,以便获取多个静态资源,这是需要注意的。

  • UV: Unique Visitor 一个独立IP,在一个单位时间内(例如一日/一小时)对系统的一个PV请求,成为一个UV(重复的PV不在进行计数)。

  • RUV: Repeat User Visitor 一个独立用户,在一个单位时间内(例如一日/一小时)对系统的一个PV请求,并且重复的访问要进行计数。

 

参考博客:http://blog.csdn.net/yinwenjie/article/details/46742661

 

posted @ 2016-08-06 15:27  yxy_linux  阅读(565)  评论(0编辑  收藏  举报