Nginx常用配置

Nginx常用命令

  1. 启动 Nginx
poechant@ubuntu:sudo ./sbin/nginx
  1. 停止 Nginx
poechant@ubuntu:sudo ./sbin/nginx -s stoppoechant@ubuntu:sudo ./sbin/nginx -s quit
-s都是采用向 Nginx 发送信号的方式。
  1. Nginx 重载配置
poechant@ubuntu:sudo ./sbin/nginx -s reload

上述是采用向 Nginx 发送信号的方式,或者使用:

poechant@ubuntu:service nginx reload
  1. 指定配置文件
poechant@ubuntu:sudo ./sbin/nginx -c /usr/local/nginx/conf/nginx.conf
-c表示configuration,指定配置文件。
  1. 查看 Nginx 版本

有两种可以查看 Nginx 的版本信息的参数。第一种如下:

poechant@ubuntu:/usr/local/nginx$ ./sbin/nginx -v
nginx: nginx version: nginx/1.0.0

另一种显示的是详细的版本信息:

poechant@ubuntu:/usr/local/nginx$ ./sbin/nginx -V
nginx: nginx version: nginx/1.0.0
nginx: built by gcc 4.3.3 (Ubuntu 4.3.3-5ubuntu4) 
nginx: TLS SNI support enabled
nginx: configure arguments: --with-http_ssl_module --with-openssl=/home/luming/openssl-1.0.0d/
  1. 检查配置文件是否正确
poechant@ubuntu:/usr/local/nginx$ ./sbin/nginx -t
nginx: [alert] could not open error log file: open() "/usr/local/nginx/logs/error.log" failed (13: Permission denied)
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
2012/01/09 16:45:09 [emerg] 23898#0: open() "/usr/local/nginx/logs/nginx.pid" failed (13: Permission denied)
nginx: configuration file /usr/local/nginx/conf/nginx.conf test failed
如果出现如上的提示信息,表示没有访问错误日志文件和进程,可以sudo(super user do)一下:

poerchant@ubuntu:/usr/local/nginx$ sudo ./sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
如果显示如上,则表示配置文件正确。否则,会有相关提示。
  1. 显示帮助信息
poechant@ubuntu:/user/local/nginx$ ./sbin/nginx -h

或者:

poechant@ubuntu:/user/local/nginx$ ./sbin/nginx -?
以上这些涵盖了 Nginx 日常维护的所有基本操作,另外还有向 master 进程发送信号的相关命令,我们会在后续看到。

配置文件详解

Nginx配置文件的分块下,基本就分为以下几块:

main # 全局设置
events { # Nginx工作模式
    ....
}
http { # http设置
    ....
    upstream myproject { # 负载均衡服务器设置
        .....
    }
    server  { # 主机设置
        ....
        location { # URL匹配
            ....
        }
    }
    server  {
        ....
        location {
            ....
        }
    }
    ....
}

1 main模块

下面是一个main区域,它是一个全局的设置:

user nobody nobody;
worker_processes 2;
error_log /usr/local/var/log/nginx/error.log notice;
pid /usr/local/var/run/nginx/nginx.pid;
worker_rlimit_nofile 1024;

user 来指定Nginx Worker进程运行用户以及用户组,默认由nobody账号运行。

worker_processes 来指定了Nginx要开启的子进程数。每个Nginx进程平均耗费10M~12M内存。根据经验,一般指定1个进程就足够了,如果是多核CPU,建议指定和CPU的数量一样的进程数即可。我这里写2,那么就会开启2个子进程,总共3个进程。

error_log 来定义全局错误日志文件。日志输出级别有debug、info、notice、warn、error、crit可供选择,其中,debug输出日志最为最详细,而crit输出日志最少。

pid 来指定进程id的存储文件位置

worker_rlimit_nofile 来指定一个nginx进程可以打开的最多文件描述符数目,这里是65535,需要使用命令“ulimit -n 65535”来设置。

2 events模块

events模块来用指定nginx的工作模式和工作模式及连接数上限,一般是这样:

events {
    use kqueue; #mac平台
    worker_connections  1024;
}

use 用来指定Nginx的工作模式。Nginx支持的工作模式有select、poll、kqueue、epoll、rtsig和/dev/poll。其中select和poll都是标准的工作模式,kqueue和epoll是高效的工作模式,不同的是epoll用在Linux平台上,而kqueue用在BSD系统中,因为Mac基于BSD,所以Mac也得用这个模式,对于Linux系统,epoll工作模式是首选。

worker_connections 用于定义Nginx每个进程的最大连接数,即接收前端的最大请求数,默认是1024。最大客户端连接数由worker_processes和worker_connections决定,即Max_clients = worker_processes * worker_connections,在作为反向代理时,Max_clients变为:Max_clients = worker_processes * worker_connections / 4。

进程的最大连接数受Linux系统进程的最大打开文件数限制,在执行操作系统命令“ulimit -n 65536”后worker_connections的设置才能生效。

3 http模块

http模块可以说是最核心的模块了,它负责HTTP服务器相关属性的配置,它里面的server和upstream子模块,至关重要,等到反向代理和负载均衡以及虚拟目录等会仔细说。

http {
    include mime.types;
    default_type application/octet-stream;
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
    access_log /usr/local/var/log/nginx/access.log  main;
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 10;
    #gzip on;
    upstream myproject {
        .....
    }
    server {
        ....
    }
}

  1. include

用来设定文件的mime类型,类型在配置文件目录下的mime.type文件定义,来告诉nginx来识别文件类型。

  1. default_type

设定了默认的类型为二进制流,也就是当文件类型未定义时使用这种方式,例如在没有配置asp的locate 环境时,Nginx是不予解析的,此时,用浏览器访问asp文件就会出现下载窗口了。

  1. log_format

用于设置日志的格式,和记录哪些参数,这里设置为main,刚好用于access_log来纪录这种类型

main的类型日志如下:也可以增删部分参数。

127.0.0.1 - - [21/Apr/2015:18:09:54 +0800] "GET /index.php HTTP/1.1" 200 87151 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.76 Safari/537.36"

  1. access_log

用来纪录每次的访问日志的文件地址,后面的main是日志的格式样式,对应于log_format的main。

  1. sendfile

用于开启高效文件传输模式。将tcp_nopush和tcp_nodelay两个指令设置为on用于防止网络阻塞。

  1. keepalive_timeout

设置客户端连接保持活动的超时时间。在超过这个时间之后,服务器会关闭该连接。

4 server模块

server模块是http的子模块,它用来定一个虚拟主机,我们先讲最基本的配置,这些在后面再讲。我们看一下一个简单的server是如何做的?

server {
    listen 8080;
    server_name localhost 192.168.12.10 www.yangyi.com;
    # 全局定义,如果都是这一个目录,这样定义最简单。
    root   /Users/yangyi/www;
    index  index.php index.html index.htm; 
    charset utf-8;
    access_log  usr/local/var/log/host.access.log  main;
    error_log  usr/local/var/log/host.error.log  error;
    ....
}

server 标志定义虚拟主机开始。

listen 用于指定虚拟主机的服务端口。

server_name 用来指定IP地址或者域名,多个域名之间用空格分开。

root 表示在这整个server虚拟主机内,全部的root web根目录。注意要和locate {}下面定义的区分开来。

index 全局定义访问的默认首页地址。注意要和locate {}下面定义的区分开来。

charset 用于设置网页的默认编码格式。

access_log 用来指定此虚拟主机的访问日志存放路径,最后的main用于指定访问日志的输出格式。

5 location模块

location模块是nginx中用的最多的,也是最重要的模块了,什么负载均衡啊、反向代理啊、虚拟域名啊都与它相关

location根据它字面意思就知道是来定位的,定位URL,解析URL,所以,它也提供了强大的正则匹配功能,也支持条件判断匹配,用户可以通过location指令实现Nginx对动、静态网页进行过滤处理。像我们的php环境搭建就是用到了它。

  1. 我们先来看这个,设定默认首页和虚拟机目录
location / {
    root   /Users/yangyi/www;
    index  index.php index.html index.htm;
}

location / 表示匹配访问根目录。

root 指令用于指定访问根目录时,虚拟主机的web目录,这个目录可以是相对路径(相对路径是相对于nginx的安装目录)。也可以是绝对路径

index 用于设定我们只输入域名后访问的默认首页地址,有个先后顺序:index.php index.html index.htm,如果没有开启目录浏览权限,又找不到这些默认首页,就会报403错误。

  1. location 还有一种方式就是正则匹配

下面这个例子是运用正则匹配来链接php。我们之前搭建环境也是这样做:

location ~ \.php$ {
    root           /Users/yangyi/www;
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    include        fastcgi.conf;
}

.php$ 熟悉正则的我们直到,这是匹配.php结尾的URL,用来解析php文件。里面的root也是一样,用来表示虚拟主机的根目录

