nginx

Nginx

轻量级、高性能的web服务器

模块化

一、研究前的准备工作

Nginx的特点
  1. 更快,单次请求很快,高峰期可以获得比其他Web服务器更快的相应速度。
  2. 高扩展性,模块化的设计。Nginx是由多个不同功能、不同层次、不同类型且耦合度极低的模块组成。
  3. 高可靠性,worker进程相对独立,master进程在1个worker进程出错时,可以快速拉起一个新的worker进程提供服务
  4. 低内存消耗,一般情况下,1w个非活跃的HTTP Keep-Alive连接在Nginx中仅消耗2.5M的内存,这是Nginx支持高并发的基础
  5. 单机支持10w+的并发连接
  6. 热部署,master进程与worker进程分离
  7. 最自由的BSD许可协议

除上述几点之外,Nginx还有很多的官方功能模块,第三方功能模块,有些模块支持Perl、Lua等脚本语言集成工作。

准备工作
  • linux 2.6+

    • 因为linux2.6+内核才支持epoll,而在linux上使用select和poll来解决事件的多路复用,是无法解决高并发压力问题的。
  • 必备软件

    • GCC编译器
    • PCRE库(用于解析正则表达式,如url重写)
    • zlib库(用于压缩文件,减少网络传输内容大小,提高相应时间)
      • zlib-devel是二次开发所需要的库
    • OpenSSL开发库(https用)

    具体需要安装哪些软件,视实际需要来定。

默认安装的部分模块
  • http_gzip_module # 执行gzip压缩文件
  • http_rewrite_module # 提供http请求在nginx内部重定向
  • http_proxy_module # 提供基本的http反向代理功能
  • http_fastcgi_module # 提供fastCGI模块
  • http_upstream_ip_hash_module # 用于计算客户端与哪个上游主机通信,实现负载均衡

在编译的时候,加上参数 --without-http_xxx 可以不安装对应模块

默认不安装的部分模块
  • http_ssl_module # 支持ssl协议

  • http_dav_module # 支持PUT/DELETE/COPY/MOVE/MKCOL等restful请求方式

在编译的时候,加上参数 --without-http_xxx 可以不安装对应模块

常用命令
  1. 默认方式启动,直接执行Nginx二进制程序,如:/usr/local/nginx/sbin/nginx
  2. 另行指定配置文件的启动方式,如:nginx -c /etc/nginx/nginx.conf
  3. 在不启动nginx的情况下,仅测试配置文件是否有错误 nginx -t
  4. 显示版本 nginx -v
  5. 显示版本及编译阶段的参数 nginx -V
  6. 快速停止服务 nginx -s stop
  7. 优雅地停止服务 nginx -s quit,区别就是会先关闭监听,然后等所有的正在处理的连接全部处理完在退出进程
  8. 重载配置 nginx -s reload

二、Nginx的配置

通常在生产环境下,Nginx使用一个master进程来管理多个worker进程,worker进程数一般和服务器的CPU核心数一致。

Apache的每个进程在同一时刻只能处理一个请求,如果需要处理高并发,需要把Apache的进程数设置得很高,通常能达到一台机器有几百个工作进程,大量的进程间切换将带来大量的系统资源消耗。而Nginx则不然,一个worker进程可以同时处理的请求数只取决于内存大小,在架构设计上,不同的worker进程之间处理并发请求时几乎没有同步锁的限制,worker进程通常不会进入睡眠状态,故当Nginx上的进程数与CPU核心数相等时(最好每隔worker进程都绑定特定的CPU核心),进程间切换的代价是最小的。

Nginx配置的通用语法
  1. 块配置项,由一个块配置项名和一对大括号组成。块配置项可以嵌套,内层块直接继承外层块,但内外层的配置项名相同时,具体以哪一层为准,取决于具体的模块。
  2. 配置项的语法格式,name value1 value2 ...; 空格分隔,分号结尾,不得出现不支持的模块配置项名。
  3. #号注释
  4. 变量,某些模块提供一些变量,并非通用。
  5. 每个配置项都有对应的配置块,放错了位置可能会报语法错误。
基本配置
  1. user nginx; 注意不要把启动用户设置为root,因为worker进程出问题后,master进程需要有权限停止、启动worker进程
  2. error_log /path/file level;,默认为error_log logs/error.log error;如果设置为debug等级,会输出所有的日志,导致log文件巨大。
  3. include /path/file; 嵌入其他配置文件
    • include mime.types;
    • include conf.d/*.conf;
  4. pid logs/nginx.pid; 保存master进程id的文件,要确保Nginx有权在相应的目标路径中创建pid文件的权限,否则Nginx将无法运行
  5. worker_processes number; worker进程数量,一般情况下,与CPU核心数保持一致
用HTTP核心模块配置一个静态web服务器
  1. listen 监听端口

    listen 80;
    listen 127.0.0.1:8000;
    listen 127.0.0.1; # 不加端口时,默认监听80端口
    listen *:8000;
    listen www.example.com:8000;
    

    若服务器使用IPv6地址,使用下面方式

    listen [::]:8000;
    listen [fe80::1];
    listen [::a8c9:1234]:80;
    

    在地址和端口后,还可以加其他参数,如:

    listen 443 default_server ssl;
    listen 127.0.0.1 default_server accept_filter=dataready backlog=1024
    

    default和default_server:将所在的块作为整个web服务的默认server块,若没有设置这个参数,那么将会以nginx.conf中找到的第一个server块作为默认server。当一个请求无法匹配配置文件中的所有主机域名时,就会选用默认的虚拟主机。

    backlog:TCP中backlog队列的大小,默认为-1,表示不予设置。

    ssl:在当前监听的端口上建立的连接必须基于SSL协议。

  2. server_name 主机名称

    server_name yourdomain.com 123.123.123.123;
    

    server_name与Host的匹配优先级如下:

    1)首先选择所有字符串完全匹配的server_name,如www.testweb.con。

    2)其次选择通配符在前面的server_name,如*.testweb.com

    3)再次选择通配符在后面的server_name,如www.testweb.*

    4)最后选择使用正则表达式才匹配的server_name,如~^\testweb.com$

    如果以上都匹配不到,就

    5)选择在listen配置项后加入[default|default_server]的server块

    6)找到匹配端口的第一个server块

  3. location

    location [=|~|~*|^|@] /uri/ {...} location会根据请求的URI来匹配上面的/uri表达式,如果可匹配,就选择location {}块中的配置来处理该请求

    1)=表示把URI作为字符串,与参数中的uri做完全匹配,如:

    location = / {
      # 只有当用户请求是/时,才会使用该location下的配置
      ...
    }
    

    2)~表示匹配URI时是字母大小写敏感的

    3)~*表示匹配URI时忽略字母大小写问题

    4)^~表示匹配URI时只需前半部分与URI参数匹配即可,如:

    location ^~ /images/ {
      # 以/images/开始的请求会匹配上,可做防盗链
      ...
    }
    

    location是有顺序的,如果一个请求可以匹配多个location,那么会被第一个location处理

    location / {} 可以匹配所有的HTTP请求,如果不能匹配此location之前的所有项,就会由这个来处理,相当于switch的default,可以用来实现,如果不匹配xxx则xxx的需求。

  4. root 设置资源路径,可置于http,server,location,if块下,定义资源文件相对于HTTP请求的根目录

    location /download/ {
      root /opt/web/html;
    }
    

    若一个请求的URI是/download/index/test.html,那么web服务器会返回/opt/web/html/download/index/test.html文件的内容。

  5. alias 也是设置文件资源路径,只能放在location块下,与root的区别在于,如:有个请求的URI是/conf/nginx.conf,而实际想访问的文件在/usr/local/nginx/conf/nginx.conf,用alias和root分别设置的方式如下:

    # alias方式
    location /conf {
      alias /usr/local/nginx/conf/;
    }
    
    # root方式
    location /conf {
      alias /usr/local/nginx/;
    }
    

    1)使用alias是,在URI向实际文件路径的映射过程中,已经把location后配置的/conf这部分字符丢弃掉,故/conf/nginx.conf请求将根据alias path映射为path/nginx.conf

    2)而root则根据完整的URI请求来映射,故/conf/nginx.conf会根据root path映射为path/conf/nginx.conf

    3)这也是root可以放到http,server,location,if块下,而alias只能放置于location块下的原因

    4)alias后还可以添加正则表达式,如:

    location ~ ^/test/(\w+)\.(\w+)$ {
      alias /usr/local/nginx/$2/$1.$2;
    }
    

    这样,请求在访问/test/nginx.conf时,Nginx会返回/usr/local/nginx/conf/nginx.conf文件的内容。

  6. index 访问首页 index index.php html/index.php index.html

    当访问的URI是/时,Nginx将会根据index配置的顺序,从左往右去查找这些文件,找到就立马返回。

    如:当root目录下同时包含index.phpindex.html时,会使用index.php文件

  7. sendfile on; 开启后,nginx可以把硬盘中的文件不载入内存就直接发送出去

  8. error_page 错误码重定向

    # 将返回码为xxx的请求重定向到新的URI
    error_page 500 502 503 504 /50x.html;
    
    # 上面的重定向,不会修改返回的HTTP错误码,想改错误码可以通过 = 来指定
    error_page 404 =200 /empty.gif
    
    # 也可以不指定具体的错误码,而是让重定向后实际处理的真实结果来决定
    error_page 404 = /empty.gif
    
    # 若不想修改URI,只是想让这样的请求重定向到另一个location中进行处理
    location / {
      error_page 404 @fallback
    }
    
    location @fallback {
      proxy_pass http://backend;
    }
    这样,404的请求就会被反向代理到http://backend的上游服务器中处理
    
  9. try_files path1 [path2] uri;

    try_files后要跟若干路径,最后必须要有URI参数,意义如下:

    1)尝试按照顺序访问每一个path,若可有效读取,就直接向用户返回这个path对应的文件结束请求,否则继续向下访问。

    2)若所有的path都找不到有效的文件,就重定向到最后的参数URI上,所以最后的URI参数是必须存在的,且应该是有效的。

    laravel的推荐配置为try_files $uri $uri/ /index.php?$query_string;即:

    1. 先按路由的uri部分找对应的 r o o t / root/ root/uri文件是否存在;
    2. 若不存在,则去寻找是否存在 r o o t / root/ root/uri/这样的目录;
    3. 若仁不存在,则将请求重新转到 r o o t / i n d e . p h p ? root/inde.php? root/inde.php?query_string作为请求发出去
  10. autoindex on; 在没有设置index的时候,可以作为一个静态资源共享盘使用,如果开启的话,并且没有对应的index文件,会报403 Forbidden

    autoindex on; # 索引
    autoindex_exact_size off; # 显示文件大小
    # 默认为on,显示出文件的确切大小,单位是bytes。
    # 改为off后,显示出文件的大概大小,单位是kB或者MB或者GB
    
    autoindex_localtime on; # 显示文件时间
    # 默认为off,显示的文件时间为GMT时间。
    # 改为on后,显示的文件时间为文件的服务器时间
    
    auth_basic "输入用户名密码";
    auth_basic_user_file /etc/nginx/passwd.db.conf;
    # auth_basic_user_file需要Apache的一个软件htpasswd生成,需要安装Apache或者下载独立的htpasswd脚本执行
    
  11. gzip 可以对指定的文件进行gzip压缩,浏览器接收到response header信息(content-type:gzip)后会进行解压缩,提高相应速度

    gzip            on; # 开启gzip压缩,可压缩传输的文件大小,提示响应速度
    gzip_min_length 1024; # 进行压缩的最小文件尺寸,单位byte字节
    gzip_types text/plain text/css application/javascript application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon;
    
  12. keepalive_timeout 超时时间,默认75 keepalive_timeout 75;

  13. limit_except method …{…} 按HTTP方法名限制用户请求,方法名可取值包括:GET,HEAD,POST,PUT,DELETE,MKCOL,COPY,MOVE,OPTIONS,PROPFIND,PROPPATCH,LOCK,UNLOCK或者PATCH。如:

   # 禁止GET方法(GET方法包含HEAD方法)和HEAD方法,其他方法是允许的
   limit_except GET {
     allow 192.168.1.0/32;
     deny all;
   }
  1. client_max_baody_size 1m; HTTP请求包体的最大值,过滤HTTP请求头中的Content-Length字段超过定义值的请求,在收到包头之后,直接返回413响应(文件过大),而不会去接收包体。

  2. limit_rate_spped 0; 限制对客户端每秒传输的字节数,0表示不限速,可对不同客户端采用不同限速策略。

  3. resolver address …; 设置DNS名字解析服务器的地址,如:resolver 127.0.0.1 192.0.2.1;

  4. set $limit_rate 1k; 设置响应速度为1kb/s

  5. 在配置文件的http{}段增加一行配置 server_names_hash_bucket_size 64;
    如果64还不够,那么就按32的倍数往上加。下面是在中文wiki上摘抄的一段说明:

保存服务器名字的hash表是由指令 server_names_hash_max_size 和 server_names_hash_bucket_size所控制的。参数hash bucket size总是等于hash表的大小,并且是一路处理器缓存大小的倍数。在减少了在内存中的存取次数后,使在处理器中加速查找hash表键值成为可能。如果 hash bucket size等于一路处理器缓存的大小,那么在查找键的时候,最坏的情况下在内存中查找的次数为2。第一次是确定存储单元的地址,第二次是在存储单元中查找键值。因此,如果Nginx给出需要增大 hash max size 或 hash bucket size的提示,那么首要的是增大前一个参数的大小.

用HTTP proxy module配置一个反向代理服务器

Nginx的反向代理,在client发来HTTP请求时,会先把用户的请求(包含HTTP包体)完整的接收到Nginx所在的服务器的硬盘或内存中,然后再向上游服务器(真实响应工作的机器)发起连接,把缓存的client请求发到上游服务器。这种特点的缺点是延长了一个请求的处理时间,并增加了用于缓存的请求内容的内存和磁盘空间,而优点则是降低了上游服务器的负载,尽量把压力放在Nginx服务器上。

之所以能减低上游服务器的负载,主要是因为通常client和服务器走的是公网,网速平均下来较慢,而代理服务器和上游服务器一般走内网,网速较快,所以Nginx在接收完了client的请求内容后,转发给上游服务器的速度很快,这样,一个client请求占用上游服务器的连接时间会非常短,这种代理方案降低了上游服务器的并发压力。

  1. upstream块,配置在http块下,与server同级

    upstream backend {
      server backend1.example.com;
      server backend2.example.com;
      server backend3.example.com;
    }
    
    server {
       location / {
         proxy_pass http://backend;
     }
    }
    
  2. server块,配置在upstream块下,server配置项指定一台上游服务器的名字,可以是域名、ip地址端口、UNIX句柄等,还可以在后面跟以下参数:

    1)weight=number 设置这台上游服务器的权重,默认为1
    2)max_fails=number 与fail_timeout配合使用,指在fail_timeout时间段内,如果向当前上游服务器的转发次数超过number,则认为当前的这台上游服务器不可用,max_fails默认为1,0表示不检查失败次数
    3)fail_timeout 默认10秒
    4)down 表示所在的上游服务器永久下线,只在使用ip_hash配置时才有效
    5)backup 在使用ip_hash配置时无效。表示所在的上游服务器只是备份服务器,只有所有的非备份上游服务器都失效后,才会向他所在的上游服务器转发请求
    
  3. ip_hash 配置在upstream块下,在有些场景下,希望某一个用户的请求固定落在某一台上游服务器上,可以使用此功能,它会根据用户的ip计算出一个key,将key按照upstream集群里的上游服务器数量进行取模,然后以取模的结果把请求转发到相应的服务器上,ip_hash与weight配置不可同时使用。如果upstream集群中有一台服务器暂时不可用,不能直接删除该配置,而是要down参数标识,确保转发策略的一贯性,如:

    upstream backend {
       ip_hash;
       server backend1.example.com;
       server backend2.example.com;
       server backend3.example.com down;
       server backend4.example.com;
    }
    
    # ip_hash与weight同时使用时,ip_hash的优先级更高
    
  4. proxy_pass URL; 配置在location、if块下,将当前请求反向代理到URL参数指定的服务器上,URL可以是主机名或IP地址加端口的形式,也可以是UNIX句柄,也可以是负载均衡的upstream块名

    默认情况下,反向代理不会转发请求中的Host头部,需加上 proxy_set_header Host $host;才可以。有些情况下,$host的端口不是80,还需要在后面追加端口 $host:8080

    以下为一个简单的例子,让10.0.150.171:8083/代理到https://www.baidu.com

    server {
        listen 8083;
        server_name 10.0.150.171;
    
        location / {
            proxy_pass https://www.baidu.com;
        }
    }
    

    但上面这种代理方式,会丢失原请求的部分头部信息,可在proxy_pass后加上以下内容

    # 可以通过手动指定这些参数,模拟任意客户端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;
    
  5. mmm

注意事项

  1. error_log /path/file level;,默认为error_log logs/error.log error;如果设置为debug等级,会输出所有的日志,导致log文件巨大。
  2. nginx配置文件里的大小单位默认为字节,还有k,K,m,M,g ,G
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值