Nginx 详解

2023/10/30 Nginx
目录

# 1、Nginx 介绍

  • Nginx是一款免费、开源、高性能的HTTP和反向代理服务器,其独特的特点是占用内存极少,同时具备极强的并发处理能力。
  • 高效性能使Nginx在同类型网页服务器中脱颖而出。Nginx的架构设计高度优化,始终将性能作为首要考虑因素。在实现过程中,Nginx追求极致效率,能够轻松应对高负载的考验。
  • 有研究报告显示,Nginx可以支持高达50000个并发连接数,这无疑证明了其卓越的性能和效率。
  • Nginx 以其高性能,稳定性,丰富的功能,简单的配置和低资源消耗而闻名。

Nginx是一个高性能的HTTP和反向代理服务器。

# 2、正向代理与反向代理

正向代理

正向代理(Forward Proxy)是帮助客户端获取目标服务器内容的中间服务器。

例子

  • 局域网的用户想要访问外部网络是不能直接访问的,需要通过代理服务器才能访问。
  • 国内访问国外网站需要翻墙,翻墙的方式就是通过代理服务器来访问国外网站。

反向代理

反向代理(Reverse Proxy)是一种代理服务器,它代替客户端向其他服务器发送请求,获取资源,并将获取的资源返回给客户端。 通过反向代理,客户端可以间接地获取到目标服务器的资源,而无需直接与目标服务器建立连接。客户端无法感知代理,因为客户端访问网络不需要配置,只要把请求发送到反向代理服务器,由反向代理服务器去选择目标服务器获取数据,然后再返回到客户端。

例子

  • 访问国外网站需要翻墙,但是我们访问一些国内版本的就不用翻墙,因为这些国内版本的网站帮我们去做了翻墙工作,也就是它帮我们去了获取国外网站的数据。并且我们不需要管它是怎么获取的。
  • 访问京东的网站地址是:https:# www.jd.com/,但我们可以用nginx反向代理,通过访问地址:https:# www.xygalaxy.com/jd/ 来访问京东。

# 3、负载均衡

随着访问量的增加,单台服务器的吞吐量、处理请求能力有限,为了避免某个服务器或计算机过载,就需要多台服务器共同来处理请求,提高网站的访问量。那么将请求分发到多台服务器上,就是负载均衡。

负载均衡

负载均衡是将客户端的请求分发到多个服务器上,以提高网站的灵活性和可用性。

例子:假设有30个请求发送到代理服务器,那么由代理服务器根据服务器数量,平均分配,每个服务器处理10个请求,这个过程就叫做负载均衡。

负载均衡的特点

  • 提高系统的吞吐量:将客户端请求分摊到多个后端服务器上,可以减少每个服务器的负载压力,从而提高系统的吞吐量和处理能力。
  • 提高系统的稳定性:当某个服务器出现故障时,负载均衡可以自动将请求转发到其他健康的服务器上,从而保证系统的稳定性和可用性。
  • 提高系统的可扩展性:通过增加后端服务器的数量,可以实现系统的横向扩展,从而应对高并发和大流量的场景。

负载均衡的算法

负载均衡的算法也有很多种,包括轮询算法、IP哈希算法、权重算法、最少连接算法等。这些算法可以根据实际场景的需求进行选择和调整。

  • 轮询算法:每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉能够被自动剔除。轮询算法适合服务器配置相当,无状态且短平快的服务使用。
  • weight权重算法:指定轮询的几率,weight和后端的访问比例成比例,weight权重越高比例越大。通常用于后端服务器配置不均的情况。
  • IP哈希算法:上面两种算法存在一个问题是就是无法做到会话保持,当用户登录到服务器上后,第二次请求的时候会被定位到服务器集群中的某一个,那么已经登录到某个服务器上的用户会重新定位到另一台,之前的登录信息会丢失。ip_hash算法可以解决这个问题,当用户再次访问请求时,会通过hash算法自动定位到已经登录的服务器上,这样每个客户端可以固定在某个web服务器上,解决客户端session的问题。

# 4、动静分离

为了加快网站的解析速度,可以把动态页面和静态页面由不同的服务器来解析,加快解析速度,降低原来单个服务器的压力。

动静分离

# 5、Nginx 安装

Nginx安装方式这里介绍两种:源码安装、Docker安装Nginx

# 5.1 源码安装

  1. 安装nginx需要的依赖环境
# 安装四个依赖环境
yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel
1
2
  1. 下载并解压安装包
# 创建文件夹
mkdir /usr/local/nginx
# 进入文件夹
cd /usr/local

# 下载nginx的tar包
wget http:# nginx.org/download/nginx-1.13.7.tar.gz

# 解压
tar -xvf nginx-1.13.7.tar.gz
1
2
3
4
5
6
7
8
9
10
  1. 指定nginx安装的目录
# 进入nginx目录
cd nginx-1.13.7/

# 指定nginx安装的目录
./configure --prefix=/usr/local/nginx
1
2
3
4
5
  1. 执行安装nginx命令
# 执行编译命令
make

# 执行安装命令
make install

# 进入安装nginx的目录
cd /usr/local/nginx
# 查看安装后的nginx目录
ll
# 或者
ls
1
2
3
4
5
6
7
8
9
10
11
12
  1. 启动nginx
# 进入nginx安装目录后, 执行sbin目录下nginx命令启动
sbin/nginx    

# 关闭nginx
sbin/nginx -s stop   

# 重启并重新加载nginx配置
sbin/nginx -s reload  
1
2
3
4
5
6
7
8
  1. 防火墙端口放行

防火墙相关命令可参考: 防火墙命令详解

# 放行nginx端口号,默认80端口
firewall-cmd --add-port=80/tcp --zone=public --permanent

# 重启防火墙
systemctl restart firewalld

# 查看防火墙放行端口号
firewall-cmd --list-port
1
2
3
4
5
6
7
8
  1. 访问测试 浏览器访问代理服务器,直接输入IP+端口即可
http:# {IP}:端口

# 本地访问,默认80可省略
http:# 127.0.0.1:80
http:# localhost:80
1
2
3
4
5

能正常访问就说明成功了

# 5.2 Docker安装Nginx

Docker安装Nginx,需要Docker环境,这里不再赘述,可参考: Docker详解

  1. Docker拉取镜像并启动
# 拉取镜像
docker pull nginx

# 创建并运行Nginx容器
docker run -d -p 80:80 --name mynginx nginx

# 或者(挂载配置文件)
docker run -d -p 80:80 --name mynginx -v /path/to/mynginx.conf:/etc/nginx/conf.d/default.conf nginx
1
2
3
4
5
6
7
8
  1. 防火墙端口放行

防火墙相关命令可参考: 防火墙命令详解

# 放行nginx端口号,默认80端口
firewall-cmd --add-port=80/tcp --zone=public --permanent

# 重启防火墙
systemctl restart firewalld

# 查看防火墙放行端口号
firewall-cmd --list-port
1
2
3
4
5
6
7
8
  1. 访问测试

能正常访问就说明成功了

# 6、Nginx 常用命令

直接操作sbin目录下nginx

# 前提,进入到nginx命令,另外一种方式是给nginx配置全局环境变量,就不用进到nginx目录再执行命令了
cd  /usr/local/nginx/sbin/

# 查看版本
./nginx -v
# 显示 nginx 的版本,编译器版本和配置参数。
./nginx -V

# 启动
./nginx

# 重启
./nginx -s restart

# 重新加载配置文件
./nginx -s reload

# 快速停止或关闭
./nginx -s stop
# nginx从容停止命令,等所有请求结束后关闭服务
ps -ef |grep nginx
kill -QUIT  nginx主进程号
nginx -s quit
# nginx 快速停止命令,立刻关闭nginx进程
ps -ef |grep nginx
kill -TERM nginx主进程号 
# 强制停止
kill -9 nginx主进程号


# 检查配置文件是否有语法操作
./nginx -t

# 或者显示指定配置文件
./nginx -t -c /usr/local/nginx/conf/nginx.con
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

nginx全局命令

# 启动
sudo service nginx start

# 重启
sudo service nginx restart

# 重新加载nginx配置
sudo service nginx reload

# 停止
sudo service nginx stop

# 配置nginx服务开机自启动
sudo systemctl enable nginx

# 查看nginx状态
sudo systemctl status nginx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 7、Nginx架构

整体架构

Nginx架构主要包括:主进程(Master)、工作进程(Worker)、模块化设计、 事件驱动模型、代理(proxy)设计、缓存加载(Cache Loader)、缓存管理(Cache Manager)

# 7.1、主进程(Master)

Nginx 启动后,在unix系统中会以守护线程(daemon) 的方式在后台运行,并会运行两种进程,一个是主进程(master),一个或多个工作进程(worker)。主进程并不处理网络请求,主要负责调度工作进程:加载配置(Load Configuration)、启动工作进程(Launch workers)及非停升级(Non-stop upgrades,又称:平滑升级)。

主进程(Master)主要用来管理工作进程(Worker)

主进程(Master)主要功能

  1. 接收来自外界的信号
  2. 向各worker进程发送信号
  3. 监控woker进程的运行状态
  4. 当woker进程退出后(异常情况下),会自动重新启动新的woker进程

Master进程接受到命令重启Nginx进程:./nginx -s reload,会按照以下流程:

  1. 首先master进程在收到重启命令后,会先重新加载配置文件,然后再启动新的worker进程,新的worker进程开始以新的配置处理新的请求。
  2. 向所有老的worker进程发送信号,老的worker在收到来自master的信号后,就不再接收新的请求,并且处理完当前进程中的所有未处理完的请求后,再退出。

# 7.2、工作进程(Worker)

Worker工作进程之间是对等的,每个进程处理请求的机会也是一样的。Nginx采用异步非阻塞(单个进程单线程)的方式来处理网络事件。

工作进程(Worker)主要用来处理基本的网络事件

工作进程(Worker)特性

  1. 多个worker进程之间是对等且相互独立的,他们同等竞争来自客户端的请求。
  2. 一个请求,只可能在一个worker进程中处理,一个worker进程,不可能处理其它进程的请求。
  3. worker进程的个数是可以设置的,一般我们会设置与机器cpu核数一致。同时,nginx为了更好的利用多核特性,具有cpu绑定选项,我们可以将某一个进程绑定在某一个核上,这样就不会因为进程的切换带来cache的失效。

工作进程(Worker)处理网络事件流程

接收请求

  1. 创建worker:worker进程都是从master进程fork过来,在master进程建立好需要listen的socket(listenfd)之后,然后再fork出多个worker进程。
  2. 等待连接:所有worker进程的listenfd会在新连接到来时变得可读,每个work进程都可以去accept这个socket(listenfd)。
  3. 连接通知:当一个client连接到来时,所有accept的work进程都会受到通知,但只有一个进程可以accept成功,其它的则会accept失败。
  4. 抢锁:为保证只有一个进程处理该连接,Nginx提供了一把共享锁accept_mutex来保证同一时刻只有一个work进程在accept连接。
  5. 唯一成功连接:所有worker进程在注册listenfd读事件前抢accept_mutex,抢到互斥锁的那个进程注册listenfd读事件,在读事件里调用accept接受该连接。只有一个进程可以accept成功,其它的则会accept失败。

处理请求

  1. 当一个worker进程在accept这个连接之后,就开始读取请求,解析请求,处理请求,产生数据后,再返回给客户端,最后才断开连接。
  2. 一个请求完全由worker进程处理,并且只在一个worker进程中处理。

# 7.3、异步非阻塞、多进程机制

Nginx采用异步非阻塞(单个进程单线程)的方式来处理网络事件。为什么要采用异步非阻塞的方式来处理网络事件呢?

Nginx异步非阻塞多进程IO模型

请求过程分析

  • 当请求过来建立连接,然后再接收数据再发送数据,具体到系统层就是IO读写事件。
  • 当读写事件没有准备好,如果不采用非阻塞的方式,就得阻塞调用,阻塞调用会进入内核等待,导致CPU资源被其它进程占用。
  • 当并发请求越大时,等待的事件越多,CPU利用不上去,并发也上不去。
  • 因此Nginx使用非阻塞的事件模型,系统中事件模型有很多中,比如select/poll/kqueue/epoll等。
  • Epoll模型基于事件驱动机制,可以监控多个事件是否准备完毕,如果可以,就放入epoll队列,这个过程是异步的,worker进程只需要从epoll队列循环处理即可。

多进程机制

  • 服务器每当收到一个客户端时,就有服务器主进程(master)生成一个子进程(worker)出来和客户端建立连接进行交互,直到连接断开,该子进程就结束了。
  • 使用进程的好处是各个进程之间相互独立,不需要加锁,减少了使用锁对性能造成影响,同时降低编程的复杂度,降低开发成本。
  • 采用独立的进程,可以让进程互相之间不会影响,如果一个进程发生异常退出时,其它进程正常工作,master进程则很快启动新的worker进程,确保服务不会中断,从而将风险降到最低。
  • 缺点是操作系统生成一个子进程需要进行内存复制等操作,在资源和时间上会产生一定的开销。当有大量请求时,会导致系统性能下降。

# 7.4、模块化设计

Nginx的架构基础是高度的模块化设计,除了少量的核心代码,其他一切皆为模块。Nginx服务器被分解为多个模块 ,每个模块就是一个功能模块 ,只负责自身的功能,模块之间严格遵循 高内聚,低耦合 的原则。

Nginx使用C语言开发,整体采用模块化设计,模块可以动态的加载到Nginx中工作,模块分为核心模块、基础模块和第三方模块

  • 核心模块:HTTP模块、EVENT模块和MAIL模块。
  • 基础模块:HTTP Access模块、HTTP FastCGI模块、HTTP Proxy模块和HTTP Rewrite模块。
  • 第三方模块:HTTP Upstream Request Hash模块、Notice模块和HTTP Access Key模块。

