nginx的配置是相当多,一次性学完不太现实,边学习边记录,遇到就记录。
nginx中的配置指令是有上下文的,它们只能在特定上下文中使用。
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:可以打开的文件数量上限。
events context包含的是和连接相关的配置,例如:
events {
accept_mutex on
use epoll; # 一般不用设置,nginx会自己选择
worker_connections 1024; # 每个worker可以建立的连接数
...
}
nginx支持多种连接处理方式(Connection processing methods) ,例如select
、poll
、kqueue
、epoll
、/dev/poll
、eventport
,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操作数量上限。
摘录自How nginx processes a request。
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
可以是通配符形式,通配符只能出现在开头或者结尾
:
*.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,表示接受没有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。
下面这种形式,比直接使用.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 设置的是哈希桶的数量。
摘录自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中上下文位于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;
}
}
}
反向代理支持http
、https
、FastCGI
、uwsgi
、SCGI
、memcached
和gRPC
,http和https直接在proxy_pass中使用即可,其它的需要使用对应的指令:
fastcgi_pass,
uwsgi_pass,
scgi_pass,
memcached_pass,
grpc_pass。
支持的负载均衡算法有:least_conn,ip_hash, weight
# 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