Nginx面试题(史上最全 + 持续更新) - 疯狂创客圈 - 博客园
8 Nginx 动态代理
使用 Nginx 实现动态代理通常涉及到配置 Nginx 以支持根据请求动态改变后端服务器的能力。这可以通过几种方法实现,包括但不限于使用 Nginx 的变量、子请求、以及结合外部脚本或服务来动态更新代理配置。下面是一个基本的例子说明如何使用这些技术来实现动态代理。
8.1 使用 Nginx 变量和子请求
你可以利用 Nginx 的 map 指令来基于某些条件(如请求的 URI)来设置变量,然后在 proxy_pass 指令中使用这些变量来指向不同的后端。
http {
# 其他配置 ...
# 动态上游配置
dyups {
srv_domain "backend.example.com";
srv_host "dns.example.com";
srv_port 8600;
update_period 60s;
update_callback "update_backend_callback";
}
# 回调函数,用于处理上游服务器更新
init_by_lua_block {
require('dyups').init()
}
upstream backend {
server backend1.example.com;
# 不需要指定具体的后端服务器,将由dyups模块动态更新
}
server {
location / {
proxy_pass http://backend;
# 代理设置 ...
}
}
}
在这个配置中,dyups模块会定期从backend.example.com:8600(通过DNS解析为IP地址)检查新的上游服务器列表,并更新 backend 上游组的服务器列表。
8.2 动态重配置
另一种方法是通过外部脚本修改 Nginx 的配置文件,并在每次修改后重新加载 Nginx 配置。这种方式允许你在运行时更改代理目标而无需重启整个 Nginx 进程。
还有一种是使用 Nginx 扩展模块。如, ngx_http_dyups_module 是 Nginx 的一个第三方模块,它允许 Nginx 在运行时动态地改变其上游(upstream)配置。这个模块扩展了 Nginx 的功能,使其能够在不重启服务的情况下,根据请求动态地选择不同的后端服务器进行代理操作。这对于需要频繁调整后端服务器映射的应用场景非常有用,尤其是在负载均衡和高可用性的部署中。
还有通过 Lua 脚本来实现等等。
9 ⭐️ 聊聊:C10K 问题的本质和解决方案
9.3 C10K 问题的解决方案探讨
从网络编程技术的角度来说,主要思路为:
- 为每个连接分配一个独立的线程/进程。
- 同一个线程/进程同时处理多个连接(IO 多路复用)。
9.3.1 为每个连接分配一个独立的线程/进程
这一思路最为直接。但是,由于申请进程/线程会占用相当可观的系统资源,同时对于多进程/线程的管理会对系统造成压力,因此,这种方案不具备良好的可扩展性。
这一思路在服务器资源还没有富裕到足够程度的时候,是不可行的。即便资源足够富裕,效率也不够高。
总之,此思路技术实现会使得资源占用过多,可扩展性差,在实际应用中已被抛弃。
9.3.2 同一个线程/进程同时处理多个连接(IO 多路复用)
IO 多路复用,从技术实现上,又分很多种。我们逐一来看看下述各种实现方式的优劣。
实现方式 1:循环逐个处理各个连接,每个连接对应一个 socket
循环逐个处理各个连接,每个连接对应一个 socket。当所有 socket 都有数据的时候,这种方法是可行的。但是,当应用读取某个 socket 的文件数据不 ready 的时候,整个应用会阻塞在这里,等待该文件句柄 ready,即使别的文件句柄 ready,也无法往下处理。
实现小结:直接循环处理多个连接。
问题归纳:任一文件句柄的不成功会阻塞住整个应用。
实现方式 2:使用 select 方法
使用 select 方法解决上面阻塞的问题,思路比较简单。在读取文件句柄之前,先查下它的状态,如果 ready 了,就进行处理;如果不 ready,就不进行处理;这不就解决了这个问题了嘛?于是,有了 select 方案。用一个 fd_set 结构体来告诉内核同时监控多个文件句柄,当其中有文件句柄的状态发生指定变化(例如某句柄由不可用变为可用)或超时,则调用返回。
之后,应用可以使用 FD_ISSET 来逐个查看,确定哪个文件句柄的状态发生了变化。这样做,小规模的连接问题不大,但当连接数很多(文件句柄个数很多)的时候,逐个检查状态就很慢了。因此,select 往往存在管理的句柄上限(FD_SETSIZE)。同时,在使用上,因为只有一个字段记录关注和发生事件,所以每次调用之前,要重新初始化 fd_set 结构体。
intselect(intnfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,structtimeval *timeout);实现小结:有连接请求抵达了,再检查处理。
问题归纳:句柄上限+重复初始化+逐个排查所有文件句柄状态,效率不高。
实现方式 3:使用 poll 方法
poll 主要解决 select 的前两个问题:
- 通过一个 pollfd 数组,向内核传递需要关注的事件,以消除文件句柄上限。
- 使用不同字段分别标注 “关注事件和发生事件”,来避免重复初始化。
实现小结:设计新的数据结构,提高使用效率。
问题归纳:逐个排查所有文件句柄状态,效率不高。
实现方式 4:使用 epoll 方法
既然 “poll 逐个排查所有文件句柄状态” 效率不高,很自然的,在调用返回的时候,如果只给应用提供发生了状态变化(很可能是数据 ready)的文件句柄,进行排查的效率就高很多。epoll 采用了这种设计,适用于大规模的应用场景。实验表明:当文件句柄数目超过 10 之后,epoll 性能将优于 select 和 poll;当文件句柄数目达到 10K 的时候,epoll 已经超过 select 和 poll 两个数量级。
实现小结:只返回状态变化的文件句柄。
问题归纳:依赖特定平台(Linux)。
因为 Linux 是互联网企业中使用率最高的操作系统,所以 Epoll 就成为 “C10K killer、高并发、高性能、异步非阻塞” 这些技术的代名词了。FreeBSD 推出了 kqueue,Linux 推出了 epoll,Windows 推出了 IOCP,Solaris 推出了 /dev/poll。这些操作系统提供的功能,就是为了解决 C10K 问题。epoll 技术的编程模型就是异步非阻塞回调,也可以叫做 Reactor、事件驱动、事件轮循(EventLoop)。Nginx、libevent、node.js 这些就是 Epoll 时代的产物。
实现方式 5:使用 libevent 库
由于 epoll,、kqueue、IOCP 每个接口都有自己的特点,程序移植非常困难,所以需要对这些接口进行封装,以让它们易于使用和移植,其中 libevent 库就是其中之一。跨平台,封装底层平台的调用,提供统一的 API,但底层在不同平台上自动选择合适的调用。
按照 libevent 的官方网站,libevent 库提供了以下功能:当一个文件描述符的特定事件(如可读,可写或出错)发生了,或一个定时事件发生了,libevent 就会自动执行用户指定的回调函数,来处理事件。目前,libevent 已支持以下接口 /dev/poll、kqueue、event ports、select、poll 和 epoll。Libevent 的内部事件机制完全是基于所使用的接口的。因此,libevent 非常容易移植,也使它的扩展性非常容易。目前,libevent 已在以下操作系统中编译通过:Linux、BSD、Mac OS X、Solaris 和 Windows。使用 libevent 库进行开发非常简单,也很容易在各种 unix 平台上移植。
12 ⭐️ 聊聊:请解释 Nginx 服务器上的 Master 和 Worker 进程分别是什么?
- 主程序 Master process 启动后,通过一个 for 循环来接收和处理外部信号;
- 主进程通过 fork() 函数产生 worker 子进程,每个子进程执行一个 for 循环来实现 Nginx 服务器对事件的接收和处理。
一般推荐 worker 进程数与 CPU 内核数一致,这样一来不存在大量的子进程生成和管理任务,避免了进程之间竞争 CPU 资源和进程切换的开销。而且 Nginx 为了更好的利用多核特性,提供了 CPU 亲缘性的绑定选项,我们可以将某一个进程绑定在某一个核上,这样就不会因为进程的切换带来 Cache 的失效。
对于每个请求,有且只有一个工作进程对其处理。首先,每个 worker 进程都是从 master 进程 fork 过来。在 master 进程里面,先建立好需要 listen 的 socket(listenfd) 之后,然后再 fork 出多个 worker 进程。
所有 worker 进程的 listenfd 会在新连接到来时变得可读,为保证只有一个进程处理该连接,所有 worker 进程在注册 listenfd 读事件前抢占 accept_mutex ,抢到互斥锁的那个进程注册 listenfd 读事件,在读事件里调用 accept 接受该连接。
当一个 worker 进程在 accept 这个连接之后,就开始读取请求、解析请求、处理请求,产生数据后,再返回给客户端,最后才断开连接。这样一个完整的请求就是这样的了。我们可以看到,一个请求,完全由 worker 进程来处理,而且只在一个 worker 进程中处理。

在 Nginx 服务器的运行过程中,主进程和工作进程需要进程交互。交互依赖于 Socket 实现的管道来实现。
16 聊聊:ngx_http_upstream_module 的作用是什么?
ngx_http_upstream_module 用于定义可通过 fastcgi 传递、proxy 传递、uwsgi 传递、memcached 传递和 scgi 传递指令来引用的服务器组。
16.1 聊聊:Nginx 配置高可用性怎么配置?
- 当上游服务器(真实访问服务器),一旦出现故障或者是没有及时相应的话,应该直接轮训到下一台服务器,保证服务器的高可用
- Nginx 配置代码:
server {
listen 80;
server_name www.lijie.com;
location / {
# 指定上游服务器负载均衡服务器
proxy_pass http://backServer;
# nginx与上游服务器(真实访问的服务器)超时时间 后端服务器连接的超时时间_发起握手等候响应超时时间
proxy_connect_timeout 1s;
# nginx发送给上游服务器(真实访问的服务器)超时时间
proxy_send_timeout 1s;
# nginx接受上游服务器(真实访问的服务器)超时时间
proxy_read_timeout 1s;
index index.html index.htm;
}
}17 ⭐️ 聊聊:Nginx 为什么不使用多线程?
17.1.1 apache:
创建多个进程或线程,而每个进程或线程都会为其分配 cpu 和内存(线程要比进程小的多,所以 worker 支持比 perfork 高的并发),并发过大会榨干服务器资源。
17.1.2 Nginx:
采用单线程来异步非阻塞处理请求(管理员可以配置 Nginx 主进程的工作进程的数量)(epoll),不会为每个请求分配 cpu 和内存资源,节省了大量资源,同时也减少了大量的 CPU 的上下文切换。
所以才使得 Nginx 支持更高的并发。
19 ⭐️ 聊聊:Nginx IO 事件模型以及连接数上限
events {
use epoll; # epoll 是多路复⽤ IO(I/O Multiplexing)中的⼀种⽅式,但是仅⽤于 linux2.6
# 以上内核,可以⼤⼤提⾼ nginx 的性能
worker_connections 1024; # 单个后台 worker process 进程的最⼤并发链接数
# multi_accept on;
}22 ⭐️ 聊聊:Nginx 和 Apache、Tomcat 之间的不同点
Tomcat 和 Nginx/Apache 区别:
1、Nginx/Apache 是 Web Server,而 Apache Tomact 是一个 servlet container
2、tomcat 可以对 jsp 进行解析,nginx 和 apache 只是 web 服务器,可以简单理解为只能提供 html 静态文件服务。
Nginx 和 Apache 区别:
1)Nginx 轻量级,同样起 web 服务,比 apache 占用更少的内存及资源。
2)Nginx 抗并发,nginx 处理请求是异步非阻塞的,而 apache 则是阻塞型的,在高并发下 nginx 能保持低资源低消耗高性能。
3)Nginx 提供负载均衡,可以做做反向代理,前端服务器
4)Nginx 多进程单线程,异步非阻塞;Apache 多进程同步,阻塞。
23 ⭐️ 聊聊:Nginx 和 Apache 之间的不同点
| nginx | apache |
|---|---|
| 1.nginx 是一个基于 web 服务器 | 1.Apache 是一个基于流程的服务器 |
| 2.所有请求都由一个线程来处理 | 2.单线程处理单个请求 |
| 3.nginx 避免子进程的概念 | 3.apache 是基于子进程的 |
| 4.nginx 类似于速度 | 4.apache 类似于功率 |
| 5.nginx 在内存消耗和连接方面比较好 | 5.apache 在内存消耗和连接方面并没有提高 |
| 6.nginx 在负载均衡方面表现较好 | 6.apache 当流量达到进程的极限时,apache 将拒绝新的连接 |
| 7.对于 PHP 来说,nginx 更可取,因为他支持 PHP | 7.apache 支持的 php python Perl 和其他语言,使用插件,当应用程序基于 python 和 ruby 时,它非常有用 |
| 8.nginx 不支持像 ibmi 和 openvms 一样的 os | 8.apache 支持更多的 os |
| 9.nginx 只具有核心功能 | 9.apache 提供了比 Nginx 更多的功能 |
| 10.nginx 性能和可伸缩性不依赖于硬件 | 10.apache 依赖于 CPU 和内存等硬件组件 |
24 ⭐️ 聊聊:Nginx 与 Apache 对比
24.1 优点
- 轻量级,采用 C 语言进行编写,同样的 web 服务,会占用更少的内存及资源。
- 抗并发,nginx 以 epoll and kqueue 作为开发模型,处理请求是异步非阻塞的,多个连接对应一个进程,负载能力比 apache 高很多,而 apache 则是同步多进程模型,只能一个连接对应一个进程,当压力过大时,它是会被阻塞型的。
在高并发下 nginx 能保持低资源低消耗高性能,而 apache 在 PHP 处理慢或者前端压力很大的情况下,很容易出现进程数飙升,从而拒绝服务的现象。 - 设计高度模块化,编写模块相对简单。
- 配置简洁,正则配置让很多事情变得简单,而且改完配置能使用 -t 测试配置有没有问题,apache 配置复杂,重启的时候发现配置出错了,会很崩溃。
- 一般用于处理静态文件,静态处理性能比 apache 高三倍以上。
- 作为负载均衡服务器,支持 7 层负载均衡。
- 本身就是一个反向代理服务器,而且可以作为非常优秀的邮件代理服务器。
- nginx 启动特别容易, 并且几乎可以做到 7*24 不间断运行,即使运行数个月也不需要重新启动,支持热部署,比如:实现不间断服务的情况下进行软件版本的升级与版本的回退。
- 社区活跃,各种高性能模块出品迅速。
24.2 缺点
- apache 的 rewrite 比 nginx 强大,在 rewrite 频繁的情况下,用 apache。
- apache 发展到现在,模块超多,基本想到的都可以找到。
- apache 更为成熟,少 bug ,nginx 的 bug 相对较多。
- apache 超稳定,Nginx 一个进程死掉时,会影响到多个用户的使用,稳定性差。
- apache 对 PHP 支持比较简单,nginx 需要配合其他后端用。
- apache 在处理动态请求有优势,nginx 在这方面是鸡肋,一般动态请求要 apache 去做,nginx 适合静态和反向。
- apache 仍然是目前的主流,拥有丰富的特性,成熟的技术和开发社区。
25 ⭐️ 聊聊:Nginx 与 Apache 选择
25.1 Apache
- apache 的 rewrite 比 nginx 强大,在 rewrite 频繁的情况下,用 apache
- apache 发展到现在,模块超多,基本想到的都可以找到
- apache 更为成熟,少 bug ,nginx 的 bug 相对较多
- apache 超稳定
- apache 对 PHP 支持比较简单,nginx 需要配合其他后端用
- apache 在处理动态请求有优势,nginx 在这方面是鸡肋,一般动态请求要 apache 去做,nginx 适合静态和反向。
- apache 仍然是目前的主流,拥有丰富的特性,成熟的技术和开发社区
25.2 Nginx
- 轻量级,采用 C 语言进行编写,同样的 web 服务,会占用更少的内存及资源
- 抗并发,nginx 以 epoll and kqueue 作为开发模型,处理请求是异步非阻塞的,负载能力比 apache 高很多,而 apache 则是阻塞型的。在高并发下 nginx 能保持低资源低消耗高性能,而 apache 在 PHP 处理慢或者前端压力很大的情况下,很容易出现进程数飙升,从而拒绝服务的现象。
- nginx 处理静态文件好,静态处理性能比 apache 高三倍以上
- nginx 的设计高度模块化,编写模块相对简单
- nginx 配置简洁,正则配置让很多事情变得简单,而且改完配置能使用 -t 测试配置有没有问题,apache 配置复杂,重启的时候发现配置出错了,会很崩溃
- nginx 作为负载均衡服务器,支持 7 层负载均衡
- nginx 本身就是一个反向代理服务器,而且可以作为非常优秀的邮件代理服务器
- 启动特别容易, 并且几乎可以做到 7*24 不间断运行,即使运行数个月也不需要重新启动,还能够不间断服务的情况下进行软件版本的升级
- 社区活跃,各种高性能模块出品迅速
28 聊聊:Nginx 处理 HTTP 请求的 11 个阶段
下面介绍一下详细的 11 个阶段,每个阶段都可能对应着一个甚至多个 HTTP 模块,通过这样一个模块对比,我们也能够很好的理解这些模块具体是怎么样发挥作用的。

- POST_READ:在 read 完请求的头部之后,在没有对头部做任何处理之前,想要获取到一些原始的值,就应该在这个阶段进行处理。这里面会涉及到一个 realip 模块。
- SERVER_REWRITE:和下面的 REWRITE 阶段一样,都只有一个模块叫 rewrite 模块,一般没有第三方模块会处理这个阶段。
- FIND_CONFIG:做 location 的匹配,暂时没有模块会用到。
- REWRITE:对 URL 做一些处理。
- POST_WRITE:处于 REWRITE 之后,也是暂时没有模块会在这个阶段出现。
接下来是确认用户访问权限的三个模块:
- PREACCESS:是在 ACCESS 之前要做一些工作,例如并发连接和 QPS 需要进行限制,涉及到两个模块:limt_conn 和 limit_req
- ACCESS:核心要解决的是用户能不能访问的问题,例如 auth_basic 是用户名和密码,access 是用户访问 IP,auth_request 根据第三方服务返回是否可以去访问。
- POST_ACCESS:是在 ACCESS 之后会做一些事情,同样暂时没有模块会用到。
最后的三个阶段处理响应和日志:
- PRECONTENT:在处理 CONTENT 之前会做一些事情,例如会把子请求发送给第三方的服务去处理,try_files 模块也是在这个阶段中。
- CONTENT:这个阶段涉及到的模块就非常多了,例如 index, autoindex, concat 等都是在这个阶段生效的。
- LOG:记录日志 access_log 模块。
以上的这些阶段都是严格按照顺序进行处理的,当然,每个阶段中各个 HTTP 模块的处理顺序也很重要,如果某个模块不把请求向下传递,后面的模块是接收不到请求的。
而且每个阶段中的模块也不一定所有都要执行一遍,下面就接着讲一下各个阶段模块之间的请求顺序。
29 聊聊:Nginx 处理 HTTP 请求的 11 个阶段的顺序处理
如下图所示,每一个模块处理之间是有序的,那么这个顺序怎么才能得到呢?其实非常简单,在源码 ngx_module.c 中,有一个数组 ngx_module_name,其中包含了在编译 Nginx 的时候的 with 指令所包含的所有模块,它们之间的顺序非常关键,在数组中顺序是相反的。
char *ngx_module_names[] = {
… …
"ngx_http_static_module",
"ngx_http_autoindex_module",
"ngx_http_index_module",
"ngx_http_random_index_module",
"ngx_http_mirror_module",
"ngx_http_try_files_module",
"ngx_http_auth_request_module",
"ngx_http_auth_basic_module",
"ngx_http_access_module",
"ngx_http_limit_conn_module",
"ngx_http_limit_req_module",
"ngx_http_realip_module",
"ngx_http_referer_module",
"ngx_http_rewrite_module",
"ngx_http_concat_module",
… …
}灰色部分的模块是 Nginx 的框架部分去执行处理的,第三方模块没有机会在这里得到处理。
在依次向下执行的过程中,也可能不按照这样的顺序。例如,在 access 阶段中,有一个指令叫 satisfy,它可以指示当有一个满足的时候就直接跳到下一个阶段进行处理,例如当 access 满足了,就直接跳到 try_files 模块进行处理,而不会再执行 auth_basic、auth_request 模块。
在 content 阶段中,当 index 模块执行了,就不会再执行 auto_index 模块,而是直接跳到 log 模块。整个 11 个阶段所涉及到的模块和先后顺序如下图所示:

配置文件 nginx.conf 有哪些属性模块?
worker_processes 1; # worker进程的数量
events { # 事件区块开始
worker_connections 1024; # 每个worker进程支持的最大连接数
} # 事件区块结束
http { # HTTP区块开始
include mime.types; # Nginx支持的媒体类型库文件
default_type application/octet-stream; # 默认的媒体类型
sendfile on; # 开启高效传输模式
keepalive_timeout 65; # 连接超时
server { # 第一个Server区块开始,表示一个独立的虚拟主机站点
listen 80; # 提供服务的端口,默认80
server_name localhost; # 提供服务的域名主机名
location / { # 第一个location区块开始
root html; # 站点的根目录,相当于Nginx的安装目录
index index.html index.htm; # 默认的首页文件,多个用空格分开
} # 第一个location区块结果
error_page 500502503504 /50x.html; # 出现对应的http状态码时,使用50x.html回应客户
location = /50x.html { # location区块开始,访问50x.html
root html; # 指定对应的站点目录为html
}
}
......34 Nginx 如何实现后端服务健康检查?
我们可以利用第三方模块 upstream_check_module 来检测后端服务的健康状态,如果后端服务器不可用,则所有的请求不转发到这台服务器。
upstream_check_module 是一款阿里的一位大佬开源的,使用 Perl 和 C 编写而成,Github 地址 : https://github.com/yaoweibin/nginx_upstream_check_module 。
关于 upstream_check_module 实现后端服务健康检查的具体做法可以参考 Nginx 负载均衡健康检查功能这篇文章。
36 Nginx 总体架构了解吗?
JavaGuide 技术指北
聊聊:Nginx 如何定义错误提示页面
#error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /root;
}是否有可能将 Nginx 的错误替换为 502 错误、503?
502 =错误网关
503 =服务器超载
有可能,但是您可以确保 fastcgi_intercept_errors 被设置为 ON,并使用错误页面指令。
Location / {
fastcgi_pass 127.0.01:9001;
fastcgi_intercept_errors on;
error_page 502 =503/error_page.html;41 聊聊:nginx 中 500、502、503、504 有什么区别?
500:
Internal Server Error 内部服务错误,比如脚本错误,编程语言语法错误。
502:
Bad Gateway 错误,网关错误。比如服务器当前连接太多,响应太慢,页面素材太多、带宽慢。
503:
Service Temporarily Unavailable,服务不可用,web 服务器不能处理 HTTP 请求,可能是临时超载或者是服务器进行停机维护。
504:
Gateway timeout 网关超时,程序执行时间过长导致响应超时,例如程序需要执行 20 秒,而 nginx 最大响应等待时间为 10 秒,这样就会出现超时。
44 聊聊:如何将请求转发给后端应用服务器
location = / {
proxy_pass http://tomcat:8080/index
}45 聊聊:如何根据文件类型设置过期时间
location ~* \.(js|css|jpg|jpeg|gif|png|swf)$ {
if (-f $request_filename) {
expires 1h;
break;
}
}46 聊聊:如何禁止访问某个目录
location ^~/path/ {
deny all;
}47 聊聊:在 Nginx 中,解释如何在 URL 中保留双斜线?
要在 URL 中保留双斜线,就必须使用 merge_slashes_off;
语法:merge_slashes [on/off]
默认值: merge_slashes on
环境: http,server
48 聊聊:Nginx rewrite 全局变量
Nginx rewrite 常用的全局变量如下:
| 变量 | 说明 |
|---|---|
| $args | 存放了请求 url 中的请求指令。比如 http://www.myweb.name/server/source?arg1=value1&arg2=value2 中的 arg1=value1&arg2=value2 |
| $content_length | 存放请求头中的 Content-length 字段 |
| $content_type | 存放了请求头中的 Content-type 字段 |
| $document_root | 存放了针对当前请求的根路径 |
| $document_uri | 请求中的 uri,不包含请求指令,比如比如 http://www.myweb.name/server/source?arg1=value1&arg2=value2 中的 /server/source |
| $host | 存放了请求 url 中的主机字段,比如 http://www.myweb.name/server/source?arg1=value1&arg2=value2 中的 www.myweb.name 。如果请求中的主机部分字段不可用或者为空,则存放 nginx 配置中该 server 块中 server_name 指令的配置值 |
| $http_user_agent | 存放客户端的代理 |
| $http_cookie | cookie |
| $limit_rate | nginx 配置中 limit_rate 指令的配置值 |
| $remote_addr | 客户端的地址 |
| $remote_port | 客户端与服务器端建立连接的端口号 |
| $remote_user | 变量中存放了客户端的用户名 |
| $request_body_file | 存放了发给后端服务器的本地文件资源的名称 |
| $request_method | 存放了客户端的请求方式,如 get,post 等 |
| $request_filename | 存放当前请求的资源文件的路径名 |
| $requset_uri | 当前请求的 uri,并且带有指令 |
| $query_string | $args 含义相同 |
| $scheme | 客户端请求使用的协议,如 http, https, ftp 等 |
| $server_protocol | 客户端请求协议的版本,如 ”HTTP/1.0”, ”HTTP/1.1” |
| $server_addr | 服务器的地址 |
| $server_name | 客户端请求到达的服务器的名称 |
| $server_port | 客户端请求到达的服务器的端口号 |
| $uri | 同 $document_uri |
49 请解释 ngx_http_upstream_module 的作用是什么?
ngx_http_upstream_module 用于定义可通过 fastcgi 传递、proxy 传递、uwsgi 传递、memcached 传递和 scgi 传递指令来引用的服务器组。
50 聊聊:stub_status 和 sub_filter 指令的作用是什么?
Stub_status 指令:该指令用于了解 Nginx 当前状态的当前状态,如当前的活动连接,接受和处理当前读/写/等待连接的总数
Sub_filter 指令:它用于搜索和替换响应中的内容,并快速修复陈旧的数据
56 聊聊:如何在 Nginx 中获得当前的时间?
要获得 Nginx 的当前时间,必须使用 SSI 模块、date_local 的变量。
Proxy_set_header THE-TIME $date_gmt;
58 聊聊:如何在 Nginx 服务器上添加模块?
在编译过程中,必须选择 Nginx 模块,因为 Nginx 不支持模块的运行时间选择。
Nginx 动态添加模块
很多时候,我们根据当时的项目情况和业务需求安装完 Nginx 后,后续随着业务的发展,往往会给安装好的 Nginx 添加其他的功能模块。在为 Nginx 添加功能模块时,要求 Nginx 不停机。
这就涉及到如何为已安装的 Nginx 动态添加模块的问题。本文,就和小伙伴们一起探讨如何为已安装的 Nginx 动态添加模块的问题。
59 聊聊:如何为 Nginx 动态添加模块
这里以安装第三方 ngx_http_google_filter_module 模块为例。
Nginx 的模块是需要重新编译 Nginx,而不是像 Apache 一样配置文件引用 .so。
59.1 下载扩展
下载第三方扩展模块 ngx_http_google_filter_module
# cd /data/software/
# git clone https://github.com/cuber/ngx_http_google_filter_module59.2 查看安装模块
查看 Nginx 编译安装时安装了哪些模块,将命令行切换到 Nginx 执行程序所在的目录并输入 ./nginx -V,具体如下:
[root@binghe sbin]# ./nginx -V
nginx version: nginx/1.19.1
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-17) (GCC)
built with OpenSSL 1.0.2 22 Jan 2015
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx-1.19.1 --with-openssl=/usr/local/src/openssl-1.0.2 --with-pcre=/usr/local/src/pcre-8.37 --with-zlib=/usr/local/src/zlib-1.2.8 --with-http_ssl_module
[root@binghe sbin]# 可以看出编译安装 Nginx 使用的参数如下:
--prefix=/usr/local/nginx-1.19.1 --with-openssl=/usr/local/src/openssl-1.0.2 --with-pcre=/usr/local/src/pcre-8.37 --with-zlib=/usr/local/src/zlib-1.2.8 --with-http_ssl_module59.3 重新编译
加入需要安装的模块,重新编译,这里添加 —add-module=/data/software/ngx_http_google_filter_module,具体如下:
./configure --prefix=/usr/local/nginx-1.19.1 --with-openssl=/usr/local/src/openssl-1.0.2 --with-pcre=/usr/local/src/pcre-8.37 --with-zlib=/usr/local/src/zlib-1.2.8 --with-http_ssl_module -–add-module=/data/software/ngx_http_google_filter_module如上,将之前安装 Nginx 的参数全部加上,最后添加 —add-module=/data/software/ngx_http_google_filter_module,之后,我们要进行编译操作,如下:
# make //千万不要make install,不然就真的覆盖这里,需要注意的是:不要执行 make install 命令。
59.4 替换 nginx 二进制文件
# 备份原来的nginx执行程序
# mv /usr/local/nginx-1.19.1/sbin/nginx /usr/local/nginx-1.19.1/sbin/nginx.bak
# 将新编译的nginx执行程序复制到/usr/local/nginx-1.19.1/sbin/目录下
# cp /opt/nginx/sbin/nginx /usr/local/nginx-1.19.1/sbin/60 聊聊:如何设置超时时间
http {
keepalive_timeout 60; ###设置客户端连接保持会话的超时时间,超过这个时间,服务器会关闭该连接。
tcp_nodelay on; ####打开 tcp_nodelay,在包含了 keepalive 参数才有效
client_header_timeout 15; ####设置客户端请求头读取超时时间,如果超过这个时间,客户端还没有发送任何数据, Nginx 将返回“Request time out(408)”错误
client_body_timeout 15;####设置客户端请求主体读取超时时间,如果超过这个时间,客户端还没有发送任何数据, Nginx 将返回“Request time out(408)”错误
send_timeout 15; ####指定响应客户端的超时时间。这个超过仅限于两个连接活动之间的时间,如果超过这个时间,客户端没有任何活动,Nginx 将会关闭连接。
}61 聊聊:Nginx 如何限制浏览器和爬虫
61.1 Nginx 限制爬虫
修改 nginx.conf,禁止网络爬虫的 ua,返回 403,具体配置如下:
server{
listen 80;
server_name 127.0.0.1;
# 添加如下内容即可防止爬虫
if ($http_user_agent ~* "qihoobot|Baiduspider|Googlebot|Googlebot-Mobile|Googlebot-Image|Mediapartners-Google|Adsbot-Google|Feedfetcher-Google|Yahoo! Slurp|Yahoo! Slurp China|YoudaoBot|Sosospider|Sogou spider|Sogou web spider|MSNBot|ia_archiver|Tomato Bot")
{
return 403;
}
}61.2 Nginx 限制浏览器访问
限制浏览器访问:
if ($http_user_agent ~* "Firefox|MSIE")
{
return 403;
}61.3 Nginx 限制 IP 访问
有时候我们需要针对屏蔽某些恶意的 IP 访问我们的网站,或者限制仅仅某些白名单 IP 才能访问我们的网站。
这时候我们就可以在 Nginx 中通过简单的配置来达到目的。
#添加IP至allow(例如我们将10.208.96.192和10.208.96.193加入)
location = /index.html
{
allow 10.208.96.192;
allow 10.208.96.193;
deny all;
root /work/weichuangli;
}屏蔽单个 ip 访问
# 格式: deny ip;
deny 123.68.23.5;允许单个 ip 访问
# 格式: allow ip;
allow 123.68.25.6;屏蔽所有 ip 访问
deny all;允许所有 ip 访问
allow all;屏蔽 ip 段访问
# deny ip/mask
# 屏蔽172.12.62.0到172.45.62.255访问的命令
deny 172.12.62.0/24;允许 ip 段访问
# allow ip/mask
# 屏蔽172.102.0.0到172.102.255.255访问的命令
allow 172.102.0.0/16;62 聊聊:502 报错可能原因有哪些?

1)FastCGI 进程是否已经启动
2)FastCGI worker 进程数是否不够
3)FastCGI 执行时间过长
4)FastCGI Buffer 不够
nginx 和 apache 一样,有前端缓冲限制,可以调整缓冲参数
fastcgi_buffer_size 32k;
fastcgi_buffers 8 32k;5)Proxy Buffer 不够
如果你用了 Proxying,调整
proxy_buffer_size 16k;
proxy_buffers 4 16k;6)php 脚本执行时间过长
将php-fpm.conf的 <value name="request_terminate_timeout">0s</value> 的 0s 改成一个时间
67 聊聊:nginx 如何配置 https
# server端基本配置
server {
listen 80;
listen 443 ssl spdy;
server_name io.123.com;
include ssl/io.com; # 注意看下一个文件
location / {
proxy_pass http:``//lb_io;
if``($scheme = http) {
return``301 https:``//$host$request_uri; # 此项配置为转换为https的基本配置
}
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection``"upgrade"``;
}
access_log /data/logs/nginx/access/niuaero.log main;
}
ssl_certificate ssl/ca/io.com.pem; # 这个为购买的https证书,供应商会生成
ssl_certificate_key ssl/ca/io.com.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
# 启用TLS1.1、TLS1.2要求OpenSSL1.0.1及以上版本,若您的OpenSSL版本低于要求,请使用 ssl_protocols TLSv1;
ssl_ciphers HIGH:!RC4:!MD5:!aNULL:!eNULL:!NULL:!DH:!EDH:!EXP:+MEDIUM;
ssl_prefer_server_ciphers ``on``;