问题描述
我用 python 对 http1.1/http2 做了一些基准测试,代码就像多次重复 Google 搜索请求一样简单。结果很有趣:http2 版本相当慢。 (我尝试了两个 pycurl/httpx 库) 有人可以解释为什么会发生这种情况吗?
更新:
这是 httpx 版本代码:(第一个 pip install httpx[http2]
)
import time
import httpx
client = httpx.Client(http2=True)
start = time.time()
for _ in range(100):
response = client.get("https://www.google.com/search?q=good")
response.raise_for_status()
print(time.time() - start)
解决方法
因此,了解 HTTP/2 旨在解决什么问题以及不解决什么问题非常重要。
HTTP/2 旨在通过向 HTTP 协议添加 multiplexing 来提高对同一站点的多个请求的效率。基本上,HTTP/1.1 在处理请求时会阻止整个连接,但 HTTP/2 不会——因此允许在此期间发出其他请求。
这意味着,在 HTTP/2 下的单个请求(就像您在做的那样)并不比在 HTTP/1.1 下更好。事实上,由于在每个 HTTP/2 连接开始时发送一些额外的设置消息,它甚至可能稍微慢一些,而在 HTTP/1.1 下不需要这些消息。虽然我很惊讶这种差异是否真的很明显,但你能否提供更多关于缓慢程度的详细信息?它也可能指向您正在使用的 HTTP/2 实现中效率较低的代码。能分享一下代码吗?
即使在浏览器上下文中,如果您查看高度优化的网站,例如 Google 的主页(可能是互联网上访问量最大的页面,并且由对网络和如何优化网页了解很多的公司运营) ,那么您可能也看不出区别。 Google 主页基本上在单个请求中呈现,因为所有关键请求都被内联以使其尽可能快 - 无论是使用 HTTP/1.1 还是 HTTP/2。
然而,浏览器中加载的典型页面涉及数十甚至数百个请求,HTTP/2 的优势往往非常明显。
如果您采用 an extreme site with lots of small requests(这是 HTTP/2 真正擅长的地方!),那么差异确实很明显。
***** 编辑,看看你提供的好 ****
关于您的特定测试用例,我可以为 Google 重复此操作,但不能为其他网站重复此操作。
差异似乎太大了,不可能是因为 HTTP/1.1 和 HTTP/2,所以我怀疑 HTTP/1.1 正在重用连接,但 HTTP/2 没有。将连接设置移动到 for 循环中对两者都产生了相同的缓慢结果,并且类似于之前的 HTTP/2 计时似乎证实了这一点。
import time
import httpx
start = time.time()
for _ in range(100):
client = httpx.Client(http2=True)
response = client.get("https://www.google.com/search?q=good")
response.raise_for_status()
print(time.time() - start)
类似地将 keepalives 更改为 0 也会降低 HTTP/1.1 的速度以匹配 HTTP/2:
client = httpx.Client(http2=False,limits=httpx.Limits(max_keepalive_connections=0))
Keepalive 不再是 HTTP/2 中的概念(默认情况下连接保持活动状态,直到客户端认为不再需要保持连接)。
所以这似乎是 httpx 的 HTTP/1 处理的问题(他们确实注意到这是实验性的),而不是协议本身的问题。
最终转向这种代码风格,似乎使 HTTP/2 统计数据重新与 HTTP/1.1 保持一致:
import time
import httpx
with httpx.Client(http2=False) as client:
start = time.time()
for _ in range(100):
response = client.get("https://www.google.com/search?q=good")
response.raise_for_status()
print(time.time() - start)
但在这一点上。 Google 对我向他们的服务器发送垃圾邮件并返回 429 Client Error: Too Many Requests...
错误感到厌烦。
当我尝试在我自己的服务器上重复相同的问题,然后在 stackoverflow.com 上,我不能 - HTTP/1.1 和 HTTP/2 的速度相似。如果相同的连接有助于加快速度,不确定 Google 是否在他们这边做一些缓存。
无论如何,重点是,这似乎是一个特定于实现的问题,与 HTTP 协议本身无关。
,https://github.com/dalf/pyhttp-benchmark 可能会有所帮助。
见:
- results for httpx 0.18.1
- results for httpx 0.16.1
- 标签:
- httpx_uvloop_True = httpx,使用 uvloop 和 http2
- httpx_uvloop_False = httpx,仅使用 uvloop 和 http1
TLDR:使用 httpx,使用 http2 时
- 避免大型内容 (>64kb)。
- 避免顺序请求
- 首选并行请求