《从 0 到 1:Nginx 入门、网络 I/O 模型与源码编译安装全指南》(1)

什么是Nginx?

Nginx官网:http://nginx.org

Nginx的功能

通过对nginx的功能进行介绍来介绍什么是nginx

1. Web 服务器(静态资源服务)

Nginx 最基础、最常用的功能。

  • 直接部署 HTML、CSS、JS、图片、视频等静态资源
  • 处理静态请求速度极快,远超传统服务器
  • 支持目录浏览、压缩、断点续传等

作用:做官网、博客、前端项目的直接入口。


2. 反向代理

这是 Nginx 最核心的能力之一。

  • 统一接收用户请求,转发给后端服务(Java、PHP、Python、Go 等)
  • 对用户隐藏后端真实地址,更安全
  • 统一入口,方便管理、扩容、维护

作用:前后端分离架构的 "大门"。


3. 负载均衡

当业务量大、后端有多台服务器时:

  • Nginx 把流量均匀分发到多台后端
  • 支持多种策略:轮询、加权轮询、IP 哈希、最少连接等
  • 某台挂了自动剔除,保证服务高可用

作用:扛高并发、防单点故障。


4. 动静分离

把请求分成两类处理:

  • 静态资源:直接由 Nginx 返回
  • 动态接口:转发给后端应用

作用:提升整体速度,减轻后端压力。


5. HTTPS / SSL 配置

  • 一键配置证书,实现 https 访问
  • 支持 HTTP/2、HTTP/3 加速
  • 支持证书自动续期、安全优化

作用:网站加密、更安全、SEO 更友好。


6. 缓存加速

  • 对后端接口、页面做本地缓存
  • 减少重复请求,大幅提升响应速度
  • 可自定义缓存时间、缓存规则

作用:高并发场景下的 "提速神器"。


7. 限流、防盗链、安全控制

  • 限制单位时间内的请求数(防刷、防攻击)
  • 限制并发连接
  • 防盗链、黑白名单、跨域配置
  • 屏蔽恶意 IP、过滤异常请求

作用:保护服务器,提升稳定性与安全性。


8. 灰度发布 / 流量切分

  • 按比例把流量分到不同版本服务
  • 不中断服务,平滑升级、回滚
  • 适合线上无感知更新

作用:现代微服务、持续部署必备。


9. 高可用与热部署

  • 支持 master-worker 多进程模型
  • 配置文件热加载,不中断业务
  • 配合 Keepalived 实现双机高可用

作用:保证服务 7×24 小时稳定运行。

Nginx的进程与架构

Nginx的高并发不仅得益于他的进程架构还有每个woker进程采用的I/O模型epoll实现单个子进程处理高并发请求。

Nginx是多进程组织模型,而且是一个由Master主进程和Worker工作进程组成。

主进程(master process)的功能:

  • 对外接口:接收外部的操作(信号)
  • 对内转发:根据外部的操作的不同,通过信号管理 Worker
  • 监控:监控 worker 进程的运行状态,worker 进程异常终止后,自动重启 worker 进程
  • 读取Nginx 配置文件并验证其有效性和正确性
  • 建立、绑定和关闭socket连接
  • 按照配置生成、管理和结束工作进程
  • 接受外界指令,比如重启、升级及退出服务器等指令
  • 不中断服务,实现平滑升级,重启服务并应用新的配置
  • 开启日志文件,获取文件描述符
  • 不中断服务,实现平滑升级,升级失败进行回滚处理
  • 编译和处理perl脚本

工作进程(worker process)的功能:

  • 所有 Worker 进程都是平等的
  • 实际处理:网络请求,由 Worker 进程处理
  • Worker进程数量:一般设置为核心数,充分利用CPU资源,同时避免进程数量过多,导致进程竞争 CPU资源
  • 增加上下文切换的损耗
  • 接受处理客户的请求
  • 将请求依次送入各个功能模块进行处理
  • I/O调用,获取响应数据
  • 与后端服务器通信,接收后端服务器的处理结果
  • 缓存数据,访问缓存索引,查询和调用缓存数据
  • 发送请求结果,响应客户的请求
  • 接收主程序指令,比如重启、升级和退出等

Nginx模块介绍

nginx 有多种模块

  • 核心模块:是 Nginx 服务器正常运行必不可少的模块,提供错误日志记录 、配置文件解析 、事件 驱动机制 、进程管理等核心功能
  • 标准HTTP模块:提供 HTTP 协议解析相关的功能,比如: 端口配置 、 网页编码设置 、 HTTP响应头设置 等等
  • 可选HTTP模块:主要用于扩展标准的 HTTP 功能,让 Nginx 能处理一些特殊的服务,比如: Flash 多媒体传输 、解析 GeoIP 请求、 网络传输压缩 、 安全协议 SSL 支持等
  • 邮件服务模块:主要用于支持 Nginx 的 邮件服务 ,包括对 POP3 协议、 IMAP 协议和 SMTP协议的支持
  • Stream服务模块: 实现反向代理功能,包括TCP协议代理
  • 第三方模块:是为了扩展 Nginx 服务器应用,完成开发者自定义功能,比如: Json 支持、 Lua 支持等

网络I/O模型

在了解模型之前先了解网络I/O的处理过程

网络I/O 处理过程

  • 获取请求数据,客户端与服务器建立连接发出请求,服务器接受请求(1-3)
  • 构建响应,当服务器接收完请求,并在用户空间处理客户端的请求,直到构建响应完成(4)
  • 返回数据,服务器将已构建好的响应再通过内核空间的网络 I/O 发还给客户端(5-7)

不论磁盘和网络I/O

I/O 统一分为两个阶段:

阶段 1:等待数据就绪(内核等待网络包)

阶段 2:数据从内核 → 用户空间(拷贝)

一次网络 I/O,本质分两步:数据从网络到内核(等待就绪)、数据从内核到用户进程(拷贝)。不同 I/O 模型,只是这两步的等待 / 通知方式不同。

同步与异步

同步/异步:关注的是消息通信机制,即调用者在等待一件事情的处理结果时,被调用者是否提供完成状 态的通知。

  • 同步:synchronous,被调用者并不提供事件的处理结果相关的通知消息,需要调用者主动询问事 情是否处理完成
  • 异步:asynchronous,被调用者通过状态、通知或回调机制主动通知调用者被调用者的运行状态

阻塞与非阻塞

阻塞/非阻塞:关注调用者在等待结果返回之前所处的状态

  • 阻塞:blocking,指IO操作需要彻底完成后才返回到用户空间,调用结果返回之前,调用者被挂 起,干不了别的事情。
  • 非阻塞:nonblocking,指IO操作被调用后立即返回给用户一个状态值,而无需等到IO操作彻底完 成,在最终的调用结果返回之前,调用者不会被挂起,可以去做别的事情。

网络I/O模型有五种,五种都是基于阻塞/非阻塞与同步/异步实现;

阻塞型、非阻塞型、复用型、信号驱动型、异步;

阻塞 I/O(Blocking I/O)

原理

调用 read/recv 后进程挂起,等内核数据就绪 + 拷贝完成才返回,全程阻塞。

大白话解读

"一件事没干完,啥也不干就死等"。进程发起 I/O 请求后,就暂停干活,直到数据准备好、拷贝完,才继续执行。

生活情景(点餐)

你去奶茶店点单,下单后站在柜台前一动不动,既不玩手机也不逛店,就等店员做好奶茶、递给你,全程盯着,啥别的事都不干。

优点

  • 编程最简单,写代码不用考虑 "等不等" 的问题
  • 系统开销小,不用频繁切换任务

缺点

  • 效率极低,单线程只能处理一个请求(比如一个店员只能服务一个死等的顾客)
  • 并发差,想服务多人就得雇很多店员(多进程 / 多线程),成本高

典型软件

早期 telnet、简单 echo 服务器、新手写的小脚本

非阻塞 I/O(Non-blocking I/O)

原理

socket 设 O_NONBLOCK,调用 read 时数据未就绪就立刻返回 "没好",进程需反复问(轮询)。

大白话解读

"不等,但会反复问"。进程发起 I/O 后,内核说 "没好" 就立刻走,过一会儿又回来问 "好了没?",循环往复,直到数据就绪才拷贝。

生活情景(取快递)

你想拿快递,到驿站门口问 "我的快递到了吗?",驿站说 "没到",你不傻等,转头去旁边便利店买水,2 分钟后又回来问,5 分钟后再问...... 直到问到 "到了",才拿快递。

优点

  • 不会卡在一个 I/O 上,单线程能兼顾多个请求
  • 不用一直挂起,能抽空做别的事

缺点

  • 反复 "问"(轮询)特别耗精力(CPU),空转严重
  • 高并发时越问越慢,纯属 "瞎忙活"

典型软件

极少直接用,仅作为 I/O 多路复用的基础、简单实时小工具

I/O 多路复用(I/O Multiplexing)

原理

select/poll/epoll 阻塞等待多个 fd 就绪,内核通知 "哪些好了",再逐个处理拷贝。

特性 select poll epoll
最大连接数 有限(默认 1024) 无上限 无上限
遍历方式 全量遍历 O (n) 全量遍历 O (n) 回调就绪 O (1)
用户态→内核态拷贝 每次都全量拷贝 每次都全量拷贝 仅注册时拷贝,mmap 共享
触发模式 仅水平触发 LT 仅水平触发 LT LT + ET(边缘触发)
性能(高并发) 极高
跨平台 最好(全平台) 较好(类 Unix) Linux 专用
典型使用 老旧程序、简单场景 几乎不用 Nginx/Redis/ 高并发服务器标配

大白话解读

"找个专人盯着所有事,谁好就处理谁"。进程不直接问每个 I/O,而是交给 "监工"(epoll/select),监工盯着所有请求,哪个数据就绪了,就告诉进程 "这个好了,快去处理",进程只处理就绪的,其余继续让监工盯着。

生活情景(餐厅点餐)

餐厅老板(进程)不亲自盯每桌客人,雇了个大堂经理(epoll)。经理盯着所有桌:

  1. A 桌喊 "要下单"(数据就绪),经理立刻告诉老板;
  2. 老板去给 A 桌下单(拷贝数据),同时经理继续盯 B/C/D 桌;
  3. B 桌喊 "要结账",经理再通知老板,全程老板只处理 "有需求" 的桌。

优点

  • 单线程能管上千上万个请求(解决 C10K 问题)
  • 不用反复轮询,CPU 开销极低
  • Linux 下 epoll 是高性能网络的 "标配"

缺点

  • 编程比阻塞 I/O 复杂一点
  • 仍是同步 I/O:拷贝数据时还是会短暂阻塞(但已经很快了)

典型软件

Nginx、Redis、Memcached、HAProxy、Go 网络底层、Java Netty

信号驱动 I/O(Signal-Driven I/O)

原理

进程注册信号处理函数,数据就绪时内核发 SIGIO 信号通知,进程再去拷贝数据。

大白话解读

"留个联系方式,好了叫我"。进程发起 I/O 后,告诉内核 "数据好了给我发个短信(信号)",然后去干别的;内核数据就绪后,发信号通知进程,进程收到信号再去拷贝数据。

生活情景(取外卖)

你点了外卖,告诉骑手 "送到楼下给我打个电话(信号)",然后你在家追剧(干别的);骑手到楼下打电话,你接完电话,下楼取外卖(拷贝数据)。

优点

  • 不用等、不用反复问,CPU 利用率高
  • 单线程能处理多个请求

缺点

  • "短信(信号)" 可能丢、可能乱序(比如同时收到 10 个信号,分不清先后)
  • 高并发时容易出问题,调试难
  • 不如 epoll 稳定好用
  • 且在处理其他事(追剧),如果信号(短信)到了会中断手头的事(追加)

典型软件

极少用于生产环境,仅简单嵌入式、小众实时场景

异步 I/O(Asynchronous I/O,AIO)

原理

调用 aio_read 后立刻返回,内核全程包办 "等数据 + 拷贝数据",完成后通知进程。

大白话解读

"全包给别人,完事通知我"。进程发起 I/O 后,啥都不管了,内核自己等数据、自己把数据拷贝到进程内存里,全部搞定后,告诉进程 "活干完了,你用数据吧",全程进程不阻塞、不干活。

生活情景(寄快递)

你要寄快递,叫了顺丰的 "上门取件 + 打包 + 发货" 全包服务:

  1. 你打个电话(发起 I/O),挂了就去上班(干别的);
  2. 快递员自己上门取件、打包、送到快递站(内核等数据 + 拷贝数据);
  3. 顺丰 App 给你发消息 "快递已发出"(内核通知),你只用看结果就行,全程没管过快递的事。

优点

  • 全程不阻塞,I/O 和计算完全不冲突,效率理论最高
  • 真正的 "异步",并发能力拉满

缺点

  • 编程模型复杂,写代码、调试都难
  • Linux 原生 AIO 生态不如 epoll 成熟
  • 网络场景用得少,主要用于磁盘 I/O

典型软件

MySQL InnoDB 异步磁盘 I/O、高性能文件存储系统、Windows IOCP(等价思想)

五种IO对比

模型 等待就绪 数据拷贝 同步 / 异步 单线程并发能力 CPU 开销 特点
阻塞 I/O 阻塞 阻塞 同步 极低 全程阻塞
非阻塞 I/O 立即返回(需轮询) 阻塞 同步 极高 轮询耗 CPU
I/O 多路复用 阻塞在多路函数 阻塞 同步 极高(epoll) 高并发首选
信号驱动 I/O 不阻塞,信号通知 阻塞 同步 信号易出问题
异步 I/O(AIO) 不阻塞 不阻塞(内核完成) 异步 极高 最低 全程不阻塞、最省心

Nginx源码编译安装

Nginx安装可以使用dnf或源码安装,但是推荐使用源码编译安装

  • dnf的版本比较旧
  • 编译安装可以更方便自定义相关路径
  • 使用源码编译可以自定义相关功能,更方便业务的上的使用

1.下载源码软件

bash 复制代码
[root@nginx ~]# wget https://nginx.org/download/nginx-1.28.1.tar.gz

2.解压

bash 复制代码
[root@nginx ~]# tar zxf nginx-1.28.1.tar.gz
[root@nginx ~]# cd nginx-1.28.1/
[root@nginx nginx-1.28.1]# ls
auto     CHANGES.ru          conf       contrib          html     man        SECURITY.md
CHANGES  CODE_OF_CONDUCT.md  configure  CONTRIBUTING.md  LICENSE  README.md  src

3.检测环境生成Makefile

bash 复制代码
pcre-devel		#正则表达式开发库
openssl-devel	#ssl开发库  
zlib-devel		#数据压缩库
#在编译过程会报出缺少依赖,根据提示安装需要的依赖
[root@nginx ~]# dnf install gcc pcre-devel zlib-devel openssl-devel -y

#选择要添加使用的模块
[root@nginx nginx-1.28.1]# ./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

4.编译

  • make 编译源码,生成目标文件在源码编译目录内
  • make install 复制文件到系统目录,完成安装
bash 复制代码
[root@nginx nginx-1.28.1]# make
[root@nginx nginx-1.28.1]# make install

补充

在编译安装前把debug下面那行注释了可以使编译出来的nginx更小

复制代码
[root@nginx nginx-1.28.1]# vim auto/cc/gcc
bash 复制代码
#编译完成后查看大小,原来5.5M左右
[root@nginx objs]# du -sh nginx
1.3M    nginx

5.启动nginx

创建运行用户

bash 复制代码
[root@nginx]# useradd  -s /sbin/nologin -M nginx

设定环境变量

bash 复制代码
[root@nginx sbin]# vim  ~/.bash_profile
export PATH=$PATH:/usr/local/nginx/sbin

[root@nginx sbin]# source   ~/.bash_profile

启动并测试

bash 复制代码
[root@nginx ~]# nginx
[root@nginx ~]# ps aux | grep nginx
root        9908  0.0  0.0  11148  2072 ?        Ss   13:42   0:00 nginx: master process ./nginx
nginx       9909  0.0  0.1  15424  5400 ?        S    13:42   0:00 nginx: worker process
root        9996  0.0  0.0   6636  2176 pts/0    S+   14:37   0:00 grep --color=auto nginx

[root@nginx ~]# echo fjwyyy > /usr/local/nginx/html/index.html
[root@nginx ~]# curl 172.25.254.100
fjwyyy
相关推荐
乘云数字DATABUFF1 天前
5分钟部署开源APM Databuff:OpenTelemetry全链路追踪入门实战
运维·后端
荣--3 天前
一键部署不是为了省时间 —— 它是把"买来的 PaaS"变成"自己的平台"的拐点
运维·zabbix·工程化·一键部署·平台化·边界设计
江华森3 天前
动手实战学 Docker — 从零到集群编排完全指南
运维
Avan_菜菜4 天前
FRP 内网穿透完整实战:从 HTTP 映射到 HTTPS 自签代理
运维·nginx·https
SelectDB5 天前
Litefuse 开源并推出单进程轻量模式,25 秒就能跑起来的 Agent 可观测与评估平台
运维·后端·自动化运维
XIAOHEZIcode6 天前
Linux系统鼠标偏移常见原因以及修复方案
linux·运维·游戏
用户0328472220707 天前
如何搭建本地yum源(上)
运维
ping某8 天前
为什么 Nginx 明明监听了 80,转发后端时却用了 4xxxx 端口?
后端·nginx
大树8810 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠10 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql