Web 服务与 I/O 模型

一、Web 服务介绍

1.1.1 Apache prefork 模型(预派生模式)

  • 核心机制:主控制进程派生多个独立子进程,使用select模型,最大并发 1024;每个子进程单线程响应用户请求
  • 资源特性:占用内存较多,但稳定性极高
  • 配置特点:可设置进程数的最大值和最小值
  • 适用场景:访问量中等的场景
  • 优缺点
    • ✅ 优点:极致稳定,故障隔离性好
    • ❌ 缺点:每个请求对应一个进程,资源占用高,并发能力弱,不适合高并发场景
1.1.2 Apache worker 模型(多进程 + 多线程混合模式)
  • 核心机制:主进程启动多个子进程,每个子进程包含固定线程数;线程处理请求,线程不足时新建子进程补充
  • 资源特性:相比 prefork 内存占用更少,支持更高并发
  • 优缺点
    • ✅ 优点:内存占用低,可处理更多请求
    • ❌ 缺点:长连接(keepalive)会长期占用线程,高并发下易出现无可用线程的情况(prefork 也存在此问题)
1.1.3 Apache event 模型(事件驱动模型)
  • 核心机制:2012 年 Apache 2.4.X 正式支持,基于epoll事件驱动;每个进程响应多个请求,专门线程管理 keepalive 连接
  • 核心优化:解决 keepalive 连接空占线程的问题,有真实请求时才分配服务线程,执行完立即释放
  • 优缺点
    • ✅ 优点:单线程响应多请求,内存占用少,高并发表现优秀
    • ❌ 缺点:无线程安全控制

1.2 Nginx - 高性能的 Web 服务端

1.2.1 Nginx 简介
  • 开发者:伊戈尔・赛索耶夫(俄罗斯),为Rambler.ru搜索引擎开发
  • 开发历程:2002 年启动开发,2004 年 10 月发布 0.1.0 版本;2019 年被 F5 以 6.7 亿美元收购
  • 核心代码:核心模块代码约 19.8 万行,按收购价折算约 2.2 万人民币 / 行
  • 官方地址:https://nginx.org
  • 版本类型:开发版、稳定版、过期版
  • 应用场景:天猫、淘宝、京东、小米、网易、新浪等一线互联网公司均使用或二次开发
1.2.2 Nginx 核心特性
  • 支持 HTTP 服务器、反向代理、邮件服务器
  • 快速响应静态网页请求
  • 支持 FastCGI/SSL/Virtual Host/URL Rewrite/Gzip/HTTP Basic Auth
  • 1.9 版本以上开启 stream 模块可支持 TCP/UDP 负载均衡
  • 支持第三方功能扩展

二、服务端 I/O 流程

2.1 基本概念

  • I/O:Input/Output(输入 / 输出)
  • IOPS:每秒输入输出量,衡量磁盘性能的核心指标,指单位时间内系统处理的 I/O 请求数(读 / 写)
  • 完整 I/O 过程:用户空间进程与内核空间数据的交换,需将内核内存数据拷贝到用户进程内存(内核与用户空间严格隔离,无法直接访问)

2.2 服务器 I/O 类型

2.2.1 磁盘 I/O
  • 进程向内核发起系统调用,请求磁盘资源(如 HTML、图片)
  • 内核通过驱动将文件加载到内核内存空间,再拷贝到进程内存
  • 大文件加载需等待较长时间
2.2.2 网络 I/O
  • 本质:对 socket 文件的读写(一切皆文件)
  • 核心:网络协议栈与用户空间进程的数据交换

2.3 I/O 通用流程(磁盘 / 网络均适用)

  1. 数据准备阶段:将数据从文件加载到内核内存缓冲区,耗时较长
  2. 数据拷贝阶段:将数据从内核缓冲区拷贝到用户进程内存,耗时较短

三、I/O 模型核心概念

3.1 同步 / 异步(消息通信机制)

  • 同步(synchronous):被调用者不主动通知处理结果,需调用者主动查询
  • 异步(asynchronous):被调用者通过状态、通知或回调主动告知调用者运行状态

3.2 阻塞 / 非阻塞(等待结果时的状态)

  • 阻塞(blocking):IO 操作完全完成后才返回用户空间,调用者挂起,无法执行其他操作
  • 非阻塞(nonblocking):IO 操作调用后立即返回状态值,无需等待完成,调用者不挂起,可执行其他操作

四、网络 I/O 模型

