大家好,我是IT孟德,You can call me Aman(阿瞒,阿弥陀佛的ē,Not阿门的ā),一个喜欢所有对象(热爱技术)的男人。我正在创作架构专栏,秉承ITer开源精神分享给志同道合(爱江山爱技术更爱美人)的朋友。专栏更新不求速度但求质量(曹大诗人传世作品必属精品,请脑补一下《短歌行》:对酒当歌,红颜几何?譬如媳妇,吾不嫌多...青青罗裙,一见动心,但为佳人,挂念至今...),用朴实无华、通俗易懂的图文将十六载开发和架构实战经验娓娓道来,让读者茅塞顿开、相见恨晚...如有吹牛,不吝赐教。关注wx公众号:IT孟德,您的每一次点赞和转发都是我继续码字的动力!
专栏文章推荐:
1、前言
键盘敲击,丰富的图文信息眨眼间跨越山海;屏幕滑动,高清的视频影像弹指间穿越时空。这些习以为常的体验,都依托于高速稳定的网络通信。网络是互联网的物理基石与运行载体,它连接着用户终端与服务集群、串联起分布式节点与存储系统,其性能直接决定了系统的可用性、扩展性与业务承载能力。在用户耐心以秒计算的时代,网络传输效率直接影响用户体验,是开发者、架构师及运维团队必须深入钻研的课题。本文聚焦网络传输性能优化这一命题,从原理到实践详细阐述如何降低延迟,提升系统吞吐量。
2、网络协议
网络通信过程通常按照功能划分为多个逻辑层次,最常见的两种网络分层模型为OSI七层模型和TCP/IP四层网络模型。OSI七层模型是理想化的理论标准,分层清晰、逻辑严谨,常用于教学、协议设计和理解网络原理;TCP/IP四层模型是实战化的应用标准,简洁高效,直接支撑了互联网的运行,是实际网络中遵循的核心架构,也是目前最广泛使用的分层结构。网络分层中每一层负责不同的功能,并对应特定的协议。
层级 | 主要功能 | 常见协议 | 示例 |
应用层 (对应OSI 应用层+表示层+会话层) | 直接为应用程序提供网络服务,处理用户数据格式、加密解密、会话管理,并定义应用程序间的通信规则 | HTTP/HTTPS、FTP、 SMTP/POP3/IMAP、DNS、Telnet/SSH、DHCP、SNMP |
|
传输层 | 提供端到端的数据传输服务,确保数据可靠性(如顺序控制、错误重传)或高效传输,通过端口号标识不同应用 | TCP、UDP |
|
网络层 | 负责数据包的路由寻址和跨网络传输,通过IP地址定位设备,并处理分片、重组和逻辑寻址 | IP (IPv4, IPv6)、ICMP、IGMP、ARP |
|
网络接口层 (对应OSI 数据链路层+物理层) | 负责物理网络设备间的数据帧传输,包括错误检测(CRC校验)、物理寻址(MAC地址)和介质访问控制(如以太网冲突避免) | Ethernet、Wi-Fi (IEEE 802.11)、PPP、MAC、Bluetooth、ZigBee |
|
网络协议是计算机网络中设备之间进行数据通信时共同遵守的一套规则和标准。它通过语法、语义和时序三要素约定了数据格式、传输方式、纠错机制、同步方式等规则,确保不同厂商、不同型号的设备能够 “理解” 彼此发送的信息,实现有效通信。
-
语法:定义数据的格式和结构,比如HTTP协议规定请求头要包含Host、Content-Type等字段。
-
语义:规定数据字段的含义和操作,比如HTTP 200状态码表示成功、TCP中SYN表示建立连接。
-
时序:定义数据传输的顺序、速率匹配和时间限制,比如TCP三次握手、四次挥手。
如果把互联网应用里的用户请求比作取快递,小件自然比大件快;包裹多的时候,用小推车就能少跑几趟,耗时更少;而快递柜的流程比驿站简单,取件也更快。系统性能优化中,网络传输优化的精髓就在网络协议设计的游戏规则下,围绕数据量、交互次数和传输效率三个维度挖掘,最大限度地发挥现有网络协议的潜能,从而实现更高效、更低延迟的数据传输。
3、减少数据传输量
-
按需获取数据
当前主流的开发方式都是前后端分离,在国内前端React、Vue、Angular三大框架中Vue占绝对优势。Vue的特点是SPA-Single Page Application(单页应用程序),即只有第一次会加载页面,以后的每次页面切换,只需要进行组件替换。该模式整体上减少了请求体积,加快页面响应速度,但初始加载时会把所有的组件和相关资源一次性加载完成。比如很多网站的登录页面非常简洁,用户可见的只有输入账号密码、点击登录的交互。但背后却加载了大量无关资源,多余的资源占着茅坑不拉屎,造成页面初始化很慢。对组件进行切割,按需加载是解决该问题的根本。首先需要对页面代码进行拆分,剔除无效代码,将可以延迟加载的模块单独打包,通过import引用。然后将需要进行懒加载的子模块文件的引入语句(import引用)放到一个函数内部,在需要加载的时候再执行该函数,比如onclick、滑动至下一屏时触发,这样才真正实现按需加载/懒加载,提升页面初始化速度。
按需加载的策略同样适用于服务端,有些程序员同学贪图省事查询数据库喜欢“select *”,然后所有数据通过接口一把返回。比如查询订单列表返回了包括详情在内的text/blob大字段,不仅增加网络传输负担,还会增加服务器内存消耗和数据库IO操作,可能导致OOM或覆盖索引失效等问题。无论是数据库查询还是API设计,通过消除无效冗余和分页等方式减少非必要数据的传输和处理,在高并发场景和移动端弱网环境下效果非常显著。
-
简化数据格式
复杂数据格式常包含多余标识、重复字段等,会增大数据体积,占用更多带宽,还会延长解析时间,增加延迟。简化数据格式核心是为了减少冗余信息,提升传输效率。RPC通信通常使用protobuf、Hessian、Thrift等数据格式,通过二进制编码序列化后体积比Json小30%-50%,而json比xml少了大量标签,平衡性能和可读性,是Web API交互首选数据格式。
数据格式 | 序列化方式 | 数据大小 | 解析速度 | 可读性 | 跨语言 | 是否需要 IDL/ Schema | 典型应用场景 |
XML | 文本(标签嵌套) | 极大(冗余标签) | 极慢(DOM解析复杂) | 高(文本可读) | 高(主流语言支持) | 可选(XSD Schema) | 传统企业服务(SOAP)、需强结构校验的旧系统、部分配置文件(如 Spring XML) |
JSON | 文本(基于键值对) | 较大(需GZIP压缩) | 较慢 | 极高(文本可读) | 极高(全语言原生支持) | 否 | Web API、前后端交互 |
Protobuf | 二进制 | 极小 | 极快(编译优化) | 低 | 高(主流语言完善支持) | 是(需 .proto 文件) | 微服务通信、高并发RPC、物联网 |
Thrift | 二进制 | 较小(接近 Protobuf) | 快 | 低 | 高(多语言支持) | 是(需 .thrift 文件) | 多语言异构系统集成、自定义协议栈的分布式服务(如 Apache Thrift 框架) |
MessagePack | 二进制(兼容 JSON 结构) | 较小(无Schema冗余) | 快 | 低 | 高(主流语言库支持) | 否 | 兼容 JSON 语义的高性能场景(如移动端 API、Redis 数据存储) |
Avro | 二进制(Schema 分离) | 较小(Schema与数据分离) | 快 | 低 | 中高(Hadoop 生态为主) | 是(需 Avro Schema) | 大数据批处理(Hadoop/Spark)、Kafka 消息序列化 |
Hessian | 二进制(Java 对象优化) | 中等 | 中 | 低 | 中(主要支持 Java) | 否(依赖 Java 类反射) | Java 生态内部 RPC(如 Dubbo 早期版本、Java 微服务间通信) |
Kryo | 二进制(Java字节码生成) | 极小(Java 场景最优) | 极快 | 低 | 低(仅 Java 原生支持) | 否 | Java 单一生态高性能场景(如 Spark 内部 RDD 传输、游戏服务器进程间数据同步) |
-
压缩传输内容
对数据进行压缩后再传输可有效节省带宽,提升响应时间。压缩方式分为无损压缩和有损压损,无损压缩(如 gzip、Deflate、Br)适用于文本、代码等需完整还原的内容,通过算法消除重复数据,如用标记替代重复字符串;有损压缩(如 JPEG、H.265)用于音频、图像等,通过舍弃感官不敏感的信息,如图片中细微色差,大幅缩减体积。
HTTP可以通过请求头Acceppt-Encoding声明浏览器支持的压缩格式,Gzip有着非常高压缩率和优秀的兼容性,文本类数据(如 JSON、HTML)压缩率可达70%以上,大幅减少传输字节数。当前大部分项目前端采用主流vue框架开发,webpack打包时引用compression-webpack-plugin插件即可对符合条件的html、js、css等文件进行gz压缩。Vue代码片段如下:
configureWebpack: config => {
return {
plugins: [
new CompressionPlugin({
filename: '[path].gz[query]',
algorithm: 'gzip',
test: /\.js$|\.css$|\.html$/, //使用正则给匹配到的文件做压缩,jpg、png等图片无需压缩
threshold: 10240, //以字节为单位压缩超过此大小的文件,使用默认值10240
minRatio: 0.8, //最小压缩比率,官方默认0.8
deleteOriginalAssets: false
})
]
}
}
压缩的静态资源通常部署在web服务器中,只有nginx同步支持gzip,才能将资源压缩后传输到浏览器。Nginx配置示例如下:
# 开启gzip,关闭为off
gzip on;
# 是否在http header中添加Vary: Accept-Encoding,建议开启
gzip_vary on;
# gzip 压缩级别,1-9,数字越大压缩得越好,也越占用CPU时间,推荐6
gzip_comp_level 6;
# 设置压缩所需要的缓冲区大小
gzip_buffers 16 8k;
# 设置gzip压缩针对的HTTP协议版本
gzip_http_version 1.1;
# 选择压缩的文件类型,其值可以在 mime.types 文件中找到。
gzip_types text/plain text/css application/json application/javascript
# 启用gzip压缩的最小文件,小于设置值的文件将不会压缩
gzip_min_length 1k;
万事俱备,最后查看浏览器Response Headers中的Content-Encoding属性和被压缩文件的实际大小和传输大小验证压缩效果,下图可见静态资源压缩比例在4到10倍之间,大大节省了服务器的网络带宽,提升浏览器的加载速度。
chrome浏览器http响应示例
此外,图片在HTTP传输中占比很高,但它本身已经被压缩过了,不能被 gzip、br继续压缩。去除图片里的拍摄时间、地点、机型等元数据,降低分辨率,缩小尺寸、选择高压缩率的格式都是很好的优化手段,比如有损格式用Jpeg,无损格式用Webp格式。
4、减少交互次数
-
合并请求
合并请求的实现需结合业务场景平衡合并粒度与响应速度,核心思路是识别可合并的请求,设计批量处理机制,从而减少RTT(往返时间)累积,尤其是公网,RTT通常20-300ms,多次请求延迟叠加比较明显。
服务端可以将多个小请求合并为一个批量接口,比如社交APP首页加载关注列表+未读消息+ 推荐内容合并为一次请求,从而减少TCP连接建立、TLS握手、DNS解析等重复操作,同时还可以避免冗余头部传输,假设每个HTTP请求平均携带500B-1KB头部,高并发场景下节省的带宽开销还是非常可观的。
在客户端带宽资源有限的情况下,为了减少网络延迟和页面加载时间,通过合并css/js文件、CSS Sprites(雪碧图,即把一个页面涉及的所有零散小图有规则的合并成一张大图,然后通过CSS的background-image、background-repeat, background-position等属性实现图片显示)等方式减少HTTP请求次数可以有效节流,从而提升用户体验。
-
缓存
接口合并往往辅以客户端缓存。比如在线问卷系统为了使用户作答过程中刷新页面或退出返回能继续之前的进度,需要实时调用服务端接口保存作答记录。假设有20道题,一个用户需调用20次接口才能完成,50万用户光提交答案就得发起1000万次请求,加上实时获取已提交答案的接口,就是2000万。如此频繁的请求一方面加重了客户端请求网络开销,另一方面极大增加了服务端和数据库的并发压力。这种业务场景就特别适合借助客户端缓存合并接口,将用户每道题的答案缓存在客户端缓存中,刷新和重新进入答题交互直接从客户端缓存获取记录,避免实时请求接口获取最新作答记录,所有题本作答完成后一次性提交,因为题本和答案只用传输固定的编号,一次性传输的内容可控。且只要用户不进行非常规的清理客户端缓存动作,在网络堵塞时还可以通过重试的机制确保答案提交成功。
chrome浏览器local storage示例
5、简化交互流程
-
选择合适的协议
不同的网络协议各有优劣,需根据具体业务需求、网络环境和设备特性进行权衡,以实现最优的通信效果。UDP无连接且传输高效,但不保证数据完整,适合实时性优先的场景,如音视频通话、多人游戏;WebSocket支持全双工持久连接,能实现服务器主动推送,适合需实时双向通信的场景,如在线聊天、在线协作工具;MQTT是轻量级发布/订阅协议,带宽占用低、能耗小,能在低算力设备和不稳定网络中高效传输少量数据,适合物联网场景,如传感器数据上报、智能家居控制;HTTP基于请求/响应模式,其无状态特性适配单次数据交互,适合客户端主动获取资源的场景,如网页浏览、API调用。
HTTP作为互联网服务中使用最多的协议,至今已迭代多个版本,每一个版本都针对性能做了大量优化。由于HTTP协议是无状态的,每次请求都需要进行三次握手、四次挥手,现在客户端交互非常复杂,频繁创建连接十分消耗资源。HTTP Keep-alive机制允许一个TCP连接被多次请求复用,从而减少创建、关闭TCP连接的开销。
HTTP/1.1默认开启Keep-alive机制,无需客户端或服务器显式启用,但默认配置可能不满足高并发场景, Nginx中仍需合理配置以优化连接管理,如静态资源服务器可缩短超时时间,API网关可增大连接复用数。针对反向代理场景,需同时配置Nginx与客户端、Nginx与上游服务器持久连接,且必须显式配置连接池和协议参数。
http {
#客户端连接配置
keepalive_timeout 65; #定义空闲连接的超时时间(默认75秒),超时后关闭连接
keepalive_requests 300;#单个连接的最大请求数(默认100),当请求数达到上限后,连接会被关闭。
#上游服务器连接池
upstream backend {
server 10.0.0.1:80;
server 10.0.0.2:80;
keepalive 300; #连接池大小,即每个worker进程与后端服务器之间保持的空闲连接数量
}
server {
location / {
proxy_pass http://backend;
proxy_http_version 1.1; #强制使用HTTP/1.1协议,启用Keep-Alive
proxy_set_header Connection ""; #清除Connection头部,防止传递"close"等值
}
}
}
HTTP/2拥有Header压缩、多路复用、二进制分帧、服务端推送等颠覆性特性。HTTP/2每次发送请求前使用HPACK规范在之前发送过的请求头列表中查找已编码的请求头信息,对当前请求头进行重组,从而压缩了大量冗余的请求头帧(Header压缩)。如果说Header压缩微不足道,那么在一个TCP连接上并行处理多个请求的多路复用就比较炸裂了。由于HTTP/1.1中的数据传输是基于文本的,必须按顺序串行传输,想要并行传输依赖浏览器建立多个TCP连接实现,常见的chrome和firefox单域名最大并发是6个,然后又衍生出域名分片(假设使用3个域名,就有18个并发)来减少阻塞概率。HTTP/2协议采用二进制编码,将请求和响应数据分割为帧,其中帧对数据进行顺序标识。这样同域名下所有请求都在单个TCP连接上进行,该连接可以承载任意数量的双向数据流,浏览器收到数据之后,就可以按照帧首部的流标识对数据进行重组。多路复用代替了HTTP/1.1 的序列和阻塞机制,极大地提高传输性能。
keepAlive与多路复用比较
HTTP/2 有许多优点,但也需要注意一些HTTP1.1中传统的优化手段可能会起反作用。比如多路复用和Header压缩使传输小文件的成本很低,所以对合并js/css、css Sprites图片合并的优化方式就失去了意义。而且资源合并还会降低浏览器缓存的可用性,只要一个小文件更新,整个缓存就完全失效,必须重新加载。所以HTTP/2协议中让资源的粒度变小,才能更好地发挥缓存的作用。
HTTP/3是HTTP协议的最新版本,其核心革新在于底层传输协议QUIC(Quick UDP Internet Connections)的重构,这一设计彻底打破了TCP的桎梏。QUIC通过0-RTT建立连接、拥塞控制算法(如CUBIC、BBR)和前向纠错(FEC)机制,在UDP上实现了比TCP更高效的可靠传输,且强制将TLS1.3直接集成进协议中,提升了握手速度(TLS1.3比TLS1.2减少了1次往返)和安全性。另外HTTP/2的多路复用虽然解决了应用层的并发问题,但底层TCP在丢包或拥塞时会重传整个数据流造成的队头阻塞,HTTP/3的每个请求/响应在一个独立的QUIC流中传输,互不干扰。在设备切换网络(如5G切换成wifi)时,HTTP/3通过唯一的Connection ID保持会话不中断,彻底解决TCP连接因IP变更而中断的问题,极大提升移动端用户体验。HTTP/3是下一代高性能、低延迟、强安全的Web协议,其在移动网络、物联网、弱网环境、实时交互等场景中的卓越表现,正推动互联网体验进入新的维度,如腾讯使用TQUIC(基于HTTP3/QUIC优化)将核心业务用户登录耗时降低30%,下载场景500ms内请求成功率从HTTPS的60%提升到90%,移动端APP在弱网、跨网场景下同样取得媲美正常网络的用户体验。截至2025年,Chrome、Firefox、Edge已全面支持HTTP/3,但Safari仅部分版本实验性支持,Android 13(API 33)系统 WebView(基于Chromium 108+)默认启用 HTTP/3 支持,iOS应用需依赖Cronet 库。当前Nginx原生不支持 QUIC和HTTP/3,需基于特定分支编译...尽管普及之路仍需跨越兼容性、部署成本等障碍,随着CDN生态的完善、工具链的成熟以及企业认知的提升,HTTP/3有望在未来几年成为主流选择。
维度 | HTTP/1.0 | HTTP/1.1 | HTTP/2 | HTTP/3 |
发布时间 | 1996年 | 1999年 | 2015年 | 2022年 |
底层协议 | TCP | TCP | TCP | UDP (QUIC) |
连接机制 | 短连接(每次请求新建连接) | 持久连接(Keep-Alive) | 多路复用 | 多路复用 + 独立流 |
传输格式 | 文本 | 文本 | 二进制分帧 | 二进制分帧 |
头部压缩 | 无 | 无 | HPACK | QPACK(改进HPACK,支持动态表) |
服务器推送 | 不支持 | 不支持 | 主动推送关联资源 | 继承HTTP/2能力 |
队头阻塞 | 严重 | 通过浏览器并发请求和域名分片缓解 | 通过多路复用解决应用层阻塞 ,TCP层阻塞仍然存在(丢包导致所有流暂停) | 彻底解决(QUIC) |
兼容性 | 全面兼容(老旧系统支持) | 广泛兼容(主流支持) | 需TLS支持,部分中间件不兼容 | 需QUIC支持,部署门槛较高 |
安全性 | 可选(依赖HTTPS/TLS) | 可选(依赖HTTPS/TLS) | 推荐(TLS 1.2+,支持加密元数据) | 内置TLS1.3 |
性能 | 低(无压缩,串行) | 中(keep-alive) | 高(头部压缩,推送) | 极高(0-RTT,无队头阻塞) |
典型延迟(1MB页面) | 300ms+ | 150-300ms | 100-200ms | 50-100ms |
-
连接池
连接池在高并发、低延迟的网络应用中发挥着关键作用。所谓连接池,是指在系统启动时预先建立一定数量的网络连接,并将这些连接集中管理,形成一个“池”。当客户端请求访问服务器时,系统无需每次都重新创建和释放连接,而是从连接池中获取一个空闲连接进行使用,用完后归还至池中,供其他请求复用。以数据库访问为例,Web应用通常需要频繁与数据库交互,若每次请求都新建数据库连接,不仅增加响应时间,也加重数据库负担。而通过使用数据库连接池(如C3P0、Druid、HikariCP等),可以大幅提升系统的吞吐能力和响应速度。
-
异步通信
当业务流程中存在非实时依赖步骤时,可使用消息队列实现异步通信平抑流量波动、降低拥塞。在高并发场景下,同步请求易导致网络瞬间过载、延迟飙升;异步通信通过队列缓冲峰值流量,让数据按接收端处理能力平稳传输,减少丢包和重传。比如用户注册后需发送短信通知、添加会员积分。主服务完成注册后,只需向队列发送一条 “用户注册成功” 消息,无需等待短信服务执行结果,直接返回给用户;短信、积分服务异步从队列取消息处理,大幅缩短用户等待时间。
专栏文章推荐: