Nginx学习笔记(二):Nginx配置文件细节

作者: 李佶澳   转载请保留:原文地址   发布时间:2018-11-22 18:17:36 +0800

说明

nginx的配置是相当多,一次性学完不太现实,边学习边记录,遇到就记录。

配置上下文

nginx中的配置指令是有上下文的,它们只能在特定上下文中使用。

main context

main context是最顶层的上下文,它就是nginx.conf文件本身,在nginx.conf中直接出现的命令就是位于main context中。

# 直接出现在nginx.conf中的指令
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
#### 省略后续内容 ### 

worker_rlimit_nofile:可以打开的文件数量上限。

event context

events context包含的是和连接相关的配置,例如:

events {
    accept_mutex on
    use  epoll;                # 一般不用设置,nginx会自己选择
    worker_connections 1024;   # 每个worker可以建立的连接数
    ...
}

连接处理相关配置

nginx支持多种连接处理方式(Connection processing methods) ,例如selectpollkqueueepoll/dev/polleventport,nginx默认会选择最合适的处理方式,可以用use指令更改。

连接相关的配置在event context上下文中配置。

accept_mutex:如果开启,工作进程轮流接受请求,可以节省系统资源。

accept_mutex_delay:accept_mutex开启的前提下,重新开始接受请求的等待时间。

debug_connection:开启连接调试日志,nginx需要在编译时指定了--with-debug

multi_accept:每次只接收一个新建连接,或者可以同时接受多个新建连接。

use:设置连接的处理方法。

worker_connections:一个nginx工作进程可以同时处理的最大连接数。

worker_aio_requests:开启异步io的情况下,单个工作进程的异步io操作数量上限。

http context

server context

摘录自How nginx processes a request

server context配置

server context可以有多个,每个server设置一个监听端口,多个server可以复用同一个监听端口,通过server_name进行区分:

server {
    listen      80;
    server_name example.org www.example.org;
    ...
}

server {
    listen      80;
    server_name example.net www.example.net;
    ...
}

server {
    listen      80;
    server_name example.com www.example.com;
    ...
}

server_name就是http请求头中的Host字段的值,可以设置一个default_server,处理没有对应server的请求:

server {
    listen      80 default_server;
    server_name example.net www.example.net;
    ...
}

server的IP地址可以不同,default_server相对于IP:Port的:

server {
    listen      192.168.1.1:80 default_server;
    server_name example.net www.example.net;
    ...
}

server {
    listen      192.168.1.2:80 default_server;
    server_name example.com www.example.com;
    ...
}

如果要禁止请求头中不带Host字段的请求,可以设置这样一个server:

server {
    listen      80;
    server_name "";
    return      444;
}
server_name的样式

server_name可以是通配符形式,通配符只能出现在开头或者结尾

*.example.org
abc.*
abc.*.org        # 错误
.example.org     # 等同于 example.org + *. example.org

server_name正则形式表达能力更强,正则形式必须用~开头:

server_name  ~^www\d+\.example\.net$;                     # `.`需要用`\`进行转义
server_name  "~^(?<name>\w\d{1,3}+)\.example\.net$";      # 如果含有{ },整个表达式需要用加引号
                                                          # 否则会出错: directive "server_name" is not terminated by ";" in ...

正则表达式采用PCRE,支持捕获:

server {
    server_name   ~^(www\.)?(?<domain>.+)$;

    location / {
        root   /sites/$domain;
    }
}

注意location中的$domain即使从正则中捕获的值,PCRE的命名捕获语法如下:

?<name> 	Perl 5.10 compatible syntax, supported since PCRE-7.0
?'name' 	Perl 5.10 compatible syntax, supported since PCRE-7.0
?P<name> 	Python compatible syntax, supported since PCRE-4.0

如果遇到下面的错误:

