跳到主要内容 Nginx 高性能 Web 服务器架构与配置指南 | 极客日志
Shell / Bash
Nginx 高性能 Web 服务器架构与配置指南 Nginx 是一款高性能的 HTTP 和反向代理服务器,具有模块化设计、高可靠性及低内存消耗等特点。文章介绍了 Nginx 的进程结构(Master/Worker)、核心模块分类、源码编译安装流程及 systemd 服务配置。内容涵盖站点配置、路径访问控制、大小写区分、用户认证、错误页面定制、变量使用、Rewrite 规则(if/break/last)、防盗链实现、反向代理缓存与动静分离、以及四层负载均衡(TCP)和 DNS 轮询等高级功能配置。
Nginx 介绍
Nginx 是一个高性能的 HTTP 和反向代理服务器,也是一个邮件代理服务器。由俄罗斯的程序设计师 Igor Sysoev 所开发,官方测试 nginx 能够支撑 5 万并发链接,并且 cpu、内存等资源消耗却非常低,运行非常稳定。所以其特点是占有内存少,并发能力强,事实上 Nginx 的并发能力确实在同类型的网页服务器中表现较好。
Nginx 基础特性
模块化设计,较好的扩展性
高可靠性
支持热部署:不停机更新配置文件,升级版本,更换日志文件
低内存消耗:10000 个 keep-alive 连接模式下的非活动连接,仅需 2.5M 内存
event-driven, aio, mmap, sendfile
nginx 的进程结构
web 请求处理机制
多进程方式:服务器每接收到一个客户端请求就有服务器的主进程生成一个子进程响应客户端,直到用户关闭连接,这样的优势是处理速度快,子进程之间相互独立,但是如果访问过大会导致服务器资源耗尽而无法提供请求。
多线程方式:与多进程方式类似,但是每收到一个客户端请求会有服务进程派生出一个线程和此客户端进行交互,一个线程的开销远远小于一个进程,因此多线程方式在很大程度减轻了 web 服务器对系统资源的要求,但是多线程也有自己的缺点,即当多个线程位于同一个进程内工作的时候,可以相互访问同样的内存地址空间,所以他们相互影响,一旦主进程挂掉则所有子线程都不能工作了,IIS 服务器使用了多线程的方式,需要间隔一段时间就重启一次才能稳定。Nginx 是多进程组织模型,而且是一个由 Master 主进程和 Worker 工作进程组成。
主进程 (master process) 的功能
对外接口:接收外部的操作(信号)
对内转发:根据外部的操作的不同,通过信号管理 Worker
监控:监控 worker 进程的运行状态,worker 进程异常终止后,自动重启 worker 进程
读取 Nginx 配置文件并验证其有效性和正确性
建立、绑定和关闭 socket 连接
按照配置生成、管理和结束工作进程
接受外界指令,比如重启、升级及退出服务器等指令
不中断服务,实现平滑升级,重启服务并应用新的配置
开启日志文件,获取文件描述符
不中断服务,实现平滑升级,升级失败进行回滚处理
编译和处理 perl 脚本
工作进程(worker process)的功能
所有 Worker 进程都是平等的
实际处理:网络请求,由 Worker 进程处理
Worker 进程数量:一般设置为核心数,充分利用 CPU 资源,同时避免进程数量过多,导致进程竞争 CPU 资源,增加上下文切换的损耗
接受处理客户的请求
将请求依次送入各个功能模块进行处理
I/O 调用,获取响应数据
与后端服务器通信,接收后端服务器的处理结果
缓存数据,访问缓存索引,查询和调用缓存数据
发送请求结果,响应客户的请求
接收主程序指令,比如重启、升级和退出等
Nginx 模块介绍
核心模块 :是 Nginx 服务器正常运行必不可少的模块,提供错误日志记录、配置文件解析、事件驱动机制、进程管理等核心功能
标准 HTTP 模块 :提供 HTTP 协议解析相关的功能,比如:端口配置、网页编码设置、HTTP 响应头设置等等
可选 HTTP 模块 :主要用于扩展标准的 HTTP 功能,让 Nginx 能处理一些特殊的服务,比如:Flash 多媒体传输、解析 GeoIP 请求、网络传输压缩、安全协议 SSL 支持等
邮件服务模块 :主要用于支持 Nginx 的邮件服务,包括对 POP3 协议、IMAP 协议和 SMTP 协议的支持
Stream 服务模块 : 实现反向代理功能,包括 TCP 协议代理
第三方模块 :是为了扩展 Nginx 服务器应用,完成开发者自定义功能,比如:Json 支持、Lua 支持等
nginx 的安装
Nginx 版本
Mainline version 主要开发版本,一般为奇数版本号,比如 1.19
Stable version 当前最新稳定版,一般为偶数版本,如:1.20
Legacy versions 旧的稳定版,一般为偶数版本,如:1.18
Nginx 安装可以使用 yum 或源码安装,但是推荐使用源码编译安装。yum 的版本比较旧,编译安装可以更方便自定义相关路径,使用源码编译可以自定义相关功能,更方便业务的上的使用。
[root@Nginx ~]# dnf install gcc pcre-devel zlib-devel openssl-devel -y
[root@Nginx nginx-1.24.0]# useradd -s /sbin/nologin -M nginx
[root@Nginx nginx]# tar zxf nginx-1.24.0.tar.gz
[root@Nginx nginx-1.24.0]# cd nginx-1.24.0/
[root@Nginx nginx-1.24.0]# ./configure --prefix=/usr/local/nginx \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--with-pcre \
--with-stream \
--with-stream_ssl_module \
--with-stream_realip_module
[root@Nginx nginx-1.24.0]# make && make install
配置 nginx 的启动文件 [root@Nginx ~]# vim /lib/systemd/system/nginx.service
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
[root@Nginx ~]# systemctl daemon-reload
[root@Nginx ~]# systemctl start nginx
核心配置示例
新建站点
在总配置文件中定义子配置文件路径 use 指定 nginx 的工作模式。nginx 支持的工作模式有 select、poll、kqueue、epoll、rtsig 和 /dev/poll。其中 select 和 poll 都是标准的工作模式,kqueue 和 epoll 是高效的工作模式,不同的是 epoll 用在 Linux 平台上,而 kqueue 用在 BSD 系统中,因为 Mac 基于 BSD,所以 Mac 也得用这个模式,对于 Linux 系统,epoll 工作模式是首选。
vim /usr/local/nginx/conf/nginx.conf
新建子配置文件路径并编辑子配置文件 mkdir /usr/local/nginx/conf.d
vim /usr/local/nginx/conf.d/vhost.conf
echo www.example.com:hello world! > /data/web/html/index.html
配置访问不同路径的网页内容 vim /usr/local/nginx/conf.d/vhost.conf
echo test1:hello world! > /data/web/test1/index.html
vim /usr/local/nginx/conf.d/vhost.conf
echo web2/test/index.html > /data/web2/test/index.html
nginx -s reload
区分大小写 vim /usr/local/nginx/conf.d/vhost.conf
mkdir /data/web3/HTML
mkdir /data/web3/html
echo html/HTML > /data/web3/html/index.html
nginx -s reload
vim /usr/local/nginx/conf.d/vhost.conf
echo ~*:html/HTML > /data/web3/html/index.html
用户认证 htpasswd -cm /usr/local/nginx/.htpasswd admin
vim /usr/local/nginx/conf.d/vhost.conf
mkdir /data/web/gyj -p
echo bjh > /data/web/bjh/index.html
nginx -s reload
自定义错误页面
自定义错误日志 ll /usr/local/nginx/logs/
vim /usr/local/nginx/conf.d/vhost.conf
mkdir /var/log/example.org
cat /var/log/example.org/access.log
cat /var/log/example.org/error.log
检测文件是否存在
编辑配置文件 vim /usr/local/nginx/conf.d/vhost.conf
mkdir /data/web/html/error
echo error default > /data/web/html/error/default.html
curl www.example.com/123.html
nginx 的变量使用 上传 echo 模块的压缩包,查看已安装好的配置文件和模块:
[root@nginx ~]# nginx -V
nginx version: nginx/1.24.0 built by gcc 11.4.1 ...
configure arguments: --prefix=/usr/local/nginx ... --add-module=/root/echo-nginx-module-0.63
[root@nginx nginx-1.24.0]# ./configure --prefix=/usr/local/nginx --user=nginx --with-http_ssl_module ... --add-module=/root/echo-nginx-module-0.63
[root@nginx nginx-1.24.0]# make && make install
内置变量 [root@php ~]# vim /usr/local/nginx/conf.d/vhosts.conf
[root@php ~]# mkdir /data/web/html/var
[root@php ~]# echo /data/web/html/var > /data/web/html/var/index.html
[root@php ~]# curl www.example.com/var?name=test &&id =6666
自定义变量 假如需要自定义变量名称和值,使用指令 set variable value; 指定 key 并给其定义一个变量,变量可以调用 Nginx 内置变量赋值给 key,另外 set 定义格式为 set key value,value 可以是 text, variables 和两者的组合。
[root@php ~]# vim /usr/local/nginx/conf.d/vhosts.conf
[root@php ~]# curl www.example.com/var
nginx rewrite 的相关功能
rewrite 模块指令
if 指令
= # 比较变量和字符串是否相等,相等时 if 指令认为该条件为 true,反之为 false
!= # 比较变量和字符串是否不相等,不相等时 if 指令认为条件为 true,反之为 false
~ # 区分大小写字符,可以通过正则表达式匹配,满足匹配条件为真,不满足匹配条件为假
!~ # 区分大小写字符,判断是否匹配,不满足匹配条件为真,满足匹配条件为假
~* # 不区分大小写字符,可以通过正则表达式匹配,满足匹配条件为真,不满足匹配条件为假
!~* # 不区分大小字符,判断是否匹配,满足匹配条件为假,不满足匹配条件为真
-f 和 !-f # 判断请求的文件是否存在和是否不存在
-d 和 !-d # 判断请求的目录是否存在和是否不存在
-x 和 !-x # 判断文件是否可执行和是否不可执行
-e 和 !-e # 判断请求的文件或目录是否存在和是否不存在 (包括文件,目录,软链接)
注意:如果变量的值为空字符串或 0,则 if 指令认为该条件为 false,其他条件为 true。
[root@php ~]# vim /usr/local/nginx/conf.d/vhosts.conf
[root@php ~]# nginx -s reload
[root@php ~]# mkdir /data/web/html/{test1,test2}
[root@php ~]# echo /data/web/html/test1 > /data/web/html/test1/index.html
[root@php ~]# echo /data/web/html/test2 > /data/web/html/test2/index.html
rewrite 案例
. # 匹配除换行符以外的任意字符
\w # 匹配字母或数字或下划线或汉字
\s # 匹配任意的空白符
\d # 匹配数字
\b # 匹配单词的开始或结束
^ # 匹配字符串的开始
$ # 匹配字符串的结束
* # 匹配重复零次或更多次
+ # 匹配重复一次或更多次
? # 匹配重复零次或一次
(n) # 匹配重复 n 次
{n,} # 匹配重复 n 次或更多次
{n,m} # 匹配重复 n 到 m 次
*? # 匹配重复任意次,但尽可能少重复
+? # 匹配重复 1 次或更多次,但尽可能少重复
?? # 匹配重复 0 次或 1 次,但尽可能少重复
{n,m}? # 匹配重复 n 到 m 次,但尽可能少重复
{n,}? # 匹配重复 n 次以上,但尽可能少重复
\W # 匹配任意不是字母,数字,下划线,汉字的字符
\S # 匹配任意不是空白符的字符
\D # 匹配任意非数字的字符
\B # 匹配不是单词开头或结束的位置
[^x] # 匹配除了 x 以外的任意字符
[^lee] # 匹配除了 lee 这几个字母以外的任意字符
break 与 last break:用于中断当前相同作用域 (location) 中的其他 Nginx 配置。与该指令处于同一作用域的 Nginx 配置中,位于它前面的配置生效,位于后面的 ngx_http_rewrite_module 模块中指令就不再执行。Nginx 服务器在根据配置处理请求的过程中遇到该指令的时候,回到上一层作用域继续向下读取配置,该指令可以在 server 块和 location if 块中使用。
[root@php ~]# vim /usr/local/nginx/conf.d/vhosts.conf
[root@php ~]# nginx -s reload
[root@php ~]# mkdir /data/web/html/break
[root@php ~]# echo /data/web/html/break > /data/web/html/break/index.html
[root@php ~]# mkdir /data/web/html/last
[root@php ~]# echo /data/web/html/last > /data/web/html/last/index.html
自动跳转 https
判断文件是否存在
nginx 防盗链 准备一个 web 服务器(172.25.254.10),写入网站内容,在该站点盗取另一个(172.25.254.100)的图片资源。
<html >
<head >
<meta http-equiv =Content-Type content ="text/html;charset=utf-8" >
<title > 盗链</title >
</head >
<body >
<img src ="http://www.example.com/images/1.png" >
<h1 > 欢迎大家</h1 >
<p > <a href =http://www.example.com </a > 出门见喜</p >
</body >
</html >
在 172.25.254.100 的服务器的 images 文件夹内上传图片 1.png。
实现防盗链 在 100 服务器 http 的发布目录内上传盗链图片,意味着当其他站点盗链 1.png 时,会自动替换成盗链图片。
nginx 的反向代理
指定 location 实现反向代理(动静分离)
proxy_pass; # 用来设置将客户端请求转发给的后端服务器的主机,可以是主机名、IP 地址:端口的方式,也可以代理到预先设置的主机群组
proxy_pass_header field; # 透传,默认 nginx 在响应报文中不传递后端服务器的首部字段 Date, Server, X-Pad, X-Accel 等参数,如果要传递的话则要使用 proxy_pass_header field 声明
proxy_pass_request_body on | off; # 是否向后端服务器发送 HTTP 实体部分,默认即为开启
proxy_pass_request_headers on | off; # 是否将客户端的请求头部转发给后端服务器,默认即为开启
proxy_set_header; # 可更改或添加客户端的请求头部信息内容并转发至后端服务器
proxy_connect_timeout time; # 配置 nginx 服务器与后端服务器尝试建立连接的超时时间,默认为 60 秒
proxy_read_timeout time; # 配置 nginx 服务器向后端服务器或服务器组发起 read 请求后,等待的超时时间,默认 60s
proxy_send_timeout time; # 配置 nginx 项后端服务器或服务器组发起 write 请求后,等待的超时时间,默认 60s
proxy_http_version 1.0; # 用于设置 nginx 提供代理服务的 HTTP 协议的版本,默认 http 1.0
proxy_ignore_client_abort off; # 当客户端网络中断请求时,nginx 服务器中断其对后端服务器的请求,默认为 off
准备两台 webserver,172.25.254.10、172.25.254.20,在 10 上安装 php,并写入内容
在 20 上写入网站首页内容并修改端口为 8080:
echo static:172.25.254.20 > /var/www/html/static/index.html
vim /etc/httpd/conf/httpd.conf
反向代理的缓存功能 缓存配置:在 nginx 的总配置文件 http 块内
nginx 的负载均衡
实验环境 主机 IP nginx 172.25.254.100 apache(server) 172.25.254.10 apache1(server) 172.25.254.20
部署后端的两台 server
[root@apache20 ~]# yum install httpd -y
[root@apache20 ~]# echo "web1 172.25.254.10" > /var/www/html/index.html
[root@apache20 ~]# systemctl enable --now httpd
[root@apache30 ~]# yum install httpd -y
[root@apache30 ~]# echo "web2 172.25.254.20" >> /var/www/html/index.html
[root@apache30 ~]# systemctl enable --now httpd
[root@centos8 ~]# curl http://172.25.254.20
web1 172.25.254.10
[root@centos8 ~]# curl http://172.25.254.30
web2 172.25.254.20
基于 cookie 的会话绑定 检测:基于 cookie 值的变化而访问不同的服务器,cookie 值相同则访问相同服务器,实现会话绑定
实现 nginx 的四层负载均衡 [root@apache20 ~]# yum install mariadb-server -y
[root@apache20 ~]# vim /etc/my.cnf.d/mariadb-server.cnf
[root@server1 ~]# mysql -e "grant all on *.* to gyj@'%' identified by 'gyj';"
[root@server2 ~]# mysql -e "grant all on *.* to gyj@'%' identified by 'gyj';"
在两台 server 中开启 mysql,查看 server_id:
mysql -ugyj -pgyj -h 172.25.254.10 -e "select @@server_id"
vim /usr/local/nginx/conf.d/tcp.conf
mysql -u gyj -pgyj -h 172.25.254.100
一次登录为 server_id 为 10
二次登录为 20
dns 在后端两台 server 下载 dns,并且修改配置文件
vim /etc/named.conf
vim /etc/named.rfc1912.zones
配置 named.gaoyingjie.org 文件:
cd /var/named/
cp named.localhost named.gaoyingjie.org -p
vim named.gaoyingjie.org
将这台 10server 的配置文件远程复制到另一台 server20:
dig www.example.com 172.25.254.10
dig www.example.com 172.25.254.20
启动两台 server 的 dns,并且查看是否解析成功:
dig www.example.com 172.25.254.10
dig www.example.com 172.25.254.20
微信扫一扫,关注极客日志 微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
相关免费在线工具 Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
Markdown转HTML 将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
HTML转Markdown 将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
JSON 压缩 通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
JSON美化和格式化 将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online