fastcgi_pass 链接的是php-fpm的地址。其他几个参数我们以后再说。

location 还有其他用法,等讲到实例的时候,再看吧。

6 upstream模块

upstream 模块负责负载均衡模块,通过一个简单的调度算法来实现客户端IP到后端服务器的负载均衡。先学习怎么用,具体的使用实例以后再说。

upstream iyangyi.com{
    ip_hash;
    server 192.168.12.1:80;
    server 192.168.12.2:80 down;
    server 192.168.12.3:8080  max_fails=3  fail_timeout=20s;
    server 192.168.12.4:8080;
}

在上面的例子中,通过upstream指令指定了一个负载均衡器的名称iyangyi.com。这个名称可以任意指定,在后面需要的地方直接调用即可。里面是ip_hash这是其中的一种负载均衡调度算法,下面会着重介绍。紧接着就是各种服务器了。用server关键字表识,后面接ip

Nginx的负载均衡模块目前支持4种调度算法:

  1. weight 轮询(默认)。每个请求按时间顺序逐一分配到不同的后端服务器,如果后端某台服务器宕机,故障系统被自动剔除,使用户访问不受影响。weight,指定轮询权值,weight值越大,分配到的访问机率越高,主要用于后端每个服务器性能不均的情况下。

  2. ip_hash。每个请求按访问IP的hash结果分配,这样来自同一个IP的访客固定访问一个后端服务器,有效解决了动态网页存在的session共享问题。

  3. fair(第三方)。比上面两个更加智能的负载均衡算法。此种算法可以依据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间来分配请求,响应时间短的优先分配。Nginx本身是不支持fair的,如果需要使用这种调度算法,必须下载Nginx的upstream_fair模块。

  4. url_hash(第三方)。按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,可以进一步提高后端缓存服务器的效率。Nginx本身是不支持url_hash的,如果需要使用这种调度算法,必须安装Nginx的hash软件包。

在HTTP Upstream模块中,可以通过server指令指定后端服务器的IP地址和端口,同时还可以设定每个后端服务器在负载均衡调度中的状态。常用的状态有:

  1. down,表示当前的server暂时不参与负载均衡。

  2. backup,预留的备份机器。当其他所有的非backup机器出现故障或者忙的时候,才会请求backup机器,因此这台机器的压力最轻。

  3. max_fails,允许请求失败的次数,默认为1。当超过最大次数时,返回proxy_next_upstream 模块定义的错误。

  4. fail_timeout,在经历了max_fails次失败后,暂停服务的时间。max_fails可以和fail_timeout一起使用。

注意:当负载调度算法为ip_hash时,后端服务器在负载均衡调度中的状态不能是weight和backup。

基于域名的虚拟主机

有的网站访问量大,需要负载均衡。然而并不是所有网站都如此出色,有的网站,由于访问量太小,需要节省成本,将多个网站部署在同一台服务器上。

例如将www.aaa.comwww.bbb.com两个网站部署在同一台服务器上,两个域名解析到同一个IP地址,但是用户通过两个域名却可以打开两个完全不同的网站,互相不影响,就像访问两个服务器一样,所以叫两个虚拟主机。

配置:

server {
    listen 80 default_server;
    server_name _;
    return 444; # 过滤其他域名的请求,返回444状态码
}
server {
    listen 80;
    server_name www.aaa.com; # www.aaa.com域名
    location / {
        proxy_pass http://localhost:8080; # 对应端口号8080
    }
}
server {
    listen 80;
    server_name www.bbb.com; # www.bbb.com域名
    location / {
        proxy_pass http://localhost:8081; # 对应端口号8081
    }
}

在服务器8080和8081分别开了一个应用,客户端通过不同的域名访问,根据server_name可以反向代理到对应的应用服务器。

虚拟主机的原理是通过HTTP请求头中的Host是否匹配server_name来实现的,有兴趣的同学可以研究一下HTTP协议。

另外,server_name配置还可以过滤有人恶意将某些域名指向你的主机服务器。

建议将对虚拟主机进行配置的内容写进另外一个文件,然后通过include指令包含进来,这样更便于维护和管理,不会使得这个nginx.conf内容太多.

反向代理

Nginx 使用反向代理,主要是使用location模块下的proxy_pass选项。

来个最简单的。当我访问 mac 上的nginx 的 centos.iyangyi.com 的内容时候, 就反向代理到虚拟机centos上的 apache 192.168.33.10 的index.html页面。

192.168.33.10 中的html 是很简单的一句输出:

centos apache2 index.html