例子

Nginx 的Worker 进程,包括核心和功能性模块 ,核心模块负责维持一个运行循环( run-loop ),执行网络请求处理的不同阶段的模块功能,比如:存储读写、内容传输 、网络读写 、外出过滤 ,以及将请求发往上游服务器等。而其代码的模块化设计 ,也使得我们可以根据需要对功能模块进行适当的选择和修改 ,编译成具有特定功能的服务器。

五大模块

核心模块、标准HTTP模块、可选HTTP模块、邮件服务模块、第三方模块

核心模块

核心模块是Nginx服务器正常运行必不可少的模块,提供错误日志记录 、配置文件解析、事件驱动机制、进程管理等核心功能。

标准HTTP模块

标准 HTTP 模块提供HTTP协议解析相关的功能,比如:端口配置 、网页编码设置 、HTTP响应头设置等等。

可选HTTP模块

可选 HTTP 模块主要用于扩展标准的HTTP功能,让 Nginx能处理一些特殊的服务,比如:Flash多媒体传输 、解析GeoIP请求、 网络传输压缩 、安全协议SSL支持等。

邮件服务模块

邮件服务模块主要用于支持Nginx的邮件服务 ,包括对POP3协议、IMAP协议和SMTP协议的支持。

第三方模块

第三方模块是为了扩展Nginx服务器应用,完成开发者自定义功能,比如:Json支持、Lua支持等。

# 7.5、事件驱动模型

Nginx使用非阻塞的事件模型,系统中事件模型有很多中,比如select/poll/kqueue/epoll等。

  • epoll例子: 当事件没有准备好时,就放入epoll(队列)里面。如果有事件准备好了,那么就去处理;如果事件返回的是EAGAIN,那么继续将其放入epoll里面。只要有事件准备好了,我们就去处理它,只有当所有时间都没有准备好时,才在epoll里面等着。这样,我们就可以并发处理大量的并发了,当然,这里的并发请求,是指未处理完的请求,线程只有一个,所以同时能处理的请求当然只有一个了,只是在请求间进行不断地切换而已,切换也是因为异步事件未准备好,而主动让出的。这里的切换是没有任何代价,你可以理解为循环处理多个准备好的事件,事实上就是这样的。

在Nginx的异步非阻塞机制中,工作进程在调用IO后,就去处理其他的请求,当IO调用返回后,会通知该工作进程 。对于这样的系统调用,主要使用Nginx服务器的事件驱动模型来实现。

事件驱动模型

以事件为核心,实现事件驱动的异步非阻塞处理方式。

即:每个连接都由一个工作进程处理,工作进程通过异步非阻塞的方式处理连接。

事件驱动模型组成部分

  1. 事件收集器:负责收集worker进程的各种IO请求。
  2. 事件发送器:负责将 IO 事件发送到事件处理器。
  3. 事件处理器:负责各种事件的响应工作。

总结

事件发送器将每个请求放入一个待处理事件列表,使用非阻塞I/O方式调用事件处理器来处理该请求。其处理方式称为多路IO复用方法,常见的包括以下三种:select 模型、poll 模型、epoll 模型。

# 7.6、惊群现象

惊群现象是一种比拟的说法,意思是在鸟群中扔一颗石子,所有的鸟儿都会被惊吓而飞起。

问题

在nginx中,master进程首先初始化监听套接字(比如8080)后,通过fork创建worker进程,所有的worker进程具有相同的进程上下文,也就是说所有的worker进程都会在同一个套接字(8080)监听,当某一个连接到来时候,所有的worker进程都会被唤醒(接收到事件发生的信号),但是最终只会有一个进程会真正处理该请求,其他进程又会再次进入“睡眠状态”。这带来的问题就是进程的切换带来资源的消耗。

解决方法

nginx通过共享内存的方式创建一把互斥锁(accept_mutex),同一时刻只能有一个worker进程持有该accept_mutex锁,worker进程在处理accept事件之前首先试着去获取accept_mutex,只有在获得accept_mutex锁的进程接受accept事件,在接受并处理完accept事件后即释放accept_mutex锁,各个worker进程再次进入竞争锁的过程,这样就避免多个进程同时唤醒处理同一个accept事件。不让多个进程在同一时间监听接受连接的socket,而是让每个进程轮流监听。

# 7.7、代理(proxy)设计

代理设计,可以说是Nginx深入骨髓的设计,无论是对于HTTP,还是对于astCGI、Memcache、Redis 等的网络请求或响应,本质上都采用了代理机制。所以,Nginx天生就是高性能的代理服务器。

# 7.8、Cache Loader

Cache Loader进程加载缓存索引文件信息

# 7.9、Cache Manager

Cache Manager进程管理磁盘的缓存大小,超过预定值大小后最小使用的数据将被删除。

# 8、Nginx目录结构

Nginx的目录结构非常清晰,大致如下:

.
├── client_body_temp                 # POST 大文件暂存目录
├── conf                             # Nginx所有配置文件的目录
│   ├── fastcgi.conf                 # fastcgi相关参数的配置文件
│   ├── fastcgi.conf.default         # fastcgi.conf的原始备份文件
│   ├── fastcgi_params               # fastcgi的参数文件
│   ├── fastcgi_params.default      
│   ├── koi-utf
│   ├── koi-win
│   ├── mime.types                   # 媒体类型
│   ├── mime.types.default
│   ├── nginx.conf                   #这是Nginx默认的主配置文件,日常使用和修改的文件
│   ├── nginx.conf.default
│   ├── scgi_params                  # scgi相关参数文件
│   ├── scgi_params.default  
│   ├── uwsgi_params                 # uwsgi相关参数文件
│   ├── uwsgi_params.default
│   └── win-utf
├── fastcgi_temp                     # fastcgi临时数据目录
├── html                             # Nginx默认站点目录
│   ├── 50x.html                     # 错误页面优雅替代显示文件,例如出现502错误时会调用此页面
│   └── index.html                   # 默认的首页文件
├── logs                             # Nginx日志目录
│   ├── access.log                   # 访问日志文件
│   ├── error.log                    # 错误日志文件
│   └── nginx.pid                    # pid文件,Nginx进程启动后,会把所有进程的ID号写到此文件
├── proxy_temp                       # 临时目录
├── sbin                             # Nginx 可执行文件目录
│   └── nginx                        # Nginx 二进制可执行程序
├── scgi_temp                        # 临时目录
└── uwsgi_temp                       # 临时目录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# 9、Nginx 配置文件结构

Nginx安装完成后,在Nginx安装目录下有个conf目录,里面有一个nginx.conf配置文件,这个配置文件就是Nginx的默认配置文件,也是我们主要需要修改的配置。

# 进入conf目录
cd /usr/local/nginx/conf

# 查看默认配置文件
cat nginx.conf

# 编辑配置文件
vi nginx.conf
1
2
3
4
5
6
7
8

# 9.1、默认配置文件

默认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;
}


http {
    include       mime.types;
    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  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    server {
        listen       80;
        server_name  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;
    #    }
    #}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115

Nginx的默认配置,并没有过多复杂的东西,只是一些案例,默认指向端口:80,默认指向页面是:root文件夹下的index.html页面。还有就是一些报错页面指向。

# 9.2、默认配置文件结构解析

结构层次如下:

...       #全局块

events {     #events块

  ...

}

http   #http块

{

  ...  #http全局块

  server    #server块

  { 

    ...    #server全局块

    location [pattern]  #location块

    {

      ...

    }

    location [pattern] 

    {

      ...

    }

  }

  server

  {

   ...

  }

  ...   #http全局块

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

解析说明

  1. 全局块:配置影响nginx全局的指令。一般有运行nginx服务器的用户组,nginx进程pid存放路径,日志存放路径,配置文件引入,允许生成worker process数等。
  2. events块:配置影响nginx服务器或与用户的网络连接。有每个进程的最大连接数,选取哪种事件驱动模型处理连接请求,是否允许同时接受多个网路连接,开启多个网络连接序列化等。
  3. http块:可以嵌套多个server,配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置。如文件引入,mime-type定义,日志自定义,是否使用sendfile传输文件,连接超时时间,单连接请求数等。
  4. server块:配置虚拟主机的相关参数,一个http中可以有多个server。
  5. location块:配置请求的路由,以及各种页面的处理情况。也就是配置代理路径。

🎉 修改完配置需要执行重新加载命令才能生效: ./nginx -s reload

# 9.3、其他配置文件

Nginx除了nginx.conf配置文件外,还有其他的几个配置文件。

nginx常见的配置文件及其作用

  • nginx.conf:nginx的基本配置文件
  • mime.types:MIME类型关联的扩展文件
  • fastcgi.conf:与fastcgi相关的配置
  • proxy.conf:与proxy相关的配置
  • sites.conf:配置nginx提供的网站,包括虚拟主机常见的配置文件及其作用

# 10、Nginx 配置场景

# 10.1、配置参数说明

  • worker_processes auto: 这个指令会告诉nginx在服务器上启动多少个worker进程。最佳实践是将其设置为“auto”,这样Nginx会自动根据服务器的CPU核心数量启动相应的worker进程。
  • worker_connections 1024: 这个指令会告诉每个worker进程能够处理的最大连接数。如果你的服务器有足够的资源,你可以增加这个数字。
  • sendfile on: 这个指令启用sendfile系统调用,可以更高效地发送文件。
  • tcp_nopush on: 这个指令用于优化TCP包的发送。
  • tcp_nodelay on: 这个指令用于后端连接,使得响应更及时。
  • keepalive_timeout 65: 这个指令设置了客户端与服务器之间的keep-alive连接超时时间。
  • gzip on: 这个指令启用gzip压缩,可以减少客户端和服务器之间传输的数据量。
  • server_tokens off: 这个指令用于关闭服务器的响应头中的版本信息,有助于提高服务器的安全性。
  • client_max_body_size 100m: 这个指令设置了客户端请求体的最大大小。如果你的应用需要用户上传文件,你可能需要调整这个值。
  • fastcgi_connect_timeout 300、fastcgi_send_timeout 300、fastcgi_read_timeout 300 这些指令设置了与FastCGI服务器的连接、发送和读取的超时时间。
  • ssl_protocols TLSv1 TLSv1.1 TLSv1.2: 这个指令设置了SSL协议的版本。建议使用最新的协议版本以提高安全性。
  • ssl_prefer_server_ciphers on: 这个指令建议服务器使用的加密套件,这有助于提高服务器的安全性。

location三个重要配置指令

root指令:用于指定文件系统中某个目录作为请求的根目录,Nginx会在该目录下寻找请求的文件。适用于指定请求的根目录。

location /images/ {
    root /var/www;
}

# 使得访问/images/目录下的资源时,Nginx会到/var/www/images/目录下查找。
# 请求的路径:root指定的URL/var/www + location上的URL/images/
1
2
3
4
5
6

alias:用于将请求映射到另一个目录或文件上(用于将请求的URL路径与文件系统路径进行映射),常用于处理静态资源的请求,这个指令的功能类似于root,只不过可以指定不同的路径。 适用于将URL路径映射到文件系统路径,方便访问资源。

location /uploads/ {
    alias /var/www/uploads/;
}

# 访问/uploads/目录下的资源时,Nginx会在/var/www/uploads/目录下查找
# 注意,使用alias指令时,URI路径会被转换成文件系统路径,例如/uploads/test.jpg会被映射到/var/www/uploads/test.jpg。
# 请求的路径:alias指定的静态资源URL/var/www/uploads/
1
2
3
4
5
6
7

proxy_pass指令:用于配置反向代理,将客户端发送的请求转发给指定的后端服务器,并返回后端服务器的响应结果。适用于配置反向代理,让Nginx将请求转发给后端服务器。

location /api/ {
    proxy_pass http://backend_server/;
}

# 访问/api/目录下的请求会被转发到http://backend_server/服务器上处理。
# 请求的路径:proxy_pass指定的后端服务URLhttp://backend_server/
1
2
3
4
5
6

# 10.2、简单配置案例说明

# 定义工作进程数,通常设置为等于CPU核数
worker_processes  auto;

# 进程文件
pid        /var/run/nginx.pid;

# 工作模式及连接数上限
events {
    worker_connections  1024;  # 单个后台worker process进程的最大并发链接数
}

# 设置日志路径,级别等
http {
    include       mime.types;  # 文件扩展名与文件类型映射表

    # 默认文件类型
    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 /var/log/nginx/access.log main;

    # sendfile 指令指定 nginx 是否调用 sendfile 函数(zero copy 方式)来输出文件,
    # 对于普通应用设为 on,如果用来进行下载等应用磁盘 IO 非常重要的应用,可设置为 off,以平衡磁盘 IO 进程,降低系统的 uptime.
    sendfile        on;
    # tcp_nopush     on;

    # 链接超时时间
    keepalive_timeout  65;

    # gzip压缩开关
    gzip  on;
    gzip_min_length 1k;
    gzip_buffers 4 16k;
    gzip_http_version 1.0;
    gzip_comp_level 2;
    gzip_types text/plain application/x-javascript text/css application/xml;

    # 虚拟主机配置
    server {
        # 监听端口
        listen       80;

        # 域名
        server_name  localhost;

        # 默认请求的静态文件前缀
        location / {
            root   html;
            index  index.html index.htm;
        }

        # 匹配以.php结尾的请求
        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;
        }

        # 匹配以.html结尾的请求
        location ~ /\.ht {
            deny  all;
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

# 10.3、反向代理配置

server { 
    listen 80; # 监听端口

    server_name localhost; # 服务器地址或绑定域名,本地就用localhost或者127.0.0.1
    
    # 拦截前缀
    location / { 
        proxy_pass http://www.baidu.com/;   # 配置反向代理的ip地址和端口号,这里反向代理到百度
    }
}
1
2
3
4
5
6
7
8
9
10

🎉 修改完配置需要执行重新加载命令才能生效: ./nginx -s reload

预期结果

浏览器访问:http://localhost:80,就会是百度首页

# 10.4、负债均衡配置

后端启动三个服务,端口分别是8080、8081、8082,配置负载均衡。

  • nginx默认的负载均衡策略是轮询(Round Robin)策略
  • nginx负载均衡关键字是:upstreamupstream块定义了一个服务器组,即多个后端服务器的集合。
http {
  upstream xygalaxy {
    # least_conn; # 最少连接(Least Connections)策略
    # ip_hash; # IP哈希(IP Hash)策略

    # 默认轮询(Round Robin)策略
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
    server 127.0.0.1:8082;

    # 加权轮询(Weighted Round Robin)策略
    # server 127.0.0.1:8080 weight=1;
    # server 127.0.0.1:8081 weight=4;
    # server 127.0.0.1:8082 weight=5;
  }

  server {
    listen 80;
    server_name 127.0.0.1;

    location / {
      proxy_pass http://xygalaxy;
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

负载均衡策略

  • 轮询(Round Robin)策略

轮询是最常见的负载均衡策略之一,也是Nginx的默认策略。它将请求均衡地分发到后端的多个服务器上,每个请求按顺序依次分发到不同的服务器上。当有服务器宕机时,Nginx会自动将其排除在负载均衡的范围外

  • 最少连接(Least Connections)策略

最少连接策略会将请求发送到当前连接数最少的服务器上,以实现负载均衡。这样可以确保每个服务器上的连接数相对均衡,避免某个服务器被过度压力。Nginx提供了一个模块least_conn来实现最少连接策略。

  • IP哈希(IP Hash)策略

IP哈希策略会根据客户端的IP地址将请求分发到后端服务器上。这样可以确保同一个客户端的请求都会被发送到同一个后端服务器上,提高缓存的效果。Nginx提供了一个模块ip_hash来实现IP哈希策略。

  • 加权轮询(Weighted Round Robin)策略

加权轮询策略允许给不同的服务器设置不同的权重,服务器的权重越高,被选中的概率就越大。这样可以有效地分配服务器的负载压力。

# 10.5、动静分离配置

将静态资源(图片和html资源)和动态资源(后端服务的请求)分离。

http {

    upstream xygalaxy {
        server 127.0.0.1:8080 weight=1;
        server 127.0.0.1:8081 weight=4;
        server 127.0.0.1:8082 weight=5;
    }

    server {
        listen 80;
        server_name 127.0.0.1;

        # 匹配图片
        location ~ .*\.(gif|jpg|pdf|jpeg|png)$ {
            expires    8h; # expires是给一个资源设定一个过期时间,也就是说无需去服务端验证,直接通过浏览器自身确认是否过期即可, 所以不会产生额外的流量。
            root   /nginx/data/image;
        }
    
        # 匹配html文件
        location ~ .*\.(html)$ {
            root   /nginx/data/html;
        }
    
        # 拦截后台请求,正则匹配 api 路径
        location ~* ^/(lb) {
            # 配置代理地址
            proxy_pass http://xygalaxy;
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

# 11、Nginx高级配置场景

# 11.1、静态文件服务

Nginx动静分离的实现。Nginx可以将硬盘上的静态文件服务于Web。对于静态内容,Nginx能提供极高的并发支持。

server {
    location /static/ {
        root /var/www/;
    }
}
1
2
3
4
5

# 11.2、动态内容代理

Nginx反向代理的实现。

location / {
    proxy_pass http://192.168.1.1:8000;
}
1
2
3

# 11.3、SSL加密

Nginx支持SSL加密,可以提供HTTPS服务。

server {
    listen 443 ssl;
    server_name www.example.com;
    ssl_certificate /etc/nginx/ssl/server.crt;
    ssl_certificate_key /etc/nginx/ssl/server.key;
}
1
2
3
4
5
6

# 11.4、URL重写

Nginx的URL重写功能可以将用户易于理解的URL映射到实际的文件路径或者代理路径。

rewrite ^/user/(\d*)$ /user?id=$1;
1

# 11.5、访问控制

Nginx可以配置访问控制,禁止或者允许某些IP或者地理位置的用户访问。

location /admin/ {
    allow 192.168.1.0/24;
    deny all;
}
1
2
3
4

# 11.6、请求限制

Nginx可以限制并发的连接数量和请求速率,预防服务被恶意请求攻击。

location /login/ {
    limit_req zone=one burst=5;
}

1
2
3
4

# 11.7、日志记录

Nginx提供详细的日志功能,可以记录每个请求的详细信息。

access_log /var/log/nginx/access.log main;
1

# 11.8、压缩

Nginx可以对响应内容进行GZIP压缩,减少网络传输的数据量。

gzip on;
gzip_types text/plain application/xml;
1
2

# 11.9. 定向与错误页面

Nginx可以配置重定向和自定义的错误页面。

location /old-url {
    rewrite ^ http://www.example.com/new-url permanent;
}
1
2
3

# 11.10、跨域配置

Nginx可以很容易地配置跨域资源共享(CORS)。

location / {
    if ($http_origin ~* (https?://.*\.example\.com(:[0-9]+)?$)) {
        add_header 'Access-Control-Allow-Origin' '$http_origin' always;
    }
}
1
2
3
4
5

# 11.11、长连接处理

Nginx可以配置长连接,大大提高效率。

keepalive_timeout  65;
1

# 11.12、代理WebSockets

Nginx可以配置代理WebSockets,适用于实时通信。

location /ws/ {
    proxy_pass http://websocket_backend;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
}
1
2
3
4
5
6

# 11.13、HTTP/2配置

Nginx支持HTTP/2协议,可以提高网页加载速度。

server {
    listen 443 ssl http2;
    server_name www.example.com;
    ssl_certificate /etc/nginx/ssl/server.crt;
    ssl_certificate_key /etc/nginx/ssl/server.key;
}
1
2
3
4
5
6

# 11.14、GeoIP配置

Nginx可以利用GeoIP模块根据访问者的IP地址判断其物理位置。

location / {
    if ($geoip_country_code = CN) {
        return 301 http://cn.example.com$request_uri;
    }
}
1
2
3
4
5

# 11.15、强制HTTPS

Nginx可以强制将HTTP请求跳转到HTTPS。

server {
    listen 80;
    server_name www.example.com;
    return 301 https://$host$request_uri;
}
1
2
3
4
5

# 11.16、IP黑名单

Nginx可以将特定的IP列入黑名单,拒绝其访问请求。

location / {
    deny 192.168.1.0;
}
1
2
3

# 11.17、流量控制

Nginx的限速模块,可以很容易地对某个位置或者具体用户等进行限速。

location /download/ {
   limit_rate 10k;
}
1
2
3

# 11.18、IP访问控制

Nginx可以根据访问者的IP地址进行访问控制,比如只允许特定IP访问,或者禁止特定IP访问。

location / {
    deny  192.168.1.1;
    allow 192.168.1.0/24;
    allow 10.1.1.0/16;
    allow 2001:0db8::/32;
    deny  all;
}
1
2
3
4
5
6
7

# 11.19、负载均衡

Nginx负载均衡实现。

upstream xygalaxy {
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
    server 127.0.0.1:8082;
}

server {
    listen 80;
    server_name 127.0.0.1;

    location / {
        proxy_pass http://xygalaxy;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 11.20、认证与授权

Nginx支持多种认证方式,如基于IP的访问控制,基于密码的HTTP基本认证,甚至可以通过第三方模块实现OAuth等复杂的认证机制。

location / {
    auth_basic "Administrator Login";
    auth_basic_user_file /etc/nginx/.htpasswd;
}
1
2
3
4

# 11.21、缓存

Nginx可以缓存来自后端服务器的响应,以加快对同一请求的响应速度,减轻后端服务器的负担。

proxy_cache_path /path/to/cache levels=1:2 keys_zone=MYCACHE:30m inactive=60m;
proxy_cache_key "$scheme$request_method$host$request_uri";

server {
    location / {
        proxy_cache MYCACHE;
        proxy_pass http://backend;
    }
}
1
2
3
4
5
6
7
8
9

# 11.22、if条件判断

Nginx配置的server段、location段支持if条件判断,并支持正则表达式匹配。

语法

if (condition) {}
1

基于浏览器实现分离案例

if ($http_user_agent ~ Firefox) {
  rewrite ^(.*)$ /firefox/$1 break;
}

if ($http_user_agent ~ MSIE) {
  rewrite ^(.*)$ /msie/$1 break;
}

if ($http_user_agent ~ Chrome) {
  rewrite ^(.*)$ /chrome/$1 break;
}
1
2
3
4
5
6
7
8
9
10
11

防盗链案例

location ~* \.(jpg|gif|jpeg|png)$ {
  valid_referers none blocked www.xygalaxy.com;
  if ($invalid_referer) {
    rewrite ^/ http://www.xygalaxy.com/403.html;
  }
}
1
2
3
4
5
6