Skip to content

Latest commit

 

History

History
424 lines (332 loc) · 18.6 KB

nginx简介.md

File metadata and controls

424 lines (332 loc) · 18.6 KB

Nginx

location 匹配规则

语法规则:

location [=|~|~*|^~] /uri/ { … }
符号 含义 优先级
= 精确匹配 1
^~ 表示 uri 以某个常规字符串开头,理解为匹配 url 路径即可。nginx 不对 url 做编码,因此请求为/static/20%/aa,可以被规则^~ /static/ /aa匹配到(注意是空格) 2
~ 区分大小 写的正则匹配 3
~* 不区分大小写的正则匹配 4
/ 通用匹配,任何请求都会匹配到 5

Example:

location = / {
   #规则A
}
location = /login {
   #规则B
}
location ^~ /static/ {
   #规则C
}
location ~ \.(gif|jpg|png|js|css)$ {
   #规则D
}
location ~* \.png$ {
   #规则E
}
location / {
   #规则F
}

那么产生的效果如下:

所以实际使用中, 一般至少有三个匹配规则定义,如下:

# 直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,官网如是说。
# 这里是直接转发给后端应用服务器了,也可以是一个静态首页
# 第一个必选规则
location = / {
    proxy_pass http://tomcat:8080/index
}

# 第二个必选规则是处理静态文件请求,这是 nginx 作为 http 服务器的强项
# 有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用
location ^~ /static/ {
    root /webroot/static/;
}
location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ {
    root /webroot/res/;
}

# 第三个规则就是通用规则,用来转发动态请求到后端应用服务器
# 非静态文件请求就默认是动态请求,自己根据实际把握
# 毕竟目前的一些框架的流行,带.php、.jsp后缀的情况很少了
location / {
    proxy_pass http://tomcat:8080/
}

ReWrite语法

  • last – 基本上都用这个 Flag
  • break – 中止 Rewirte,不在继续匹配
  • redirect – 返回临时重定向的 HTTP 状态 302
  • permanent – 返回永久重定向的 HTTP 状态 301

可以用来判断的表达式

  • -f 和 !-f 用来判断是否存在文件
  • -d 和 !-d 用来判断是否存在目录
  • -e 和 !-e 用来判断是否存在文件或目录
  • -x 和 !-x 用来判断文件是否可执行

if 是邪恶的

  • 避免使用 if 指令

    • 当在 location 区块中使用 if 指令的时候会有一些问题, 在某些情况下它并不按照你的预期运行而是做一些完全不同的事情。 而在另一些情况下他甚至会出现段错误。
    • 在 location 区块里 if 指令下唯一 100% 安全的指令应该只有: return …; rewrite … last;
  • 如何替换掉 if

    • 使用 try_files 如果他适合你的需求
    • 在其他的情况下使用 return … 或者 rewrite … last
    • 还有一些情况可能要把 if 移动到 server 区块下( 只有当其他的 rewrite 模块指令也允许放在的地方才是安全的 )。
  • 原因

    • if 指令是 rewrite 模块中的一部分, 是实时生效的指令。 在if里写入一些非rewrite指令, 会导致各种错误。

Nginx 静态文件服务

最简单的本地静态文件服务配置:

server {
    listen       80;
    server_name www.test.com;
    charset utf-8;
    root   /data/www.test.com;
    index  index.html index.htm;
}

这个配置可以用, 但是远远没有发挥 Nginx 的半成功力。

下面是一个改进的配置:

http {
    # 这个将为打开文件指定缓存,默认是没有启用的,max 指定缓存数量,
    # 建议和打开文件数一致,inactive 是指经过多长时间文件没被请求后删除缓存。
    open_file_cache max=204800 inactive=20s;

    # open_file_cache 指令中的inactive 参数时间内文件的最少使用次数,
    # 如果超过这个数字,文件描述符一直是在缓存中打开的,如上例,如果有一个
    # 文件在inactive 时间内一次没被使用,它将被移除。
    open_file_cache_min_uses 1;

    # 这个是指多长时间检查一次缓存的有效信息
    open_file_cache_valid 30s;

    # 默认情况下,Nginx的gzip压缩是关闭的, gzip压缩功能就是可以让你节省不
    # 少带宽,但是会增加服务器CPU的开销哦,Nginx默认只对text/html进行压缩 ,
    # 如果要对html之外的内容进行压缩传输,我们需要手动来设置。
    gzip on;
    gzip_min_length 1k;
    gzip_buffers 4 16k;
    gzip_http_version 1.0;
    gzip_comp_level 2;
    gzip_types text/plain application/x-javascript text/css application/xml;

    server {
        listen       80;
        server_name www.test.com;
        charset utf-8;
        root   /data/www.test.com;
        index  index.html index.htm;
    }
}

如何安装和配置基础缓存 Basic Caching

  • proxy_cache_path 用来设置缓存的路径和配置,
  • proxy_cache 用来启用缓存
proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m
use_temp_path=off;

server {
    ...
    location / {
        proxy_cache my_cache;
        proxy_pass http://my_upstream;
    }

}

参数及对应配置说明:

  1. 本地磁盘目录 /path/to/cache/
  2. levels 在 /path/to/cache/ 设置了一个两级层次结构的目录。
    • 将大量的文件放置在单个目录中会导致文件访问缓慢,所以针对大多数部署,我们推荐使用两级目录层次结构。如果 levels 参数没有配置,则 Nginx 会将所有的文件放到同一个目录中。
  3. keys_zone 设置一个共享内存区,该内存区用于存储缓存键和元数据,有些类似计时器的用途。将键的拷贝放入内存可以使 Nginx 在不检索磁盘的情况下快速决定一个请求是HIT还是MISS,这样大大提高了检索速度。一个 1MB 的内存空间可以存储大约 8000个key,那么上面配置的 10MB 内存空间可以存储差不多 80000 个 key。
  4. max_size 设置了缓存的上限(在上面的例子中是 10G)。
    • 这是一个可选项;如果不指定具体值,那就是允许缓存不断增长,占用所有可用的磁盘空间。
    • 当缓存达到这个上线,处理器便调用 cache manager 来移除最近最少被使用的文件,这样把缓存的空间降低至这个限制之下。
  5. inactive 指定了项目在不被访问的情况下能够在内存中保持的时间。在上面的例子中,如果一个文件在 60 分钟之内没有被请求,则缓存管理将会自动将其在内存中删除,不管该文件是否过期。该参数默认值为 10 分钟(10m)。注意,非活动内容有别于过期内容。 Nginx 不会自动删除由缓存控制头部指定的过期内容(本例中 Cache-Control:max-age=120)。过期内容只有在 inactive 指定时间内没有被访问的情况下才会被删除。如果过期内容被访问了,那么 Nginx 就会将其从原服务器上刷新,并更新对应的inactive计时器。
  6. Nginx 最初会将注定写入缓存的文件先放入一个临时存储区域,use_temp_path=off命令指示 Nginx 将在缓存这些文件时将它们写入同一个目录下。
    • 强烈建议你将参数设置为off来避免在文件系统中不必要的数据拷贝。use_temp_path在 Nginx 1.7版本和 Nginx Plus R6中有所介绍。
  7. proxy_cache 命令启动缓存那些URL与location部分匹配的内容(本例中,为/)。
    • 你同样可以将proxy_cache命令添加到server部分,这将会将缓存应用到所有的那些location中未指定自己的proxy_cache命令的服务中。

缓存微调 TODO

跨多硬盘分割缓存 TODO

反向代理

反向代理 配置

worker_processes 1;

pid logs/nginx.pid;
error_log logs/error.log warn;

events {
    worker_connections 3000;
}

http {
    include mime.types;
    server_tokens off;

    ## 下面配置反向代理的参数
    server {
        listen    80;

        ## 1. 用户访问 http://ip:port,则反向代理到 https://github.com
        location / {
            proxy_pass  https://github.com;
            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;
        }

        ## 2.用户访问 http://ip:port/README.md,则反向代理到
        ##   https://github.com/.../README.md
        location /README.md {
            proxy_set_header  X-Real-IP  $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_pass https://github.com/moonbingbing/openresty-best-practices/blob/master/README.md;
        }
    }
}
  • proxy_pass
  • proxy_set_header
    • 默认情况下,反向代理不会转发原始请求中的 Host 头部,如果需要转发,就需要加上这句:proxy_set_header Host $host;
    • 除了上面提到的常用配置项,还有 proxy_redirect、proxy_set_body、proxy_limit_rate 等参数

负载均衡

upstream 负载均衡概要

upstream test.net{
    ip_hash;
    server 192.168.10.13:80;
    server 192.168.10.14:80  down;
    server 192.168.10.15:8009  max_fails=3  fail_timeout=20s;
    server 192.168.10.16:8080;
}
server {
    location / {
        proxy_pass  http://test.net;
    }
}
  • upstream 是 Nginx 的 HTTP Upstream 模块,
    • 这个模块通过一个简单的调度算法来实现客户端 IP 到后端服务器的负载均衡。
    • 在上面的设定中,通过 upstream 指令指定了一个负载均衡器的名称 test.net。 这个名称可以任意指定,在后面需要用到的地方直接调用即可。

upstream 支持的负载均衡算法

upstream 支持的负载均衡算法

Nginx 的负载均衡模块目前支持 6 种调度算法, 后两项属于第三方调度算法。

  • 轮询(默认):每个请求按时间顺序逐一分配到不同的后端服务器,如果后端某台服务器宕机,故障系统被自动剔除,使用户访问不受影响。
    • Weight 指定轮询权值,Weight 值越大,分配到的访问机率越高,主要用于后端每个服务器性能不均的情况下。
  • ip_hash:每个请求按访问IP的hash结果分配,
    • 这样来自同一个IP的访客固定访问一个后端服务器,有效解决了动态网页存在的session共享问题。
  • fair:这是比上面两个更加智能的负载均衡算法。此种算法可以依据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间来分配请求,响应时间短的优先分配。
    • Nginx本身是不支持fair的,如果需要使用这种调度算法,必须下载Nginx的upstream_fair模块。
  • url_hash:此方法按访问 url 的 hash 结果来分配请求,使每个 url 定向到同一个后端服务器,可以进一步提高后端缓存服务器的效率。
    • Nginx 本身是不支持 url_hash 的,如果需要使用这种调度算法,必须安装 Nginx 的 hash 软件包。
  • least_conn:最少连接负载均衡算法,简单来说就是每次选择的后端都是当前最少连接的一个 server(这个最少连接不是共享的,是每个 worker 都有自己的一个数组进行记录后端 server 的连接数)。
  • hash:这个 hash 模块又支持两种模式 hash, 一种是普通的 hash, 另一种是一致性 hash(consistent)。

upstream 支持的状态参数

  • down:表示当前的server暂时不参与负载均衡。
  • backup:预留的备份机器。
    • 当其他所有的非 backup 机器出现故障或者忙的时候,才会请求 backup 机器,因此这台机器的压力最轻。
    • 当负载调度算法为 ip_hash 时,后端服务器在负载均衡调度中的状态不能是 backup。
  • max_fails:允许请求失败的次数,默认为 1。
    • 当超过最大次数时,返回 proxy_next_upstream 模块定义的错误。
  • fail_timeout:在经历了 max_fails 次失败后,暂停服务的时间。
    • max_fails 可以和 fail_timeout 一起使用。

配置 nginx 进行健康状态检查

upstream webservers {
    server 192.168.18.201 weight=1 max_fails=2 fail_timeout=2;
    server 192.168.18.202 weight=1 max_fails=2 fail_timeout=2;
}

Nginx 陷阱和常见错误

  • 糟糕的配置: 把 root 放在 location 区块内
  • 重复的 index 指令
  • 用 if 检查文件是否存在
    • 使用 if 指令来判断文件是否存在是很可怕的,如果你在使用新版本的 Nginx , 你应该看看 try_files 。
  • 脚本文件名里面的 FastCGI 路径
    • 推荐: fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    • 糟糕: fastcgi_param SCRIPT_FILENAME /var/www/yoursite.com/$fastcgi_script_name;
  • 费力的 rewrites
  • 忽略 http:// 的rewrite
    • 糟糕的配置:rewrite ^ example.com permanent;
    • 推荐的配置:rewrite ^ http://example.com permanent;
  • 代理所有东西
    • 把 所有东西 都丢给了 PHP 。 Apache 可能要这样做,但在 Nginx 里你不必这样。
    • 换个思路,try_files 有一个神奇之处,它是按照特定顺序去尝试文件的。 这意味着 Nginx 可以先尝试下静态文件,如果没有才继续往后走。
    • 这样PHP就不用参与到这个处理中,会快很多。 特别是如果你提供一个1MB图片数千次请求的服务,通过PHP处理还是直接返回静态文件呢?
server {
    server_name _;
    root /var/www/site;
    location / {
        try_files $uri $uri/ @proxy;
    }
    location @proxy {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/tmp/phpcgi.socket;
    }
}
  • 代理所有东西 Cont.
    • 如果请求的 URI 存在, Nginx 会处理掉; 如果不存在,检查下目录是不是存在,是的话也可以被 Nginx 处理; 只有在 Nginx 不能直接处理请求的URI的时候,才会进入 proxy 这个 location 来处理。
  • 配置的修改没有起效
    • 浏览器缓存。你的配置可能是对的,但怎么尝试结果总是不对,百思不得其解。 罪魁祸首是你的浏览器缓存。当你下载东西的时候,浏览器做了缓存。
    • 使用 curl 避免
  • VirtualBox
    • 如果你在 VirtualBox 的虚拟机中运行 Nginx ,而它不工作,可能是因为 sendfile() 引起的麻烦。
    • 只用简单的注释掉 sendfile 指令,或者设置为 off。 该指令大都会写在 Nginx .conf 文件中: sendfile off;
  • 丢失(消失)的 HTTP 头
    • 如果你没有明确的设置 underscores_in_headers on; , Nginx 将会自动丢弃带有下划线的 HTTP 头(根据 HTTP 标准,这样做是完全正当的).
    • 这样做是为了防止头信息映射到 CGI 变量时产生歧义,因为破折号和下划线都会被映射为下划线。
  • 没有使用标准的 Document Root Location
    • 在所有的文件系统中,一些目录永远也不应该被用做数据的托管。这些目录包括 / 和 /root 。
    • 你永远不应该使用这些目录作为你的 document root。
    • 服务器很容易变成肉鸡
  • 使用默认的 Document Root
    • 不要假设默认的 document root 里面的数据在 升级系统 的时候会原封不动。
  • 使用主机名来解析地址
    • server http://someserver;
    • 使用主机名对应 IP 地址,而不是主机名。 这可以防止 Nginx 去查找 IP 地址,也去掉了去内部、外部解析程序的依赖。
  • 在 HTTPS 中使用 SSLv3
    • 由于 SSLv3 的 POODLE 漏洞, 建议不要在开启 SSL 的网站使用 SSLv3。 你可以简单粗暴的直接禁止 SSLv3, 用 TLS 来替代:
    • ssl_protocols TLSv1 TLSv1.1 TLSv1.2;