在hosts里新加上这个域名:

#vi /etc/hosts 
127.0.0.1 centos.iyangyi.com

在vhost目录中新建一个conf server:

#centos.iyangyi.conf
server {
    listen 80;
    server_name centos.iyangyi.com;

    access_log /usr/local/var/log/nginx/centos.iyangyi.access.log main;
    error_log /usr/local/var/log/nginx/centos.iyangyi.error.log error;

    location / {
        proxy_pass http://192.168.33.10;
    }
}

重启下nginx:

sudo nginx -s reload

当然。proxy 还有其他的参数,比如:proxy_set_header 用来设置header头部信息参数转发等,等用了可以仔细看看。

负载均衡

别被这个名字给吓住了,以为是什么很牛逼的东西的。其实不然。也很简单。

先简单说下负载均衡是干嘛的?举个例子:我们的小网站,刚开始就一台nginx服务器,后来,随着业务量增大,用户增多,一台服务器已经不够用了,我们就又多加了几台服务器。那么这几台服务器如何调度?如何均匀的提供访问?这就是负载均衡。

负载均衡的好处是可以集群多台机器一起工作,并且对外的IP和域名是一样的,外界看起来就好像一台机器一样。

  1. 基于 weight 权重的负载

先来一个最简单的,weight权重的:

upstream webservers{
    server 192.168.33.11 weight=10;
    server 192.168.33.12 weight=10;
    server 192.168.33.13 weight=10;
}

server {
    listen 80;
    server_name upstream.iyangyi.com;

    access_log /usr/local/var/log/nginx/upstream.iyangyi.access.log main;
    error_log /usr/local/var/log/nginx/upstream.iyangyi.error.log error;

    location / {
        proxy_pass http://webservers;
        proxy_set_header  X-Real-IP  $remote_addr;
    }
}

我们再来继续看几个参数 : max_fails和fail_timeout

**max_fails : **允许请求失败的次数,默认为1。当超过最大次数时,返回proxy_next_upstream 模块定义的错误。

**fail_timeout : **在经历了max_fails次失败后,暂停服务的时间。max_fails可以和fail_timeout一起使用,进行健康状态检查。

upstream webservers{
    server 192.168.33.11 weight=10 max_fails=2 fail_timeout=30s;
    server 192.168.33.12 weight=10 max_fails=2 fail_timeout=30s;
    server 192.168.33.13 weight=10 max_fails=2 fail_timeout=30s;
}

down: 表示这台机器暂时不参与负载均衡。相当于注释掉了。

backup: 表示这台机器是备用机器,是其他的机器不能用的时候,这台机器才会被使用,俗称备胎

upstream webservers{
    server 192.168.33.11 down;
    server 192.168.33.12 weight=10 max_fails=2 fail_timeout=30s;
    server 192.168.33.13 backup;
}
  1. 基于 ip_hash 的负载

这种分配方式,每个请求按访问IP的hash结果分配,这样来自同一个IP的访客固定访问一个后端服务器,有效解决了动态网页存在的session共享问题。

upstream webservers{
    ip_hash;
    server 192.168.33.11 weight=1 max_fails=2 fail_timeout=30s;
    server 192.168.33.12 weight=1 max_fails=2 fail_timeout=30s;
    server 192.168.33.13 down;
}

ip_hash 模式下,最好不要设置weight参数,因为你设置了,就相当于手动设置了,将会导致很多的流量分配不均匀。

ip_hash 模式下,backup参数不可用,加了会报错,为啥呢?因为,本身我们的访问就是固定的了,其实,备用已经不管什么作用了。

页面缓存

页面缓存也是日常web 开发中很重要的一个环节,对于一些页面,我们可以将其静态化,保存起来,下次请求时候,直接走缓存,而不用去请求反相代理服务器甚至数据库服务了。从而减轻服务器压力。

nginx 也提供了简单而强大的下重定向,反向代理的缓存功能,只需要简单配置下,就能将指定的一个页面缓存起来。它的原理也很简单,就是匹配当前访问的url, hash加密后,去指定的缓存目录找,看有没有,有的话就说明匹配到缓存了。

我们先来看一下一个简单的页面缓存的配置:

http {
    proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=cache_zone:10m inactive=1d max_size=100m;
    upstream myproject {
        .....
    }
    server  {
        ....
        location ~ *\.php$ {
            proxy_cache cache_zone; #keys_zone的名字
            proxy_cache_key $host$uri$is_args$args; #缓存规则
            proxy_cache_valid any 1d;
            proxy_pass http://127.0.0.1:8080;
        }
    }
    ....
}

下面我们来一步一步说。用到的配置参数,主要是proxy_*前缀的很多配置。

首先需要在http中加入proxy_cache_path 它用来制定缓存的目录以及缓存目录深度制定等。它的格式如下:

proxy_cache_path path [levels=number] keys_zone=zone_name:zone_size [inactive=time] [max_size=size]; 

path是用来指定 缓存在磁盘的路径地址。比如:/data/nginx/cache。那以后生存的缓存文件就会存在这个目录下。

levels用来指定缓存文件夹的级数,可以是:levels=1, levels=1:1, levels=1:2, levels=1:2:3 可以使用任意的1位或2位数字作为目录结构分割符,如 X, X:X,或 X:X:X 例如: 2, 2:2, 1:1:2,但是最多只能是三级目录。

那这个里面的数字是什么意思呢。表示取hash值的个数。比如:

现在根据请求地址localhost/index.php?a=4 用md5进行哈希,得到e0bd86606797639426a92306b1b98ad9

levels=1:2 表示建立2级目录,把hash最后1位(9)拿出建一个目录,然后再把9前面的2位(ad)拿来建一个目录, 那么缓存文件的路径就是/data/nginx/cache/9/ad/e0bd86606797639426a92306b1b98ad9

以此类推:levels=1:1:2表示建立3级目录,把hash最后1位(9)拿出建一个目录,然后再把9前面的1位(d)建一个目录, 最后把d前面的2位(8a)拿出来建一个目录 那么缓存文件的路径就是/data/nginx/cache/9/d/8a/e0bd86606797639426a92306b1b98ad9

keys_zone 所有活动的key和元数据存储在共享的内存池中,这个区域用keys_zone参数指定。zone_name指的是共享池的名称,zone_size指的是共享池的大小。注意每一个定义的内存池必须是不重复的路径,例如:

proxy_cache_path  /data/nginx/cache/one  levels=1      keys_zone=one:10m;
proxy_cache_path  /data/nginx/cache/two  levels=2:2    keys_zone=two:100m;
proxy_cache_path  /data/nginx/cache/three  levels=1:1:2  keys_zone=three:1000m;

inactive 表示指定的时间内缓存的数据没有被请求则被删除,默认inactive为10分钟。inactive=1d 1小时。inactive=30m 30分钟。

max_size 表示单个文件最大不超过的大小。它被用来删除不活动的缓存和控制缓存大小,当目前缓存的值超出max_size指定的值之后,超过其大小后最少使用数据(LRU替换算法)将被删除。max_size=10g表示当缓存池超过10g就会清除不常用的缓存文件。

clean_time 表示每间隔自动清除的时间。clean_time=1m 1分钟清除一次缓存。

好。说完了这个很重要的参数。我们再来说在server模块里的几个配置参数:

proxy_cache 用来指定用哪个keys_zone的名字,也就是用哪个目录下的缓存。上面我们指定了三个one, two,three 。比如,我现在想用one 这个缓存目录 : proxy_cache one

proxy_cache_key 这个其实蛮重要的,它用来指定生成hash的url地址的格式。根据这个key映射成一个hash值,然后存入到本地文件。proxy_cache_key $host$uri表示无论后面跟的什么参数,都会访问一个文件,不会再生成新的文件。 而如果proxy_cache_key $is_args$args,那么传入的参数 localhost/index.php?a=4 与localhost/index.php?a=44 将映射成两个不同hash值的文件。

proxy_cache_key 默认是 "$scheme$host$request_uri"。但是一般我们会把它设置成:$host$uri$is_args$args 一个完整的url路径。

proxy_cache_valid 它是用来为不同的http响应状态码设置不同的缓存时间。

proxy_cache_valid  200 302  10m;
proxy_cache_valid  404      1m;

表示为http status code 为200和302的设置缓存时间为10分钟,404代码缓存1分钟。 如果只定义时间:

proxy_cache_valid 5m;

那么只对代码为200, 301和302的code进行缓存。 同样可以使用any参数任何相响应:

proxy_cache_valid  200 302 10m;
proxy_cache_valid  301 1h;
proxy_cache_valid  any 1m; #所有的状态都缓存1小时

好。缓存的基本一些配置讲完了。也大致知道了怎么使用这些参数。现在开始实战!我们启动一台vagrant linux 机器 web1 (192.168.33.11) 用作远程代理机器,就不搞复杂的负载均衡了。

先在Mac本地加一个域名cache.iyangyi.com, 然后按照上面的配置在vhost 下新建一个proxy_cache.iyangyi.conf 文件:

proxy_cache_path /usr/local/var/cache levels=1:2 keys_zone=cache_zone:10m inactive=1d max_size=100m;
server  {
    listen 80;
    server_name cache.iyangyi.com;

    access_log /usr/local/var/log/nginx/cache.iyangyi.access.log main;
    error_log /usr/local/var/log/nginx/cache.iyangyi.error.log error;

    add_header X-Via $server_addr;
    add_header X-Cache $upstream_cache_status;

    location / {
        proxy_set_header  X-Real-IP  $remote_addr;
        proxy_cache cache_zone;
        proxy_cache_key $host$uri$is_args$args;
        proxy_cache_valid 200 304 1m;
        proxy_pass http://192.168.33.11;
    }
}

打开审核元素或者firebug。看network网络请求选项,我们可以看到,Response Headers,在这里我们可以看到:

X-Cache:MISS
X-Via:127.0.0.1

X-cache 为 MISS 表示未命中,请求被传送到后端。因为是第一次访问,没有缓存,所以肯定是未命中。我们再刷新下,就发现其变成了HIT, 表示命中。它还有其他几种状态:

MISS 未命中,请求被传送到后端

HIT 缓存命中

EXPIRED 缓存已经过期请求被传送到后端

UPDATING 正在更新缓存,将使用旧的应答

STALE 后端将得到过期的应答

BYPASS 缓存被绕过了

我们再去看看缓存文件夹 /usr/local/var/cache里面是否有了文件:

cache git:(master) cd a/13
➜  13 git:(master) ls
5bd1af99bcb0db45c8bd601d9ee9e13a
➜  13 git:(master) pwd
/usr/local/var/cache/a/13

已经生成了缓存文件。

我们在url 后面随便加一个什么参数,看会不会新生成一个缓存文件夹及文件:http://cache.iyangyi.com/?w=ww55 。因为我们使用的生成规则是全部url转换(proxy_cache_key $host$uri$is_args$args;)

查看 X-cache 为 MISS,再刷新 ,变成HIT。再去看一下缓存文件夹 /usr/local/var/cache。

~cache git:(master) ls
 4 a

果然又生成了一个4文件夹。

location 正则模块

这一小节,主要来学习nginx中的URL重写怎么做。url重写模块,主要是在location模块面来实现,我们一点一点的看。

首先看下location 正则匹配的使用。还记得之前是如何用location来定位.php文件的吗?

location ~ \.php$ {
    fastcgi_pass   127.0.0.1:9000; 
    fastcgi_index  index.php;
    include        fastcgi.conf;
}

我们用~来表示location开启正则匹配, 这样:location ~。还可以用这个来匹配静态资源,缓存它们,设置过期时间:

location ~ .*\.(gif|jpg|jpeg|bmp|png|ico|txt|mp3|mp4|swf){
    expires 15d;
}
location ~ .*\.(css|js){
    expires 12h;
}

expires 用来设置HTTP应答中的Expires和Cache-Control的头标时间,来告诉浏览器访问这个静态文件时,不用再去请求服务器,直接从本地缓存读取就可以了

语法: expires [time|epoch|max|off]
默认值: expires off
作用域: http, server, location

可以在time值中使用正数或负数。“Expires”头标的值将通过当前系统时间加上您设定的 time 值来获得。可以设置的参数如下:

epoch 指定“Expires”的值为 1 January, 1970, 00:00:01 GMT。

max 指定“Expires”的值为 31 December 2037 23:59:59 GMT,“Cache-Control”的值为10年。

-1 指定“Expires”的值为 服务器当前时间 -1s,即永远过期。

负数:Cache-Control: no-cache。

正数或零:Cache-Control: max-age = #, # 会转换为指定时间的秒数。比如:1d、2h、3m。

off 表示不修改“Expires”和“Cache-Control”的值。

比如再看个例子: 控制图片等过期时间为30天

location ~ \.(gif|jpg|jpeg|png|bmp|ico)$ {
    expires 30d;
}

我们还可以控制哪一个文件目录的时间,比如控制匹配/resource/或者/mediatorModule/里所有的文件缓存设置到最长时间。

location ~ /(resource|mediatorModule)/ {
    root    /opt/demo;
    expires max;
}

URL重写模块

重写模块与很多模块一起使用。先看一下是怎么用的,看2个例子,然后我们再一点一点讲每个的使用方法:

location /download/ {
    if ($forbidden) {
        return   403;
    }
    if ($slow) {
        limit_rate  10k;
    }
    rewrite ^/(download/.*)/media/(.*)\..*$  /$1/mp3/$2.mp3 break;
    ......
}
location / {
    root   html;
    index  index.html index.htm;
    rewrite ^/bbs/(.*)$ http://192.168.18.201/forum/$1;
}

上面2个例子就是利用rewrite来完成URL重写的。我们慢慢来看它的用法。

  1. break

break和编程语言中的用法一样,就是跳出某个逻辑。

语法:break

默认值:none

使用字段:server, location, if

if (!-f $request_filename) {
    break;
}

上面这个例子就是在if里面使用break,意思是如果访问的文件名不存在,就跳出。后续会有更多的例子。

  1. if

if 判断一个条件,如果条件成立,则后面的大括号内的语句将执行,相关配置从上级继承。

语法:if (condition) { … }

默认值:none

使用字段:server, location

可以在判断语句中指定下列值:

一个变量的名称;不成立的值为:空字符传”“或者一些用“0”开始的字符串。

一个使用=或者!=运算符的比较语句。

使用符号*和模式匹配的正则表达式:

~为区分大小写的匹配。

~*不区分大小写的匹配(firefox匹配FireFox)。

!和!*意为“不匹配的”。

使用-f和!-f检查一个文件是否存在。

使用-d和!-d检查一个目录是否存在。

使用-e和!-e检查一个文件,目录或者软链接是否存在。

使用-x和!-x检查一个文件是否为可执行文件。

$http_user_agent变量获取浏览器的agent,使用~ 来匹配大小写。用户如果使用的IE 浏览器,就执行if里面的操作。

if ($http_user_agent ~ MSIE) {
    rewrite  ^(.*)$  /msie/$1  break;
}

$request_method变量获取请求的方法,使用=来判断是否等于POST 。如果复合,就执行if 里面的操作。

if ($request_method = POST ) {
    return 405;
}

$request_filename变量获取请求的文件名,使用!-f来匹配文件,如果不是一个文件名,就执行if 里面的逻辑。

if (!-f $request_filename) {
    break;
    proxy_pass  http://127.0.0.1;
}
  1. return

这个指令结束执行配置语句并为客户端返回状态代码,可以使用下列的值:204,400,402-406,408,410, 411, 413, 416与500-504。此外,非标准代码444将关闭连接并且不发送任何的头部。

语法:return code

默认值:none

使用字段:server, location, if

  1. rewrite

语法:rewrite regex replacement flag

默认值:none

使用字段:server, location, if

rewrite用来重写url,有3个位置:

regex 表示用来匹配的正则

replacement 表示用来替换的

flag 是尾部的标记

flag可以是以下的值:

last - url重写后,马上发起一个新的请求,再次进入server块,重试location匹配,超过10次匹配不到报500错误,地址栏url不变

break - url重写后,直接使用当前资源,不再执行location里余下的语句,完成本次请求,地址栏url不变

redirect - 返回302临时重定向,url会跳转,爬虫不会更新url。

permanent - 返回301永久重定向。url会跳转。爬虫会更新url。

为空 - URL 不会变,但是内容已经变化,也是永久性的重定向。

上面的正则表达式的一部分可以用圆括号,方便之后按照顺序用$1-$9来引用。

我们来看几个例子:

需要将/photos/123456重写成/path/to/photos/12/1234/123456.png

可以这样:

rewrite  "/photos/([0-9] {2})([0-9] {2})([0-9] {2})" /path/to/photos/$1/$1$2/$1$2$3.png;

下面是一些简单的常见的重写:

rewrite ^/js/base.core.v3.js /js/base.core.v3.dev.js redirect;
rewrite ^/js/comment.frame.js /js/comment.frame.dev.js redirect;
rewrite ^/live-static/(.*)$ http://live.bilibili.com/public/$1 last;

配置整理

在此记录下Nginx服务器nginx.conf的配置文件说明, 部分注释收集与网络:

# 运行用户
user www-data;    
# 启动进程,通常设置成和cpu的数量相等
worker_processes  1;

# 全局错误日志及PID文件
error_log  /var/log/nginx/error.log;
pid        /var/run/nginx.pid;

# 工作模式及连接数上限
events {
    use epoll; #epoll是多路复用IO(I/O Multiplexing)中的一种方式,但是仅用于linux2.6以上内核,可以大大提高nginx的性能
    worker_connections 1024; #单个后台worker process进程的最大并发链接数
    # multi_accept on; 
}