4.1 阻塞型 I/O 模型(blocking IO)

  • 核心流程
    1. 用户线程通过read系统调用发起 I/O 读操作,从用户态切换到内核态
    2. 内核等待数据包到达后,将数据拷贝到用户空间
    3. 用户线程需等待read完成后才能处理数据
  • 核心特征:用户线程全程阻塞,CPU 利用率低
  • 优缺点
    • ✅ 优点:程序简单,阻塞期间进程 / 线程挂起,基本不占用 CPU
    • ❌ 缺点:每个连接需独立进程 / 线程,高并发时内存、线程切换开销大
  • 应用场景:Apache prefork 模式

4.2 非阻塞型 I/O 模型(nonblocking IO)

  • 核心流程
    1. 用户线程发起 IO 请求后立即返回(无数据)
    2. 用户线程需不断轮询发起 IO 请求,直到数据到达后读取
  • 核心问题
    • 大量文件描述符需逐个轮询,上下文切换频繁
    • 轮询时间难把控(过长响应慢,过短耗 CPU)
  • 优缺点
    • ✅ 优点:调用者不阻塞,可执行其他操作
    • ❌ 缺点:轮询耗 CPU,实际极少单独使用
  • 核心机制:无数据时内核返回EWOULDBLOCK错误,数据就绪后拷贝到进程缓冲区

4.3 信号驱动式 I/O 模型(signal-driven IO)

  • 核心流程
    1. 通过sigaction系统调用注册信号处理回调函数,调用立即返回,主程序继续执行
    2. 内核数据就绪时发送SIGIO信号,触发回调函数
    3. 回调函数中调用recvfrom将数据从内核拷贝到用户空间
  • 优缺点
    • ✅ 优点:等待数据时进程不阻塞,资源利用率高
    • ❌ 缺点:大量 IO 操作时可能因信号队列溢出导致通知失效

4.4 异步 I/O 模型(asynchronous IO)

  • 核心区别:信号驱动是通知 “开始 IO”,异步 IO 是通知 “IO 完成”
  • 核心流程
    1. 用户进程调用aio_read后立即返回,可执行其他操作
    2. 内核完成数据准备 + 拷贝后,主动通知用户进程
  • 核心特征:IO 两个阶段(准备 + 拷贝)进程均非阻塞
  • 优缺点
    • ✅ 优点:充分利用 DMA 特性,IO 与计算重叠
    • ❌ 缺点:操作系统实现复杂;Linux 2.6 才引入,AIO 不完善(常用 libevent/libev/libuv 等开源库)
  • 应用场景:异步非阻塞是最常用的通信方式(进程和内核均不阻塞,相互不影响)

4.5 多路复用 I/O 模型(I/O multiplexing)

4.5.1 核心原理
  • 单个线程监控 / 处理多个文件描述符的 IO(复用线程)
  • 通过内核的select/poll/epoll系统调用实现
  • 内核轮询监控所有注册的 socket,数据就绪时通知用户进程
4.5.2 核心流程
  1. 用户将 IO 操作注册到select,等待其返回
  2. 数据就绪后select返回,用户线程调用read读取数据
  3. 阻塞发生在select调用上,而非实际 IO 操作
4.5.3 关键说明
  • Apache prefork 用select,worker 用poll
  • NIO(非阻塞 IO)需与 IO 多路复用配合才有实际意义(仅用多路复用 + BIO 仍会阻塞)
  • 虽阻塞在select,但可同时监控多个 IO,相比单线程单 IO 更高效
4.5.4 优缺点
  • ✅ 优点:基于一个阻塞对象监控多个描述符,节省系统资源
  • ❌ 缺点:连接数少时效率低于 “多线程 + 阻塞 IO”,单个连接需 2 次系统调用
4.5.5 适用场景
  • 客户端处理多个描述符(交互式输入 + 网络套接字)
  • 客户端同时处理多个套接字
  • 服务器同时处理监听套接字 + 已连接套接字
  • 服务器同时处理 TCP+UDP
  • 服务器处理多服务 / 多协议

4.6 五种 I/O 模型对比

模型类型阻塞特性同步 / 异步核心特点
阻塞 IO全程阻塞同步简单但并发差
非阻塞 IO非阻塞(轮询)同步耗 CPU,极少单独使用
信号驱动 IO等待非阻塞同步信号队列易溢出
异步 IO全程非阻塞异步性能最优,实现复杂
多路复用 IO阻塞在 select同步高并发主流方案,异步阻塞
注:前四种均为同步 IO(recvfrom会阻塞),仅异步 IO 符合 POSIX 异步定义

五、零拷贝

5.1 传统 Linux I/O 问题

  • 标准 IO 接口(read/write)基于数据拷贝,频繁的用户态 / 内核态切换 + 数据拷贝消耗大量 CPU
  • 数据拷贝时间占数据包处理总时间的 57.1%

5.2 零拷贝核心思想

  • 并非真正 “0 拷贝”,而是通过优化减少拷贝操作,降低 CPU 压力
  • 核心技术:MMAP(内存映射)、SENDMSG/SENDFILE

5.3 MMAP(Memory Mapping)

  • 原理:将文件磁盘地址与进程虚拟地址空间映射,进程可直接操作内存(无需 read/write)
  • 优势:减少内核态→用户态的一次拷贝(传统 read 需拷贝,MMAP 直接访问页缓存)
  • 适用场景:大量数据传输

六、Nginx 实战操作

6.1 Nginx 源码编译安装

6.1.1 下载解压

# 下载软件包 [root@Nginx ~]# wget https://nginx.org/download/nginx-1.28.1.tar.gz ​ # 解压 [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

6.1.2 环境准备与配置

# 安装依赖 [root@Nginx ~]# dnf install gcc openssl-devel.x86_64 pcre2-devel.x86_64 zlib-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

6.1.3 编译安装

# 编译 [root@Nginx nginx-1.28.1]# make ​ # 安装 [root@Nginx nginx-1.28.1]# make install

6.1.4 启动配置

# 设置环境变量 [root@Nginx sbin]# vim ~/.bash_profile export PATH=$PATH:/usr/local/nginx/sbin # 添加此行 [root@Nginx sbin]# source ~/.bash_profile # 生效 ​ # 创建nginx用户 [root@Nginx logs]# useradd -s /sbin/nologin -M nginx ​ # 启动nginx [root@Nginx logs]# nginx ​ # 验证启动 [root@Nginx logs]# ps aux | grep nginx root       44012 0.0 0.1 14688 2356 ?       Ss   17:01   0:00 nginx: master process nginx nginx     44013 0.0 0.2 14888 3892 ?       S   17:01   0:00 nginx: worker process ​ # 测试访问 [root@Nginx logs]# echo timinglee > /usr/local/nginx/html/index.html [root@Nginx logs]# curl 172.25.254.100 # 预期输出:timinglee

6.1.5 编写 systemd 启动文件

[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 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 enable --now nginx ​ # 验证状态 [root@Nginx ~]# systemctl status nginx.service

6.2 Nginx 平滑升级及回滚

6.2.1 下载高版本并编译

# 下载高版本 [root@Nginx ~]# wget https://nginx.org/download/nginx-1.29.4.tar.gz ​ # 解压并修改版本信息(隐藏版本) [root@Nginx ~]# tar zxf nginx-1.29.4.tar.gz [root@Nginx ~]# cd nginx-1.29.4/src/core/ [root@Nginx core]# vim nginx.h #define nginx_version     1029004 #define NGINX_VERSION     "" #define NGINX_VER         "TIMINGLEE/" NGINX_VERSION ​ # 编译(参数与旧版本一致) [root@Nginx core]# cd ../../ [root@Nginx nginx-1.29.4]# ./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.29.4]# make # 仅编译,不安装

6.2.2 平滑升级

# 替换二进制文件 [root@Nginx nginx-1.29.4]# cd objs/ [root@Nginx objs]# \cp -f nginx /usr/local/nginx/sbin/nginx ​ # 查看旧master进程ID [root@Nginx sbin]# ps aux | grep nginx root       1643 0.0 0.1 14688 2360 ?       Ss   09:55   0:00 nginx: master process /usr/local/nginx/sbin/nginx ​ # 发送USR2信号启动新master进程 [root@Nginx sbin]# kill -USR2 1643 ​ # 验证双master进程 [root@Nginx sbin]# ps aux | grep nginx root       1643 0.0 0.1 14688 2744 ?       Ss   09:55   0:00 nginx: master process /usr/local/nginx/sbin/nginx nginx       1644 0.0 0.2 14888 3896 ?       S   09:55   0:00 nginx: worker process root       4919 0.0 0.4 14716 7936 ?       S   10:24   0:00 nginx: master process /usr/local/nginx/sbin/nginx nginx       4921 0.0 0.2 14916 4156 ?       S   10:24   0:00 nginx: worker process ​ # 验证版本 [root@Nginx sbin]# nginx -V nginx version: TIMINGLEE/ # 已升级为新版本 ​ # 回收旧版本worker进程 [root@Nginx sbin]# kill -WINCH 1643

6.2.3 版本回滚

# 备份新版本二进制文件 [root@Nginx sbin]# cp nginx nginx.new -p ​ # 恢复旧版本二进制文件(需提前备份) [root@Nginx sbin]# \cp nginx.old nginx -pf ​ # 发送HUP信号重启旧master进程 [root@Nginx sbin]# kill -HUP 1643 ​ # 验证回滚结果 [root@Nginx sbin]# nginx -V nginx version: nginx/1.28.1 # 回滚至旧版本 ​ # 回收新版本master进程 [root@Nginx sbin]# kill -WINCH 4919

6.3 Nginx 配置优化

6.3.1 基础用户配置

[root@Nginx ~]# vim /usr/local/nginx/conf/nginx.conf user nginx; # 指定运行用户 ​ # 验证配置并重载 [root@Nginx ~]# nginx -t [root@Nginx ~]# nginx -s reload

6.3.2 工作进程优化

# 手动设置进程数 [root@Nginx ~]# vim /usr/local/nginx/conf/nginx.conf worker_processes 2; # 设置2个工作进程 [root@Nginx ~]# nginx -s reload ​ # 自动适配CPU(推荐) [root@Nginx ~]# vim /usr/local/nginx/conf/nginx.conf worker_processes auto; # 自动匹配CPU核心数 worker_cpu_affinity 0001 0010 0100 1000; # 进程绑定CPU核心(4核心示例) ​ # 验证绑定结果 [root@Nginx ~]# ps axo pid,cmd,psr | grep nginx   887 nginx: master process /usr/   3   1635 nginx: worker process         0   1636 nginx: worker process         1   1637 nginx: worker process         2   1638 nginx: worker process         3

6.3.3 事件模块优化

[root@Nginx ~]# vim /usr/local/nginx/conf/nginx.conf events {   worker_connections 10000; # 单个进程最大连接数   use epoll; # 使用epoll事件模型   accept_mutex on; # 防止惊群效应   multi_accept on; # 一次性接受所有新连接 } [root@Nginx ~]# nginx -s reload

6.3.4 系统文件句柄限制(解决高并发报错)

# 报错场景:ab测试时提示 "socket: Too many open files (24)" [root@Nginx ~]# ab -n 100000 -c5000 http://172.25.254.100/index.html ​ # 修改系统限制 [root@Nginx ~]# vim /etc/security/limits.conf *               -       nofile         100000 # 所有用户最大文件句柄数 *               -       noproc         100000 # 所有用户最大进程数 root           -       nofile         100000 # root用户单独设置 ​ # 验证生效 [root@Nginx ~]# sudo -u nginx ulimit -n 100000 ​ # 重新测试高并发 [root@Nginx ~]# ab -n 100000 -c10000 http://172.25.254.100/index.html


总结

  1. Web 服务核心:Apache 稳定但并发弱(prefork/worker/event 三种模型),Nginx 高性能高并发,是互联网场景首选。
  2. I/O 模型关键:同步 / 异步关注 “通知机制”,阻塞 / 非阻塞关注 “等待状态”;多路复用(epoll)是高并发主流方案,异步 IO 性能最优但实现复杂。
  3. Nginx 实战重点:源码编译需匹配依赖,平滑升级通过信号(USR2/WINCH)实现无停机更新,配置优化核心是进程数、CPU 绑定、连接数和文件句柄限制。

Read more

【Linux网络系列】:JSON+HTTP,用C++手搓一个web计算器服务器!

【Linux网络系列】:JSON+HTTP,用C++手搓一个web计算器服务器!

🔥 本文专栏:Linux网络Linux实践系列 🌸作者主页:努力努力再努力wz 💪 今日博客励志语录:别害怕选错,人生最遗憾的从不是‘选错了’,而是‘我本可以’。每一次推倒重来的勇气,都是在给灵魂贴上更坚韧的勋章。 ★★★ 本文前置知识: 序列化与反序列化 引入 在之前的博客中,我详细介绍了序列化 与反序列化 的概念。对于使用 TCP 协议进行通信的双方,由于 TCP 是面向字节流的,在发送数据之前,我们通常需要定义一种结构化的数据来描述传输内容,并以此作为数据的容器。在 C++ 中,这种结构化数据通常表现为对象或结构体。然而,我们不能直接将结构体内存中对应的字节原样发送到另一端,因为直接传递内存字节会引发字节序 和结构体内存对齐 的问题。不同平台、不同编译器所遵循的内存对齐规则可能不同,这可能导致接收方在解析结构体字段时出现错误。 因此,我们需要借助序列化 。序列化 是指将结构化的数据按照预定的规则转换为连续的字节流。其主要目的是屏蔽平台差异,使得位于不同平台的进程能够以统一的方式解析该字节流。序列化通常分为两种形式:文本序列化 与二进制序列化 。 文

【2025最新】基于SpringBoot+Vue的web喀什旅游网站管理系统源码+MyBatis+MySQL

【2025最新】基于SpringBoot+Vue的web喀什旅游网站管理系统源码+MyBatis+MySQL

系统架构设计### 摘要 随着信息技术的快速发展,旅游业逐渐向数字化、智能化方向转型。喀什作为中国西部重要的旅游城市,拥有丰富的自然和人文资源,但传统旅游管理模式效率低下,难以满足游客个性化需求。基于此,开发一款高效、便捷的旅游网站管理系统成为提升喀什旅游服务质量的关键。该系统通过整合旅游资源信息、优化游客体验、提高管理效率,为游客提供一站式服务,同时为旅游管理者提供数据支持和决策依据。关键词:喀什旅游、数字化管理、旅游资源、游客体验、一站式服务。 该系统采用SpringBoot+Vue的前后端分离架构,结合MyBatis和MySQL数据库实现高效数据交互。前端使用Vue.js框架构建响应式用户界面,后端通过SpringBoot提供RESTful API接口,实现用户管理、景点信息展示、订单管理、评论互动等功能。系统支持多角色登录,包括游客、管理员和商家,确保数据安全性和操作便捷性。关键技术包括JWT认证、Redis缓存、阿里云OSS文件存储等,显著提升系统性能和用户体验。关键词:SpringBoot、Vue.js、MyBatis、MySQL、JWT认证、Redis缓存。

Linux网络 | 理解Web路径 以及 实现一个简单的helloworld网页

Linux网络 | 理解Web路径 以及 实现一个简单的helloworld网页

前言:本节内容承接上节课的http相关的概念, 主要是实现一个简单的接收http协议请求的服务。这个程序对于我们理解后面的http协议的格式,报头以及网络上的资源的理解, 以及本节web路径等等都有着重要作用。 可以说我们就用代码来理解这些东西。 那么废话不多说, 现在开始我们的学习吧。         ps:本节内容建议先看一下上一篇文章http的相关概念哦:linux网络 | 深度学习http的相关概念-ZEEKLOG博客 目录  准备文件  makefile HttpServer.hpp 类内成员 封装sockfd start  ThreadRun  全部代码 运行结果 响应书写 Web路径  准备文件         首先准备文件: 这里面Httpserver.cc用来运行接收http请求的服务。 HttpServer.hpp用来定义http请求。Log.hpp就是一个打印日志的小组件, Socket.hpp同样是套接字的组件。 到使用直接调用相关接口即可。(Log.hpp和Socket.hpp如何实现不讲解, 如果想要知道

WebRTC尝试实现实时双向语音合成与交互

WebRTC 与 IndexTTS 2.0 构建实时语音交互系统 在虚拟主播、AI陪聊和远程数字人日益普及的今天,用户不再满足于“能说话”的AI——他们期待的是会表达、有情绪、像真人一样即时回应的语音交互体验。然而,传统语音合成技术往往依赖批处理模式,生成延迟动辄秒级,难以支撑流畅对话;而即便能快速出声,声音也常常千篇一律,缺乏个性与情感变化。 这一瓶颈正在被打破。借助 WebRTC 提供的低延迟通信能力和 IndexTTS 2.0 的高质量零样本语音生成能力,我们完全可以构建一个“输入即发声”的实时双向语音通道。这种架构不仅能让AI以你熟悉的声音语调说话,还能根据情境切换喜怒哀乐,真正实现个性化、情感化、近实时的人机语音互动。 从一句话开始:当AI学会“即时反应” 设想这样一个场景:你在直播中向虚拟助手提问:“今天的热点新闻是什么?”几乎在问题结束的同时,一个熟悉的声音——也许是模仿你自己的音色——带着轻微的兴奋感回答道:“刚刚发布的报告显示,AI芯片性能提升了三倍!”整个过程自然得就像对面坐着一个人。