HTTP请求合并 vs HTTP并行请求

本文通过实验对比了HTTP请求合并与并行请求在不同资源大小情况下的加载时间,发现对于大资源,合并和拆分几乎没有显著差异;而对于小资源,合并请求通常更快,但网络延迟和服务器响应速度也可能影响结果。此外,资源拆分有利于浏览器缓存和域名分片策略的应用。
摘要由CSDN通过智能技术生成

今天项目遇到一个问题,请求合并和请求拆解哪一个效率更高,一直我都是认为请求合并比拆解效率上来说更好,但是其实并不是这么回事。

浏览器是可以并行下载资源的,将多个资源合并成一个资源,只使用一个HTTP请求下载,不一定会比用多个HTTP请求并行下载没有合并过的多个资源速度更快。
下面的实验内容我都是参考segmentfault中的文章:
作者:艾特老干部
名称:《合并HTTP请求 vs 并行HTTP请求,到底谁更快?》

HTTP请求过程
一个HTTP请求的主要过程是:

DNS解析(T1) -> 建立TCP连接(T2) -> 发送请求(T3) -> 等待服务器返回首字节(TTFB)(T4) -> 接收数据(T5)。

如下图所示,是Chrome Devtools中显示的一个HTTP请求,显示了HTTP请求的主要阶段,注意,Queueing阶段是请求在浏览器队列中的排队时间,并不计入HTTP请求时间。
在这里插入图片描述
从这个过程中,可以看出如果合并N个HTTP请求为1个,可以节省(N-1)* (T1+T2+T3+T4) 的时间。

但实际场景并没有这么理想,上面的分析存在几个漏洞:

浏览器会缓存DNS信息,因此不是每次请求都需要DNS解析。
HTTP 1.1 keep-alive的特性,使HTTP请求可以复用已有TCP连接,所以并不是每个HTTP请求都需要建立新的TCP连接。
浏览器可以并行发送多个HTTP请求,同样可能影响到资源的下载时间,而上面的分析显然只是基于同一时刻只有1个HTTP请求的场景。
实验论证
我们来做4组实验,对比一个HTTP请求加载合并后的资源所需时间,和多个HTTP请求并行加载拆分的资源所需时间。每组实验所用资源的体积大小有显著差异。

实验环境:
服务器:阿里云ECS 1核 2GB内存 带宽1M
Web服务器:Nginx (未启用Gzip)
Chrome v66 隐身模式,禁用缓存
Client 网络:wifi 带宽20M
实验代码地址:https://github.com/xuchaobei/

实验 1
测试文件:large1.css、large2.css … large6.css,每个文件141K;large-6in1.css,由前面6个css文件合并而成,大小为846K。parallel-large.html引用large1.css、large2.css … large6.css, combined-large.html引用large-6in1.css,代码如下:

// parallel-large.html
<!DOCTYPE html>
<html>

  <head>
    <meta charset="utf-8" />
    <title>Parallel Large</title>
    <link rel="stylesheet" type="text/css" media="screen" href="large1.css" />
    <link rel="stylesheet
`CompletableFuture` 是 Java 中用于异步编程的强大工具,它允许你在单线程的上下文中处理并发任务,并提供了一种更优雅的方式来处理并行操作的结果合并。在实战场景中,常常会遇到这样的情况: 1. **HTTP 请求池**:当你需要同时发送多个 HTTP 请求到不同的服务器,并希望在所有请求都完成后再继续后续处理,可以使用 `CompletableFuture` 的 `supplyAsync()` 函数来发起异步请求,然后通过 `thenApply()` 或 `thenCombine()` 将结果组合成最终结果。 ```java CompletableFuture<HttpResponse> future1 = httpClient.getAsync(url1); CompletableFuture<HttpResponse> future2 = httpClient.getAsync(url2); CompletableFuture<Void> allDone = CompletableFuture.allOf(future1, future2); allDone.thenAccept(responsePairs -> { HttpResponse firstResponse = responsePairs.get(0); HttpResponse secondResponse = responsePairs.get(1); // 处理两个响应... }); ``` 2. **数据库操作批量处理**:如果你正在执行一系列数据库查询,可以将每个查询封装到一个 CompletableFutrue 对象里,然后使用 `CompletableFuture.sequence()` 来同步所有的查询完成。 ```java CompletableFuture<ResultSet> queryFuture1 = executeQuery(sql1); CompletableFuture<ResultSet> queryFuture2 = executeQuery(sql2); CompletableFuture<Void> allQueriesComplete = CompletableFuture.sequence(Arrays.asList(queryFuture1, queryFuture2)); allQueriesComplete.thenAccept(resultSets -> { ResultSet firstResult = resultSets.get(0); ResultSet secondResult = resultSets.get(1); // 处理结果集... }); ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值