文章目录
Nginx核心配置文件结构
我们知道Nginx的核心配置文件默认是放在/usr/local/nginx/conf/nginx.conf
。读取Nginx自带的Nginx配置文件,我们将其中的注释部分删除掉后,就剩下下面内容:
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
指令名 指令值; #全局块,主要设置Nginx服务器整体运行的配置指令
#events块,主要设置,Nginx服务器与用户的网络连接,这一部分对Nginx服务器的性能影响较大,
例如:是否开启对多 work process 下的网络连接进行序列化,是否允许同时接收多个网络连接,选取哪种事件驱动模型来处理连接请求等。
events {
指令名 指令值;
}
#http块,是Nginx服务器配置中的重要部分,代理、缓存、日志记录、第三方模块配置...
http {
指令名 指令值;
server { #server块,是Nginx配置和虚拟主机相关的内容
指令名 指令值;
location / {
#基于 URI 进行匹配,以确定请求应当由哪个 location 处理。
指令名 指令值;
}
}
...
}
简单小结下:
-
nginx.conf配置文件中默认有三大块:全局块、events块、http块
-
http块中可以配置多个server块,每个server块又可以配置多个location块。
events块和http块之外的都属于全局块
涉及到的一些术语
虚拟主机技术
我们在上面的配置文件中可以看到server块,是Nginx配置和虚拟主机相关的内容,第一次接触的小伙伴可能就要问了:什么是虚拟主机?
虚拟主机是一种技术,它可以在一台物理服务器上托管多个网站。每个网站都有自己的域名和内容。它可以将一台实际的物理服务器分成多台虚拟的服务器(也就是说我们可以将每个server块单独的看作一个服务器),每台虚拟服务器都可以通过nginx配置不同的web服务。利用虚拟主机,不用为每个要运行的网站提供一台单独的Nginx服务器或单独运行一组Nginx进程。虚拟主机提供了在同一台服务器、同一组Nginx进程上运行多个网站的功能。
我们来看一个例子:
一个基本的 server 块配置如下:
server {
listen 80; # 监听端口
server_name www.example.com; # 服务器名
location / {
root /data/www/example.com; # 网站根目录
index index.html index.htm; # 默认首页文件
}
}
这个 server 块定义了一个 www.example.com 这个域名的虚拟主机,它监听 80 端口,网站根目录为 /data/www/example.com,默认首页为 index.html。
所以,在一台 Nginx 服务器上,我们可以通过多个 server 块来配置多个虚拟主机,每个虚拟主机有自己独立的:
- 域名:通过 server_name 定义
- 根目录:通过 root 定义
- 访问端口:通过 listen 定义
- 默认首页:通过 index 定义
- 自定义配置:可以在 server 块内定义任意 Nginx 配置来自定义该虚拟主机
Nginx是如何拦截到用户对其配置服务器的请求的?
Nginx 是通过监听端口来拦截用户请求的。
当用户在浏览器中访问一个网站时,浏览器会发送 HTTP 请求到服务器的某个端口。Nginx 作为网站的服务器,需要监听某个端口,来接收用户的请求。
Nginx 的端口监听有两种方式:
- 监听所有接口的指定端口:使用 listen 80 等方式监听 80 端口,这会监听服务器上的所有网络接口的 80 端口。
- 监听指定接口的指定端口:使用 listen 192.168.1.1:80 等方式监听某个具体网络接口的 80 端口。
举个例子,一个简单的 Nginx 服务器配置为:
server {
listen 80;
server_name www.example.com;
...
}
此配置使 Nginx 监听所有网络接口的 80 端口。
- 当用户在浏览器中访问 www.example.com 时,浏览器会向这个服务器的 80 端口发起 HTTP 请求。
- Nginx 由于监听了 80 端口,所以能够拦截到这个请求。
- 接收到请求后,Nginx 根据 server_name 配置找到与请求对应的虚拟主机配置(所以两个不同的 server 块可以监听同一个端口),并对请求进行处理。
所以,Nginx 要实现拦截用户请求,关键是要监听正确的端口。只有当 Nginx 监听了用户请求会访问的端口时,才能够拦截到对应请求,然后进行处理。如果 Nginx 没有监听用户请求的端口,该请求就无法被 Nginx 拦截和处理。
总结一下:
Nginx 拦截用户请求的思路是:监听端口 -> 拦截请求 -> 虚拟主机映射 -> 处理请求。只有用户请求访问了 Nginx 监听的端口,Nginx 才有机会去拦截和处理该请求。
网络接口
我们在上面一部分中可以看见一句话:
使用 listen 80 等方式监听 80 端口,这会监听服务器上的所有网络接口的 80 端口
。那么我们怎么理解所有网络接口的 80 端口
这句话呢?
服务器一般会有多块网络接口,例如:
- 公网 IP 对应的网卡接口
- 内网 IP 对应的网卡接口
- 本地回环接口 lo
- 等等
当 Nginx 使用 listen 80 这种方式监听 80 端口时,它会监听服务器上所有的网络接口的 80 端口。
也就是说,无论用户通过哪块网卡向服务器的 80 端口发送请求,Nginx 都可以接收到。
举个例子,如果一台服务器:
- 公网 IP:219.216.121.12
- 内网 IP:192.168.1.10
- 本地回环 IP:127.0.0.1
该服务器上安装了 Nginx,并配置为:
server {
listen 80;
...
}
则:
- 当用户访问 219.216.121.12 的 80 端口时,Nginx 可以接收到请求
- 当用户访问 192.168.1.10 的 80 端口时,Nginx 也可以接收到请求
- 当用户访问 127.0.0.1 的 80 端口时,Nginx 同样可以接收到请求
这是因为 Nginx 监听了所有的网络接口(网卡)的 80 端口,不管数据从哪块网卡进来,只要目标端口是 80,Nginx 都可以拦截到。
所以,当 Nginx 配置为 listen 80 时,它所监听的是:
- 所有公网 IP 对应的网卡
- 所有内网 IP 对应的网卡
- 本地回环接口
- 服务器上的其他所有网络接口
的 80 端口。不管用户是通过哪个 IP 或哪块网卡访问,Nginx 都能接收到数据,这就是监听“所有网络接口”的含义。
如果 Nginx 只想监听某个具体的 IP 或网卡,可以使用 listen 192.168.1.10:80 这种方式指定具体的 IP 地址进行监听。
全局块
user指令
(1)user:用于配置运行Nginx服务器的worker进程的用户和用户组。
语法 | user user [group] |
---|---|
默认值 | nobody |
位置 | 全局块 |
如果不配置用户组则默认会以用户的名字作为用户组
该属性也可以在编译的时候指定,语法如下./configure --user=user --group=group
,如果两个地方都进行了设置,最终生效的是配置文件中的配置。
该指令的使用步骤:
(1)设置一个用户信息"www"
user www;
这里之所以报错是因为我们当前的centos系统里面根本没有www这个用户,所以我们首先新建一个www用户。
(2) 创建一个用户
useradd www
(3)修改user属性
user www
此时我们reload以后可以发现用户已经生效了:
(4)创建/root/html/index.html
页面,添加如下内容
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
<p><em>I am WWW</em></p>
</body>
</html>
(5)修改nginx.conf
location / {
root /root/html;
index index.html index.htm;
}
(5)测试启动访问
页面会报403拒绝访问的错误
(6)分析原因
因为当前用户没有访问/root/html目录的权限
(7)将文件创建到 /home/www/html/index.html
,修改配置
location / {
root /home/www/html;
index index.html index.htm;
}
(8)再次测试启动访问
能正常访问。
综上所述,使用user指令可以指定启动运行工作进程的用户及用户组,这样对于系统的权限访问控制的更加精细,也更加安全。
work process指令
master_process:用来指定是否开启工作进程。
这个指令我们在工作中一般采用默认就可以,只有当我们进行测试的时候我们可能会把它关闭掉,只留一个Nginx的主进程进行测试。
语法 | master_process on|off; |
---|---|
默认值 | master_process on; |
位置 | 全局块 |
worker_processes:用于配置Nginx生成工作进程的数量,这个是Nginx服务器实现并发处理服务的关键所在。理论上来说workder process的值越大,可以支持的并发处理量也越多,但事实上这个值的设定是需要受到来自服务器自身的限制,建议将该值和服务器CPU的内核数保存一致。
语法 | worker_processes num/auto; |
---|---|
默认值 | 1 |
位置 | 全局块 |
如果将worker_processes设置成2,则会看到如下内容:
其他指令
daemon:设定Nginx是否以守护进程的方式启动。
守护式进程是linux后台执行的一种服务进程,特点是独立于控制终端,不会随着终端关闭而停止
语法 | daemon on|off; |
---|---|
默认值 | daemon on; |
位置 | 全局块 |
pid:用来配置Nginx当前master进程的进程号ID存储的文件路径。
语法 | pid file; |
---|---|
默认值 | 默认为:/usr/local/nginx/logs/nginx.pid |
位置 | 全局块 |
该属性可以通过./configure --pid-path=PATH
来指定
error_log:用来配置Nginx的错误日志存放路径
语法 | error_log file [日志级别]; |
---|---|
默认值 | error_log logs/error.log error; |
位置 | 全局块、http、server、location |
该属性可以通过./configure --error-log-path=PATH
来指定
其中日志级别的值有:debug|info|notice|warn|error|crit|alert|emerg,翻译过来为试|信息|通知|警告|错误|临界|警报|紧急,这块建议大家设置的时候不要设置成info以下的等级,因为会带来大量的磁盘I/O消耗,影响Nginx的性能
(5)include:用来引入其他配置文件,使Nginx的配置更加灵活
语法 | include file; |
---|---|
默认值 | 无 |
位置 | any |
events块
(1)accept_mutex:用来设置Nginx网络连接序列化
语法 | accept_mutex on|off; |
---|---|
默认值 | accept_mutex on; |
位置 | events |
这个配置主要可以用来解决常说的"惊群"问题。大致意思是在某一个时刻,客户端发来一个请求连接,Nginx后台是以多进程的工作模式,也就是说有多个worker进程会被同时唤醒,但是最终只会有一个进程可以获取到连接,如果每次唤醒的进程数目太多,就会影响Nginx的整体性能。如果将上述值设置为on(开启状态),将会对多个Nginx进程接收连接进行序列号,一个个来唤醒接收,就防止了多个进程对连接的争抢。
(2)multi_accept:用来设置是否允许同时接收多个网络连接
语法 | multi_accept on|off; |
---|---|
默认值 | multi_accept off; |
位置 | events |
如果multi_accept被禁止了,nginx一个工作进程只能同时接受一个新的连接。否则,一个工作进程可以同时接受所有的新连接
(3)worker_connections:用来配置单个worker进程最大的连接数
语法 | worker_connections number; |
---|---|
默认值 | worker_commections 512; |
位置 | events |
这里的连接数不仅仅包括和前端用户建立的连接数,而是包括所有可能的连接数。另外,number值不能大于操作系统支持打开的最大文件句柄数量。
(4)use:用来设置Nginx服务器选择哪种事件驱动来处理网络消息。
语法 | use method; |
---|---|
默认值 | 根据操作系统定 |
位置 | events |
注意:此处所选择事件处理模型是Nginx优化部分的一个重要内容,method的可选值有select/poll/epoll/kqueue等,之前在准备centos环境的时候,我们强调过要使用linux内核在2.6以上,就是为了能使用epoll函数来优化Nginx。
另外这些值的选择,我们也可以在编译的时候使用
--with-select_module
、--without-select_module
、
--with-poll_module
、 --without-poll_module
来设置是否需要将对应的事件驱动模块编译到Nginx的内核。
events指令配置实例
打开Nginx的配置文件 nginx.conf,添加如下配置
events{
accept_mutex on;
multi_accept on;
worker_commections 1024;
use epoll;
}
启动测试
./nginx -t
./nginx -s reload
http块
定义MIME-Type
我们都知道浏览器中可以显示的内容有HTML、XML、GIF等种类繁多的文件、媒体等资源,浏览器为了区分这些资源,就需要使用MIME Type。所以说MIME Type是网络资源的媒体类型。Nginx作为web服务器,也需要能够识别前端请求的资源类型。
在Nginx的配置文件中,默认有两行配置
include mime.types;
default_type application/octet-stream;
默认的default_type是application/octet-stream,指的是以二进制流的方式进行处理,也就是说浏览器接收到相应请求之后会以下载附件的方式进行相关操作。
(1)default_type:用来配置Nginx响应前端请求默认的MIME类型。
语法 | default_type mime-type; |
---|---|
默认值 | default_type text/plain; |
位置 | http、server、location |
在default_type之前还有一句include mime.types
,include之前我们已经介绍过,相当于把mime.types文件中MIMT类型与相关类型文件的文件后缀名的对应关系加入到当前的配置文件中。
举例来说明:
有些时候请求某些接口的时候需要返回指定的文本字符串或者json字符串,如果逻辑非常简单或者干脆是固定的字符串,那么可以使用nginx快速实现,这样就不用编写程序响应请求了,可以减少服务器资源占用并且响应性能非常快。
如何实现:
location /get_text {
#这里也可以设置成text/plain
default_type text/html;
return 200 "<h1>This is nginx's text</h1>";
}
location /get_json{
default_type application/json;
return 200 '{"name":"TOM","age":18}';
}
我们分别来看看效果:
情况一:
情况二:
自定义服务日志
Nginx中日志的类型分access.log、error.log。
access.log:用来记录用户所有的访问请求。
error.log:记录nginx本身运行时的错误信息,不会记录用户的访问请求。
Nginx服务器支持对服务日志的格式、大小、输出等进行设置,需要使用到两个指令,分别是access_log和log_format指令。
(1)access_log:用来设置用户访问日志的相关属性。
语法 | access_log path[format[buffer=size]] |
---|---|
默认值 | access_log logs/access.log combined; |
位置 | http , server , location |
(2)log_format:用来指定日志的输出格式。
语法 | log_format name [escape=default|json|none] string…; |
---|---|
默认值 | log_format combined “…”; |
位置 | http |
注意:
这里access_log中的format参数和log_format中的name参数要对应:
其他配置指令
(1)sendfile:用来设置Nginx服务器是否使用sendfile()传输文件,该属性可以大大提高Nginx处理静态资源的性能
语法 | sendfile on|off; |
---|---|
默认值 | sendfile off; |
位置 | http、server、location |
(2)keepalive_timeout:用来设置长连接的超时时间。
为什么要使用keepalive?
我们都知道HTTP是一种无状态协议,客户端向服务端发送一个TCP请求,服务端响应完毕后断开连接。
如果客户端向服务端发送多个请求,每个请求都需要重新创建一次连接,效率相对来说比较低,使用keepalive模式,可以告诉服务器端在处理完一个请求后保持这个TCP连接的打开状态,若接收到来自这个客户端的其他请求,服务端就会利用这个未被关闭的连接,而不需要重新创建一个新连接,提升效率,但是这个连接也不能一直保持,这样的话,连接如果过多,也会是服务端的性能下降,这个时候就需要我们进行设置其的超时时间。
语法 | keepalive_timeout time; |
---|---|
默认值 | keepalive_timeout 75s; |
位置 | http、server、location |
(3)keepalive_requests:用来设置一个keep-alive连接使用的次数。
语法 | keepalive_requests number; |
---|---|
默认值 | keepalive_requests 100; |
位置 | http、server、location |
当我们设置了keepalive之后我们打开开发者工具:
在原来多次请求(或者刷新几次)的的时候会有多个痕迹:
而现在只会有一个,说明链接在复用:
server块和location块
这里我们主要来认识下Nginx默认给的nginx.conf中的相关内容,以及server块与location块在使用的时候需要注意的一些内容。
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 404 /50x.html;
location = /50x.html {
root html;
}
}
http块中可以放多个server块,每一个server块里面也可以放多个location块
- listen表示监听相关端口,默认是80端口
- server-name表示对应的服务名称,这个名称我们可以指定具体的ip也可以指定localhost,也可以是域名
- listen和server-name共同组成了我们请求url的前半部分,而后半部分是由我们的location来进行设置的
- location里面的root代表资源所对应的目录
- index表示当路径匹配的时候默认访问的首页,从前往后尝试到成功为止
- 这里的index.html 和 index.htm都要放在html文件夹(也就是root指定的资源目录)下才能生效
- error_page后面跟的是错误(状态)码,当发生指定的状态码的时候会跳转到/50x.html页面
- 这个/50x.html也是放在html目录
Nginx服务器基础配置实例
我们将通过一个比较完整和最简单的基础配置实例,来巩固下前面所学习的指令及其配置。
需求如下:
(1)有如下访问:
http://192.168.200.133:8081/server1/location1
访问的是:index_sr1_location1.html
http://192.168.200.133:8081/server1/location2
访问的是:index_sr1_location2.html
http://192.168.200.133:8082/server2/location1
访问的是:index_sr2_location1.html
http://192.168.200.133:8082/server2/location2
访问的是:index_sr2_location2.html
(2)如果访问的资源不存在,
返回自定义的404页面
(3)将/server1和/server2的配置使用不同的配置文件分割
将文件放到/home/www/conf.d目录下,然后使用include进行合并
(4)为/server1和/server2各自创建一个访问日志文件
准备相关文件,目录如下:
配置的内容如下:
##全局块 begin##
#配置允许运行Nginx工作进程的用户和用户组
user www;
#配置运行Nginx进程生成的worker进程数
worker_processes 2;
#配置Nginx服务器运行对错误日志存放的路径
error_log logs/error.log;
#配置Nginx服务器允许时记录Nginx的master进程的PID文件路径和名称
pid logs/nginx.pid;
#配置Nginx服务是否以守护进程方法启动
#daemon on;
##全局块 end##
##events块 begin##
events{
#设置Nginx网络连接序列化
accept_mutex on;
#设置Nginx的worker进程是否可以同时接收多个请求
multi_accept on;
#设置Nginx的worker进程最大的连接数
worker_connections 1024;
#设置Nginx使用的事件驱动模型
use epoll;
}
##events块 end##
##http块 start##
http{
#定义MIME-Type
include mime.types;
default_type application/octet-stream;
#配置允许使用sendfile方式运输
sendfile on;
#配置连接超时时间
keepalive_timeout 65;
#配置请求处理日志格式
log_format server1 '===>server1 access log';
log_format server2 '===>server2 access log';
##server块 开始##
include /home/www/conf.d/*.conf;
##server块 结束##
}
##http块 end##
server1.conf
server{
#配置监听端口和主机名称
listen 8081;
server_name localhost;
#配置请求处理日志存放路径
access_log /home/www/myweb/server1/logs/access.log server1;
#配置错误页面
error_page 404 /404.html;
#配置处理/server1/location1请求的location
location /server1/location1{
root /home/www/myweb;
index index_sr1_location1.html;
}
#配置处理/server1/location2请求的location
location /server1/location2{
root /home/www/myweb;
index index_sr1_location2.html;
}
#配置错误页面转向
location = /404.html {
root /home/www/myweb;
index 404.html;
}
}
server2.conf
server{
#配置监听端口和主机名称
listen 8082;
server_name localhost;
#配置请求处理日志存放路径
access_log /home/www/myweb/server2/logs/access.log server2;
#配置错误页面,对404.html做了定向配置
error_page 404 /404.html;
#配置处理/server1/location1请求的location
location /server2/location1{
root /home/www/myweb;
index index_sr2_location1.html;
}
#配置处理/server2/location2请求的location
location /server2/location2{
root /home/www/myweb;
index index_sr2_location2.html;
}
#配置错误页面转向
location = /404.html {
root /home/www/myweb;
index 404.html;
}
}
接下来我们进行测试:
-
访问测试:http://192.168.200.133:8081/server1/location1,访问的是:index_sr1_location1.html
-
http://192.168.200.133:8081/server1/location2,访问的是:index_sr1_location2.html
-
http://192.168.200.133:8082/server2/location1,访问的是:index_sr2_location1.html
-
http://192.168.200.133:8082/server2/location2,访问的是:index_sr2_location2.html
-
如果访问的资源不存在,返回自定义的404页面: