nginx基础配置详解:基础篇

nginx简介

Nginx 是一款轻量的(相比 Apache、Lighttpd 而言)、高性能的 HTTP 服务器,同时也可以用作反向代理、负载平衡器和 HTTP 缓存。Nginx 采用了模块化、事件驱动的架构设计,使用了异步非阻塞的事件处理机制处理请求,使得在高负载下也能提供更可靠的性能。

Nginx 的内部结构是由核心部分和一系列的功能模块所组成。Nginx Core 实现底层的通讯协议,为其他模块构建了基本的运行时环境,并且构建了其他各模块的协作基础。

Nginx 程序在启动后,会以守护进程的方式在系统后台中运行,后台进程包含一个 master 进程和多个 worker 进程。

master 进程负责管理 Nginx 本身和其他 worker 进程,包含:接收来自外界的信号、向各 worker 进程发送信号、监控 worker 进程的运行状态、当 worker 进程退出后(异常情况下),会自动重新启动新的 worker 进程等。

worker 进程主要处理基本的网络事件,多个 worker 进程之间是对等的,他们同等竞争来自客户端的请求,各进程互相之间是独立的。一个请求,完全由 worker 进程来处理,而且只在一个 worker 进程中处理。worker 进程的个数是可以设置的,一般我们会设置与机器 cpu 核数一致,这里面的原因与 Nginx 的进程模型以及事件处理模型是分不开的。

nginx安装与命令

安装方法

yum安装rpm包会比编译安装简单很多,默认会安装许多模块,但缺点是如果你想以后安装第三方模块那就没办法了。可参考:https://nginx.org/en/linux_packages.html#RHEL-CentOS

1
2
3
4
5
6
7
cat >/etc/yum.repos.d/nginx.repo <<EOF
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/\$releasever/\$basearch/
gpgcheck=0
enabled=1
EOF

这样就安装好了。如果要选择版本安装,可以使用yum list nginx --enablerepo=nginx --showduplicates来查看可用的版本。

而编译安装会复杂很多,也比较麻烦,但是优点是比较灵活,可以随意添加自己想要的模块。方法在:centos7编译安装LNMP:nginx1.16+mysql5.7+php7.2

nginx相关命令

有如下参数:

1
2
3
4
5
6
7
8
9
10
11
Options:
-?,-h : this help
-v : 输出版本号
-V : 输出版本号以及编译选项
-t : 检查配置文件的语法
-T : 检查配置文件的语法并输出配置的内容
-q : 静默模式,不输出任何信息,用于shell
-s signal : 向主进程发送信号:stop, quit, reopen, reload
-p prefix : 设置nginx的basedir(默认为编译时的prefix,rpm包安装时为/etc/nginx)
-c filename : 指定配置文件,(rpm包安装时为/etc/nginx/nginx.conf)
-g directives : 提前设置全局指令

控制nginx的相关的主要命令有:

  • 启动:nginx -c /etc/nginx/nginx.conf
  • 关闭:nginx -s stop,等同于 kill -s TERM $(cat /var/run/nginx.pid)
  • 优雅关闭:nginx -s quit,等同于 kill -s QUIT $(cat /var/run/nginx.pid),所有的工作进程会停止接受新的连接,并继续服务旧的连接请求直到所有的请求完成后才退出。
  • 加载配置文件:nginx -s reload,等同于 kill -s HUP $(cat /var/run/nginx.pid)
  • 重新打开日志文件:nginx -s reopen,等同于 kill -USR1 $(cat /var/run/nginx.pid)

reload是有做了以下操作:当nginx主进程接收到重载配置文件的命令后,它会先检查新配置文件语法,然后载入该配置文件到内存中并解析。然后,主进程fork一系列新的worker进程,并发送QUIT信号给旧的worker进程(graceful stop)。旧的工作进程接收到QUIT信号后,会停止接受新的连接请求,并继续处理旧的连接直到请求处理完成后才退出。如下work进程的pid是有发生了变化:

1
2
3
4
5
6
7
8
[root@localhost ~]# ps aux |grep nginx
root 10484 0.0 0.0 47260 2080 ? Ss Jan11 0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
nginx 30497 0.0 0.0 47264 2288 ? S Jan17 0:00 nginx: worker process
[root@localhost ~]# nginx -s reload
[root@localhost ~]#
[root@localhost ~]# ps aux |grep nginx
root 10484 0.0 0.0 47260 2080 ? Ss Jan11 0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
nginx 30993 0.0 0.0 47264 2044 ? S 02:59 0:00 nginx: worker process

nginx版本升级

在说明如何稳定安全地升级、降级已经在运行中的nginx之前,需要先了解nginx支持的几种信号。可以通过man nginx来查看到具体的含义:

1
2
3
4
5
6
SIGINT, SIGTERM  立即杀掉nginx主进程(即所有进程)
SIGQUIT graceful stop主进程
SIGWINCH graceful stop所有的worker进程
SIGHUP reload配置文件,并使老的worker进程graceful stop
SIGUSR1 重新打开日志文件(Reopen log files)
SIGUSR2 在线切换nginx可执行程序(Upgrade the nginx executable on the fly)

版本升级时,第一步是先编译好新版本的nginx,再发送 kill -USR2 $(cat /var/run/nginx/nginx.pid)信号,该信号提示nginx旧的主进程要升级,并执行新的nginx程序。发送该信号后将会切换pid文件,旧的pid文件被重命名为nginx.pid.oldbin,记录的是旧的nginx主进程pid值,新的pid文件为nginx.pid,记录的是新启动的nginx的主进程pid值。然后再发送 kill -QUIT $(cat /var/run/nginx/nginx.pid.oldbin)来向旧的主进程号发送QUIT信号,该信号将使得主进程以graceful的方式关闭。这将使得旧的主进程、旧的worker进程不再接受任何新请求,但却会把正在处理过程中的请求处理完毕,然后被销毁退出。

  • 下载新版本,然后按原来的编译参数进行编译:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    [root@VM_0_6_centos ~]# nginx -V
    nginx version: nginx/1.16.1
    built by gcc 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC)
    built with OpenSSL 1.1.1d 10 Sep 2019
    TLS SNI support enabled
    configure arguments: --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-http_gzip_static_module --with-http_sub_module --with-stream --with-stream_ssl_module --with-openssl=/usr/local/src/lnmp1.6/src/openssl-1.1.1d --with-openssl-opt='enable-weak-ssl-ciphers'
    [root@VM_0_6_centos ~]# wget http://nginx.org/download/nginx-1.17.7.tar.gz
    [root@VM_0_6_centos ~]# tar zxf nginx-1.17.7.tar.gz && cd nginx-1.17.7

    # 复制configure arguments的参数过来,原先的参数一定要一样,但可以添加新的模块
    [root@VM_0_6_centos nginx-1.17.7]# ./configure --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-http_gzip_static_module --with-http_sub_module --with-stream --with-stream_ssl_module --with-openssl=/usr/local/src/lnmp1.6/src/openssl-1.1.1d --with-openssl-opt='enable-weak-ssl-ciphers'
    [root@VM_0_6_centos nginx-1.17.7]# make

    make完以后,不需要执行make install,否则会覆盖安装,nginx服务会出现各种问题。

  • 替换执行文件

    1
    2
    3
    4
    [root@VM_0_6_centos nginx-1.17.7]# mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak
    [root@VM_0_6_centos nginx-1.17.7]# cp objs/nginx /usr/local/nginx/sbin/
    [root@VM_0_6_centos nginx-1.17.7]# nginx -v
    nginx version: nginx/1.17.7
  • 使用 make upgrage命令进行升级。我们可以先打开Makefile文件看一下是做了什么操作:

1
2
3
4
5
6
7
8
upgrade:
/usr/local/nginx/sbin/nginx -t

kill -USR2 `cat /usr/local/nginx/logs/nginx.pid`
sleep 1
test -f /usr/local/nginx/logs/nginx.pid.oldbin

kill -QUIT `cat /usr/local/nginx/logs/nginx.pid.oldbin`

跟我们上面说的过程是一样的。开始运行:

1
2
3
4
5
6
7
8
[root@VM_0_6_centos nginx-1.17.7]# make upgrade
/usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
kill -USR2 `cat /usr/local/nginx/logs/nginx.pid`
sleep 1
test -f /usr/local/nginx/logs/nginx.pid.oldbin
kill -QUIT `cat /usr/local/nginx/logs/nginx.pid.oldbin`

此方法同样可以适用于降级操作。整个升级期间是网站都是可以访问的,这是最安全的升级方式。

nginx基础配置详解

nginx配置文件主要分为六个区域: main(全局设置)、events(nginx工作模式)、http(http设置)、 sever(主机设置)、location(URL匹配)、upstream(负载均衡服务器设置)。如下结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
main
events {
....
}
http {
....
upstream myproject {
.....
}
server {
....
location {
....
}
}
....
}

注意:nginx具体的配置后面必须加逗号结尾,不然会报错。所有web站点的配置都是要放在http模块里面的。

main模块

main是一个全局的设置,不需要{},如下:

1
2
3
4
5
user  www www;
worker_processes auto;
error_log /home/wwwlogs/nginx_error.log crit;
pid /usr/local/nginx/logs/nginx.pid;
worker_rlimit_nofile 51200;
  • user 来指定Nginx Worker进程运行用户以及用户组

  • worker_processes来指定了Nginx要开启的子进程数。每个Nginx进程平均耗费10M~12M内存。根据经验,一般指定1个进程就足够了,如果是多核CPU,建议指定和CPU的数量一样的进程数即可。

  • error_log用来定义全局错误日志文件。日志输出级别有debug、info、notice、warn、error、crit可供选择,其中,debug输出日志最为最详细,而crit输出日志最少。

  • pid用来指定进程id的存储文件位置。

  • worker_rlimit_nofile用于指定一个nginx进程可以打开的最多文件描述符数目,也可以理解为一个ningx进程所能处理的最大的连接数。

events 模块

events模块来用指定nginx的工作模式和工作模式及连接数上限。

1
2
3
4
5
6
events
{
use epoll;
worker_connections 51200;
multi_accept on;
}
  • use用来指定Nginx的工作模式。Nginx支持的工作模式有select、poll、kqueue、epoll、rtsig和/dev/poll。其中select和poll都是标准的工作模式,kqueue和epoll是高效的工作模式,不同的是epoll用在Linux平台上,而kqueue用在BSD系统中,因为Mac基于BSD,所以Mac也得用这个模式,对于Linux系统,epoll工作模式是首选。
  • worker_connections用于定义Nginx每个进程的最大连接数,即接收前端的最大请求数,默认是1024。最大客户端连接数由worker_processesworker_connections决定,即Max_clients=worker_processes*worker_connections,在作为反向代理时,Max_clients变为:Max_clients = worker_processes * worker_connections/2

http 模块

http模块可以说是最核心的模块了,它负责HTTP服务器相关属性的配置,它里面的server和upstream子模块,至关重要。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
http{
include mime.types; # nginx支持的媒体文件类型。相对路径为同目录conf下的其他文件
default_type 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 /usr/local/var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 60;
#gzip on;
client_max_body_size 50m;

upstream myproject {
.....
}
server {
....
}
}
  • include 加载 mime.type 文件,用于帮助 Nginx 识别文件的 MIME 类型;
  • default_type 指定文件默认的 MIME 类型。例如,在没有配置 asp 的环境时,Nginx 是不予解析的,此时,浏览器访问 asp 文件就会出现 下载 的提示了;
  • log_format 设置日志的格式和记录哪些参数;
  • access_log 设置 access_log 日志文件地址;
  • sendfile 开启高效文件传输模式,sendfile指令指定nginx是否调用sendfile函数来输出文件,减少用户空间到内核空间的上下文切换。对于普通应用设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络I/O处理速度,降低系统的负载。
  • keepalive_timeout 设置客户端连接保持活动的超时时间,在超过这个时间之后,服务器会关闭该连接;
  • gzip 是否开启 gzip 压缩,这将会减少我们发送的数据量;
    • gzip_min_length 1k : 设置允许压缩的页面最小字节数,页面字节数从header头得content-length中进行获取。默认值是20。建议设置成大于1k的字节数,小于1k可能会越压越大。
    • gzip_buffers 4 16k : 设置系统获取几个单位的缓存用于存储gzip的压缩结果数据流。4 16k代表以16k为单位,安装原始数据大小以16k为单位的4倍申请内存。
    • gzip_http_version 1.0 : 用于识别 http 协议的版本,早期的浏览器不支持 Gzip 压缩,用户就会看到乱码,所以为了支持前期版本加上了这个选项,如果你用了 Nginx 的反向代理并期望也启用 Gzip 压缩的话,由于末端通信是 http/1.0,故请设置为 1.0。
    • gzip_comp_level 6 : gzip压缩比,1压缩比最小处理速度最快,9压缩比最大但处理速度最慢(传输快但比较消耗cpu)
    • gzip_types :匹配mime类型进行压缩,无论是否指定,”text/html”类型总是会被压缩的。
    • gzip_proxied any : Nginx作为反向代理的时候启用,决定开启或者关闭后端服务器返回的结果是否压缩,匹配的前提是后端服务器必须要返回包含”Via”的 header头。
    • gzip_vary on : 和http头有关系,会在响应头加个 Vary: Accept-Encoding ,可以让前端的缓存服务器缓存经过gzip压缩的页面,例如,用Squid缓存经过Nginx压缩的数据
  • client_max_body_size 允许客户端请求的最大单文件字节数。如果上传较大文件,请增加它的限制值;
  • client_body_buffer_size 允许客户端请求的最大缓冲区字节数;
  • proxy_connect_timeout 设置与后端服务器连接超时时间。

server 模块