#设定http服务器,利用它的反向代理功能提供负载均衡支持
http {
    #设定mime类型,类型由mime.type文件定义
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    #设定日志格式
    access_log    /var/log/nginx/access.log;

    #sendfile 指令指定 nginx 是否调用 sendfile 函数(zero copy 方式)来输出文件,对于普通应用,
    #必须设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为 off,以平衡磁盘与网络I/O处理速度,降低系统的uptime.
    sendfile        on;
    #将tcp_nopush和tcp_nodelay两个指令设置为on用于防止网络阻塞
    tcp_nopush      on;
    tcp_nodelay     on;
    #连接超时时间
    keepalive_timeout  65;

    #开启gzip压缩
    gzip  on;
    gzip_disable "MSIE [1-6]\.(?!.*SV1)";

    #设定请求缓冲
    client_header_buffer_size    1k;
    large_client_header_buffers  4 4k;

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;

    #设定负载均衡的服务器列表
    upstream mysvr {
        #weigth参数表示权值,权值越高被分配到的几率越大
        #本机上的Squid开启3128端口
        server 192.168.8.1:3128 weight=5;
        server 192.168.8.2:80  weight=1;
        server 192.168.8.3:80  weight=6;
    }

    server {
        #侦听80端口
        listen       80;
        #定义使用www.xx.com访问
        server_name  www.xx.com;

        #设定本虚拟主机的访问日志
        access_log  logs/www.xx.com.access.log  main;

        #默认请求
        location / {
            root   /root;      #定义服务器的默认网站根目录位置
            index index.php index.html index.htm;   #定义首页索引文件的名称

            fastcgi_pass  www.xx.com;
            fastcgi_param  SCRIPT_FILENAME  $document_root/$fastcgi_script_name; 
            include /etc/nginx/fastcgi_params;
        }

        # 定义错误提示页面
        error_page   500 502 503 504 /50x.html;  
            location = /50x.html {
            root   /root;
        }

        #静态文件,nginx自己处理
        location ~ ^/(images|javascript|js|css|flash|media|static)/ {
            root /var/www/virtual/htdocs;
            #过期30天,静态文件不怎么更新,过期可以设大一点,如果频繁更新,则可以设置得小一点。
            expires 30d;
        }
        #PHP 脚本请求全部转发到 FastCGI处理. 使用FastCGI默认配置.
        location ~ \.php$ {
            root /root;
            fastcgi_pass 127.0.0.1:9000;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME /home/www/www$fastcgi_script_name;
            include fastcgi_params;
        }
        #设定查看Nginx状态的地址
        location /NginxStatus {
            stub_status            on;
            access_log              on;
            auth_basic              "NginxStatus";
            auth_basic_user_file  conf/htpasswd;
        }
        #禁止访问 .htxxx 文件
        location ~ /\.ht {
            deny all;
        }

    }

    #第一个虚拟服务器
    server {
        #侦听192.168.8.x的80端口
        listen       80;
        server_name  192.168.8.x;

        #对aspx后缀的进行负载均衡请求
        location ~ .*\.aspx$ {
            root   /root;#定义服务器的默认网站根目录位置
            index index.php index.html index.htm;#定义首页索引文件的名称

            proxy_pass  http://mysvr;#请求转向mysvr 定义的服务器列表

            #以下是一些反向代理的配置可删除.
            proxy_redirect off;

            #后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
            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 90;  #nginx跟后端服务器连接超时时间(代理连接超时)
            proxy_send_timeout 90;        #后端服务器数据回传时间(代理发送超时)
            proxy_read_timeout 90;         #连接成功后,后端服务器响应时间(代理接收超时)
            proxy_buffer_size 4k;             #设置代理服务器(nginx)保存用户头信息的缓冲区大小
            proxy_buffers 4 32k;               #proxy_buffers缓冲区,网页平均在32k以下的话,这样设置
            proxy_busy_buffers_size 64k;    #高负荷下缓冲大小(proxy_buffers*2)
            proxy_temp_file_write_size 64k;  #设定缓存文件夹大小,大于这个值,将从upstream服务器传
        }
    }
}

参考

WEB请求处理二:Nginx请求反向代理

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 197,000评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,825评论 2 374
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 144,055评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,766评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,639评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,453评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,860评论 3 388
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,492评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,783评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,817评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,624评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,439评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,872评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,075评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,372评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,868评论 2 343
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,075评论 2 338

推荐阅读更多精彩内容