问题:我需要向服务器发送很多HTTP请求。我只能使用一个连接(不可协商的服务器限制)。服务器的响应时间加上网络延迟太高 - 我落后了。带请求流水线的Python HTTP客户端
这些请求通常不会更改服务器状态,也不依赖于先前请求的响应。所以我的想法是简单地发送它们,排队响应对象,并依赖传入响应的Content-Length:将传入的响应提供给下一个等待的响应对象。换句话说:将请求传递给服务器。
这当然不是完全安全的(任何没有Content-Length的答复都意味着麻烦),但我不在乎 - 在这种情况下,我总是可以重试任何排队的请求。 (安全的方法是在发送下一个位之前等待头部,这可能会帮助我,事先没有办法测试)
所以,理想情况下,我想要下面的客户端代码(它使用客户端延迟以模仿网络延迟)在三秒钟内运行。
现在为$ 64000问题:是否有一个Python库已经这样做,还是我需要滚动我自己?我的代码使用gevent;如果需要,我可以使用Twisted,但Twisted的标准连接池不支持流水线请求。如果需要,我也可以为某个C库编写一个包装,但我更喜欢本地代码。
#!/usr/bin/python
import gevent.pool
from gevent import sleep
from time import time
from geventhttpclient import HTTPClient
url = 'http://local_server/100k_of_lorem_ipsum.txt'
http = HTTPClient.from_url(url, concurrency=1)
def get_it(http):
print time(),"Queueing request"
response = http.get(url)
print time(),"Expect header data"
# Do something with the header, just to make sure that it has arrived
# (the greenlet should block until then)
assert response.status_code == 200
assert response["content-length"] > 0
for h in response.items():
pass
print time(),"Wait before reading body data"
# Now I can read the body. The library should send at
# least one new HTTP request during this time.
sleep(2)
print time(),"Reading body data"
while response.read(10000):
pass
print time(),"Processing my response"
# The next request should definitely be transmitted NOW.
sleep(1)
print time(),"Done"
# Run parallel requests
pool = gevent.pool.Pool(3)
for i in range(3):
pool.spawn(get_it, http)
pool.join()
http.close()
注意:至于C库,我已经在http://code.google.com/p/serf/找到了serf。不幸的是,为* *库编写可行的Python绑定并不是我目前支付的东西。 : -/ –
你的代码看起来有点像[grequests](https://github.com/kennethreitz/grequests/blob/master/grequests.py)。你有没有看过它?如果你有,你能解释为什么它不适合吗? (我可能还没有完全理解这个问题) – BorrajaX
grequests是一个简单的异步请求包装器,即每个请求一个线程,并且每个仍然是使用自己的连接的发送/接收/发送下一个位置的锁步。我需要一些打开单个TCP连接的东西,然后产生一个发送请求头的线程,另一个接收响应并将它们与“他们的”请求关联起来。 –