server 模块是http的子模块,它用来定一个虚拟主机。就是用来建立多个网站的意思。一个server就是对应一个网站。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
server {
listen 80;
server_name localhost;
# 全局定义,如果都是这一个目录,这样定义最简单。
root /usr/www;
index index.php index.html index.htm;

charset utf-8;

error_page 404 /404.html;
error_page 403 /403.html;
error_page 500 502 503 504 /50x.html;

access_log usr/local/var/log/host.access.log main;
aerror_log usr/local/var/log/host.error.log error;
}
  • listen 设置监听端口,默认 80,小于 1024 的要以 root 用户启动。可以为 listen *:80listen 127.0.0.1:80 等形式;
  • server_name 设置域名,多个域名之间用空格分开;
  • root 设置虚拟主机的默认网站根目录;
  • index 定义默认访问的文件名;
  • charset 设置网页的默认编码格式;
  • error_page 设置错误页面,相对于上面的 root 目录。

root与alias区别

root指的是网站的根目录,而alias指的是别名。先看下例子:

1
2
3
4
5
6
7
8
9
10
11
# nginx有如下配置:
location /test/ {
root /tmp/;
}

[root@localhost ~]# cat /tmp/test/a.txt
root3333333333
[root@localhost ~]# cat /tmp/a.txt
abcd
[root@localhost ~]# curl http://localhost/test/a.txt
root3333333333

配置root的时候,访问 http://localhost/test/a.txt时,访问的文件是 /tmp/test/a.txt

将nginx的配置由root修改为alias之后,再次访问 http://localhost/test/a.txt

1
2
[root@localhost ~]# curl http://localhost/test/a.txt
abcd

这时访问的文件是/tmp/a.txt,这时就可以实现URL的重写。

location详解

location 根据它字面意思就知道是来定位的,定位URL,解析URL,所以,它也提供了强大的正则匹配功能,也支持条件判断匹配,用户可以通过location指令实现Nginx对动、静态网页进行过滤处理。像我们的php环境搭建就是用到了它。

locaiton有以下几种类型的匹配规则:

模式 含义
location = /uri = 表示精确匹配,只有完全匹配上才能生效,优先级最高
location ^~ /uri ^~ 开头对URL路径进行前缀匹配,优先级比 = 次之,但比正则的优先级更高
location ~ pattern 开头表示区分大小写的正则匹配
location ~* pattern 开头表示不区分大小写的正则匹配
location /uri 不带任何修饰符,也表示前缀匹配,但是在正则匹配之后
location / 通用匹配,任何未匹配到其它location的请求都会匹配到

其匹配的顺序如下:

  • ^~和普通匹配。使用前缀匹配,不支持正则表达式,如果有多个location匹配成功的话,不会终止匹配过程,会记忆表达式最长的那个
  • 如果上一步得到的最长的location为^~类型,则表示阻断正则表达式,不再匹配正则表达式
  • 如果上一步得到的最长的location不是^~类型,继续匹配正则表达式,只要有一个正则成功,则使用这个正则的location,立即返回结果,并结束解析过程

实例如下:

  1. ^~优先级并不比普通匹配高:访问/test_1,返回的状态码为400,这是由于最长匹配的结果。
1
2
3
4
5
6
7
8
9
10
11
12
13
#nginx配置
location /test_1 {
return 400;
}
location ^~ /test {
return 401;
}

#测试
[root@localhost ~]# curl -s -o /dev/null -w "%{http_code}\n" http://192.168.1.61/test
401
[root@localhost ~]# curl -s -o /dev/null -w "%{http_code}\n" http://192.168.1.61/test_1
400
  1. 普通匹配、^~、~三者混合使用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#nginx配置
location /test_1 {
return 400;
}
location ^~ /test {
return 401;
}
location ~ /test {
return 402;
}

#测试
[root@localhost ~]# curl -s -o /dev/null -w "%{http_code}\n" http://192.168.1.61/test_1
402
[root@localhost ~]# curl -s -o /dev/null -w "%{http_code}\n" http://192.168.1.61/test
401
[root@localhost ~]# curl -s -o /dev/null -w "%{http_code}\n" http://192.168.1.61/test1
401
  • 访问http://192.168.1.61/test_1,返回的是402,此时^~和普通匹配只记住了最长一个location /test_1,不会阻止正则

  • 访问http://192.168.1.61/test,,返回401,此时^~和普通匹配只记住了最长一个location ^~ /test,会阻止正则

  • 访问http://192.168.1.61/test1,,返回401,此时匹配到了^~,并没有匹配上~
  • return 400一直是匹配不上的。

参考资料

nginx官方文档

Nginx的location规则:优先级和路径替换

nginx配置location总结及rewrite规则写法

nginx的配置、虚拟主机、负载均衡和反向代理

nginx服务器安装及配置文件详解

0%