2013-10-11 44 views
17

问题:我需要向服务器发送很多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() 
+0

注意:至于C库,我已经在http://code.google.com/p/serf/找到了serf。不幸的是,为* *库编写可行的Python绑定并不是我目前支付的东西。 : -/ –

+0

你的代码看起来有点像[grequests](https://github.com/kennethreitz/grequests/blob/master/grequests.py)。你有没有看过它?如果你有,你能解释为什么它不适合吗? (我可能还没有完全理解这个问题) – BorrajaX

+2

grequests是一个简单的异步请求包装器,即每个请求一个线程,并且每个仍然是使用自己的连接的发送/接收/发送下一个位置的锁步。我需要一些打开单个TCP连接的东西,然后产生一个发送请求头的线程,另一个接收响应并将它们与“他们的”请求关联起来。 –

回答

-1

这不是一个答案,你的图书馆的问题,但你能不能使用的东西如硒及其selenium.webdriver.support.ui进口WebDriverWait 等待你的要求了一段时间进行处理,然后取你的下一步是,如果你没有任何相关的答案,它是否存储回应供以后使用或发送下一个请求?
如果您不需要对此连接进行身份验证,则此接口的使用还允许使用代理绕过(根据您的应用程序和需要合理设置)服务器限制(3或5有助于提高速度) 。

-2

看来你正在运行python2。

对于python3> = 3.5 你可以使用异步/的await循环 见asyncio

此外,还有建在上面更好的图书馆,更容易使用 称为Trio,在PIP提供。


我能想到的另一件事是带锁的多线程。 我会考虑如何更好地解释这个问题,甚至可以解决问题。

+1

请解释哪个异步HTTP库能够将多个请求放入单个连接。 aiohttp无法做到这一点。 –

+0

anser与流水线无关 – MacHala

+0

_aiohttp_可能会在“ClientSession”中添加请求流水线:https://github.com/aio-libs/aiohttp/issues/1740 – DurandA

0

Dugong是声称支持真正的HTTP/1.1流水线的仅HTTP/1.1的客户端。 The tutorial包括几个关于如何使用它的例子,包括一个using threads和另一个using asyncio

务必确认您与之通信的服务器实际上是否支持HTTP/1.1流水线 - 一些服务器声称支持HTTP/1.1但未实现流水线。