pcre_compile() failed: unrecognized character after (?< in ...

是因为PCRE版本比较旧,不支持命名捕获,需要使用数字的形式,注意下面的$2

server {
    server_name   ~^(www\.)?(.+)$;

    location / {
        root   /sites/$2;
    }
}
一些特殊的server_name

的server_name,表示接受没有Host字段的请求,注意下面的""

server {
    listen       80;
    server_name  example.org  www.example.org  "";
    ...
}

如果没有server_name,默认是使用的server_name:

server {
    listen       80;
    ...
}

server_name可以是IP地址,请求头中的Host字段的值依旧需要且是IP地址。

如果要匹配所有的server_name,设置为default_server,server_name设置为一个无效值:

server {
    listen       80  default_server;
    server_name  _;     
    return       444;
}

非英文的域名需要用ASCII码表示,例如пример.испытание

server {
    listen       80;
    server_name  xn--e1afmkfd.xn--80akhbyknj4f;  # пример.испытание
    ...
}
server_name优化

直接的server_name、用通配符开头的server_name和用通配符结束的server_name,分别被存放在三个哈希表中。

查找的时候,首先从直接的server_name中查找,然后从以通配符开头的server_name中查找,再从以通配符结尾的server_name中查找,最后是按照正则形式的server_name的出现顺序进行正则匹配。

从直接的server_name中查找速度是最快的,应当尽可能多的使用直接的server_name。

下面这种形式,比直接使用.example.org效率高,(以.开头server_name存放在以通配符开头的server_name哈希表中):

server {
    listen       80;
    server_name  example.org  www.example.org  *.example.org;
    ...
}

哈希桶的数量可以调整,哈希桶数量的翻倍增加(2的指数)。

server_names_hash_max_size设置的是server_name的最大长度,server_names_hash_bucket_size 设置的是哈希桶的数量。

location context

摘录自How nginx processes a request

location是server context中的context,匹配url:

server {
    listen      80;
    server_name example.org www.example.org;
    root        /data/www;

    location / {
        index   index.html index.php;
    }

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

    location ~ \.php$ {
        fastcgi_pass  localhost:9000;
        fastcgi_param SCRIPT_FILENAME
                      $document_root$fastcgi_script_name;
        include       fastcgi_params;
    }
}

url分为前缀形式正则形式两种,查找请求对应的location时,先进行前缀匹配,选择最长匹配的location。

如果通过前缀匹配没有找到对应的location,在通过正则匹配查找,按照正则形式的url在配置文件中出现的顺序查找,一旦匹配就停止查找。

查找请求对应的location时,只考虑uri,不考虑参数。

upstream context

upstream中上下文位于http context中,是用来设置多个后端服务地址,以及负载均衡策略的,Using nginx as HTTP load balancer

http {
    upstream myapp1 {
        server srv1.example.com;
        server srv2.example.com;
        server srv3.example.com;
    }

    server {
        listen 80;

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

反向代理支持httphttpsFastCGIuwsgiSCGImemcachedgRPC,http和https直接在proxy_pass中使用即可,其它的需要使用对应的指令: fastcgi_passuwsgi_passscgi_passmemcached_passgrpc_pass

支持的负载均衡算法有:least_connip_hashweight


# least_conn方式
upstream myapp1 {
    least_conn;
    server srv1.example.com;
    server srv2.example.com;
    server srv3.example.com;
}

# ip_hash方式
upstream myapp1 {
    ip_hash;
    server srv1.example.com;
    server srv2.example.com;
    server srv3.example.com;
}

# weight的方式:
upstream myapp1 {
    server srv1.example.com weight=3;
    server srv2.example.com;
    server srv3.example.com;
}

还有可以设置健康检查、keep-alive等,见Health checks

参考

  1. nginx documentation
  2. events context
  3. Tuning NGINX for Performance

欢迎加微信,最好备注姓名和方向

QQ交流群

区块链实践互助QQ群:576555864

Kubernetes实践互助QQ群:947371129

Prometheus实践互助QQ群:952461804

API网关Kong实践互助QQ群:952503851

Ansible实践互助QQ群:955105412

Copyright @2011-2018 All rights reserved. 转载请添加原文连接,合作请加微信lijiaocn或者发送邮件: lijiaocn@foxmail.com,备注网站合作 友情链接: lijiaocn github.com