说起配置Nginx确实是一件让人头疼的事,开始时对Nginx配置不熟悉,为了满足需求在网上查找了很多相关配置的博客,也是天花乱坠不知道谁对谁错。就不停反复尝试最终在不懈的努力下中终于成功了。那时就觉得是时候好好整理一下Nginx的相关配置了。
以fastcgi
开头的配置
fastchi
?fastCGi
是由CGI(common gateway interface,通用网关接口)发展而来,是http服务器(nginx,apache)和动态语言(PHP) 之间的通信接口。记住,fastCGI只是一个接口。关于fastCGI我们这里就不做过多的解释说明。可以参考FastCGI协议理论讲解,Nginx,fastCGI,http方式关系梳理,通用网关接口-FastCGI介绍等。
以mime开头的配置
媒体类型文件,Nginx 会根据服务端文件后缀名在映射关系中获取所属文件类型,将文件类型添加到 HTTP 消息头字段“Content-Type”中.
以nginx开头的配置
nginx默认的主配置文件(核心配置文件,也是今天的主角)
以scgi开头的配置
SCGI (Simple common gateway interface)是 CGI 的替代版本,它与 FastCGI 类似,同样是将请求处理程序独立于 Web 服务器之外,但更容易实现,性能比 FastCGI 要弱一些。
以uwsgi开头的配置
WSGI (Web server gateway interface)是为 Python 语言中定义的 Web 服务器与 Python 应用程序或框架间的通用通信接口,可以使 Python 应用程序或框架与支持这一协议的不同Web服务器进行通信。常见的 Python Web 框架都实现了该协议的封装。
为了便于了解 Nginx 配置文件的内部结构,这里约定几个名词的定义。
1) 配置指令
在配置文件中,由 Nginx 约定的内部固定字符串,Nginx 官方文档中的英文单词为 directive,本次统一称为配置指令,简称指令。指令是 Nginx 中功能配置的最基本元素,Nginx 的每个功能配置都是通过多个不同的指令组合来实现的。
2) 配置指令值
每个配置指令都有对应的内容来表示该指令的控制参数,本次约定其对应的内容为配置指令值,简称指令值。指令值可以是字符串、数字或变量等多种类型。
3) 配置指令语句
指令与指令值组合构成指令语句。一条指令语句可以包含多个配置指令值,在 Nginx 配置文件中,每条指令语句都要用;作为语句结束的标识符。
4) 配置指令域
配置指令值有时会是由{ }括起来的指令语句集合,本次约定{ }括起来的部分为配置指令域,简称指令域。指令域既可以包含多个指令语句,也可以包含多个指令域。
5) 配置全局域
配置文件 nginx.conf 中上层没有其他指令域的区域被称为配置全局域,简称全局域。
Nginx 的常见配置指令域如下表所示。
域名称 | 域类型 | 域说明 |
---|---|---|
main | 全局域 | Nginx 的根级别指令区域。该区域的配置指令是全局有效的,该指令名为隐性显示,nginx.conf 的整个文件内容都写在该指令域中 |
events | 指令域 | Nginx 事件驱动相关的配置指令域 |
http | 指令域 | Nginx HTTP 核心配置指令域,包含客户端完整 HTTP 请求过程中每个过程的处理方法的配置指令 |
upstream | 指令域 | 用于定义被代理服务器组的指令区域,也称“上游服务器” |
server | 指令域 | Nginx 用来定义服务 IP、绑定端口及服务相关的指令区域 |
location | 指令域 | 对用户 URI 进行访问路由处理的指令区域 |
stream | 指令域 | Nginx 对 TCP 协议实现代理的配置指令域 |
types | 指令域 | 定义被请求文件扩展名与 MIME 类型映射表的指令区域 |
if | 指令域 | 按照选择条件判断为真时使用的配置指令域 |
打开系统默认的 nginx.conf 文件,可以看到整个文件的结构如下。
#user nobody;
worker_processes 1; # 只启动一个工作进程
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024; # 每个工作进程的最大连接为1024
}
http {
include mime.types; # 引入MIME类型映射表文件
default_type application/octet-stream; # 全局默认映射类型为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 logs/access.log main;
sendfile on; # 启用零复制机制
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65; # 保持连接超时时间为65s
#gzip on;
server {
listen 80; # 监听80端口的网络连接请求
server_name localhost; # 虚拟主机名为localhost
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;
# location / {
# root html;
# index index.html index.htm;
# }
#}
# HTTPS server
#
#server {
# listen 443 ssl;
# server_name localhost;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
#}
}
由上述配置文件可以看出,配置文件中的指令和指令值是以类似于 key-value 的形式书写的。写在配置文件全局域的指令是 Nginx 配置文件的核心指令,主要是对 Nginx 自身软件运行进行配置的指令。其中,events 和 http 所包含的部分分别为事件指令域和 HTTP 指令域,指令域内的指令则明确约定了该区域内的指令的应用范围。
server 指令域被包含于 http 指令域中,同时又包含了 location 指令域,各指令域中的共用范围逐层被上层指令域限定,可见各指令域匹配的顺序是由外到内的。Nginx 的配置指令按照内部设定可以同时编写在不同指令域中,包含在最内层的指令将对外层同名指令进行指令值覆盖,并以最内层指令配置为最终生效配置。
编写 Nginx 配置文件时,为了便于维护,也会把一些指令或指令域写在外部文件中,再通过 include 指令引入 nginx.conf 主配置文件中。例如,配置文件中把写有 types 指令域的 mime.types 文件引用到 http 指令域中。此处使用的是 nginx.conf 文件的相对路径。
一个重要的 Web 服务器任务是提供文件(例如图像或静态 HTML 页面)。您将实现一个示例,根据请求,将从不同的本地目录提供文件: /data/www (可能包含 HTML 文件)和 /data/images (包含图像)。这将需要编辑配置文件,并在具有两个位置块的 http 块内设置一个服务器块。
首先,创建 /data/www 目录并将包含 index.html 任何文本内容的文件放入其中,然后创建目录 /data/images 并在其中放置一些图像。
接下来,打开配置文件。默认配置文件已经包含了该 server 块的几个示例,其中大部分被注释掉了。现在,注释掉所有此类块并启动一个新 server 块:
http {
server {
}
}
通常,配置文件可以包含几个 server 块,这些块由它们侦听的端口和服务器名称来区分。一旦 nginx 决定了哪个 server 处理请求,它就会根据 server 块中定义的 location 指令参数测试请求标头中指定的 URI。
将以下 location 块添加到块中 server :
location / {
root /data/www;
}
此 location 块指定 “ / ” 前缀,与请求中的 URI 相比。对于匹配的请求,URI 将被添加到 root 指令中指定的路径中,即 to /data/www ,以形成本地文件系统上所请求文件的路径。如果有多个匹配 location 的块,nginx 会选择前缀最长的块。上面的 location 块提供最短的前缀,长度为 1,因此只有当所有其他 location 块都无法提供匹配时,才会使用此块。
接下来,添加第二个 location 块:
location /images/ {
root /data;
}
它将匹配以 开头的 /images/ 请求( location / 也匹配此类请求,但前缀较短)。
server 该块的结果配置应如下所示:
server {
location / {
root /data/www;
}
location /images/ {
root /data;
}
}
这已经是侦听标准端口 80 的服务器的工作配置,并且可以在本地计算机上访问 http://localhost/ 。为了响应 URI 以 /images/ 开头的请求,服务器将从该 /data/images 目录发送文件。例如,为了响应请求, http://localhost/images/example.png nginx 将发送 /data/images/example.png 文件。如果这样的文件不存在,nginx 将发送一个指示 404 错误的响应。URI 不以 开头的 /images/ 请求将映射到目录 /data/www 。例如,为了响应请求, http://localhost/some/example.html nginx 将发送 /data/www/some/example.html 文件。
要应用新配置,请启动 nginx(如果尚未启动)或将 reload 信号发送到 nginx 的主进程,方法是执行:
nginx -s reload
nginx 的常见用途之一是将其设置为代理服务器,这意味着接收请求、将它们传递给代理服务器、从它们检索响应并将它们发送到客户端的服务器。
我们将配置一个基本的代理服务器,该服务器使用本地目录中的文件处理图像请求,并将所有其他请求发送到代理服务器。在此示例中,两个服务器都将在单个 nginx 实例上定义。
首先,通过在 nginx 的配置文件中再 server 添加一个块来定义代理服务器,其中包含以下内容:
server {
listen 8080;
root /data/up1;
location / {
}
}
这将是一个简单的服务器,它侦听端口 8080(以前,由于使用标准端口 80 以来,尚未指定该 listen 指令)并将所有请求映射到本地文件系统上的 /data/up1 目录。创建此目录并将 index.html 文件放入其中。请注意,该 root 指令放置在上下文中 server 。当选择用于处理请求的 location 块不包含其自己的 root 指令时,将使用此类 root 指令。
接下来,使用上一节中的服务器配置,并对其进行修改,使其成为代理服务器配置。在第一个 location 块中,将 proxy_pass 指令与参数中指定的代理服务器的协议、名称和端口放在一起(在我们的例子中,它是 http://localhost:8080 ):
server {
location / {
proxy_pass http://localhost:8080;
}
location /images/ {
root /data;
}
}
我们将修改第二个 location 块,该块当前将带有前缀的 /images/ 请求映射到 /data/images 目录下的文件,以使其与具有典型文件扩展名的图像的请求相匹配。修改后的 location 块如下所示:
location ~ \.(gif|jpg|png)$ {
root /data/images;
}
该参数是一个正则表达式,匹配所有以 .gif 、 .jpg 或 .png 结尾的 URI。正则表达式的前面应加上 ~ 。相应的请求将映射到目录 /data/images 。
当 nginx 选择一个 location 块来处理请求时,它首先检查指定前缀的位置指令,记住 location 最长的前缀,然后检查正则表达式。如果存在与正则表达式的匹配项,nginx 会选择这个 location ,否则,它会选择之前记住的那个。
代理服务器的最终配置将如下所示:
server {
location / {
proxy_pass http://localhost:8080/;
}
location ~ \.(gif|jpg|png)$ {
root /data/images;
}
}
在 Nginx 配置文件中有很多与容量、时间相关的指令值,Nginx 配置文件有如下规范。
512
1k或1K
10m或10M
1g或10G
2.时间的最小单位是毫秒,示例如下。
10ms # 10毫秒
30s # 30秒
2m # 2分钟
5h # 5小时
1h 30m # 1小时30分
6d # 6天
3w # 3周
5M # 5个月
2y # 2年
Nginx 使用哈希表加速对 Nginx 配置中常量的处理,如 server 中的主机名、types 中的 MIME 类型映射表、请求头属性字段等数据集合。哈希表是通过关键码来快速访问常量对应值的数据存储结构,在通过哈希表获取数据的过程中,其内部实现通过相关函数将常量名转换为一个关键码来实现对应值的快速定位和读取。
由于数据的复杂性,会出现不同常量名转换的关键码是一样的情况,这就会导致读取对应值时发生冲突。为了解决这个问题,Nginx 同时引入了哈希桶机制,就是把相同关键码的哈希键存在一个哈希桶定义的存储空间中,然后再进行二次计算来获取对应的值。
单个哈希桶的大小等于 CPU 缓存行大小的倍数。这样就可以通过减少内存访问的数量来加速在 CPU 中搜索哈希关键码的速度。如果哈希桶的大小等于 CPU 的缓存行的大小,在 Nginx 进行哈希关键码搜索期间,内存的访问次数最多是两次,一次是计算哈希桶的地址,另一次是在哈希桶内进行哈希关键码的搜索。
Nginx 在每次启动或重新加载配置时会选择合适大小的最小初始化哈希表。哈希表的大小会随哈希桶数量的增加而不断调整,直到哈希桶总的大小达到哈希表设置的最大值。因此,在 Nginx 提示需要增加哈希表或哈希桶的大小时,要先调整哈希表的大小。