为什么长HTTP往返时间会拖延我的Tornado AsyncHttpClient?

时间:2016-07-22 16:01:37

标签: python http asynchronous tornado

我正在使用Tornado以快速,定期的连续(每0.1秒甚至0.01秒)向服务器发送请求。为此,我正在使用带有回调的AsyncHttpClient.fetch来处理响应。 这是一个非常简单的代码来显示我的意思:

from functools import partial
from tornado import gen, locks, httpclient
from datetime import timedelta, datetime

    # usually many of these running on the same thread, maybe requesting the same server
 @gen.coroutine
 def send_request(url, interval):
    wakeup_condition = locks.Condition()
    #using this to allow requests to send immediately
    http_client = httpclient.AsyncHTTPClient(max_clients=1000) 

    for i in range(300):
        req_time = datetime.now()

        current_callback = partial(handle_response, req_time)
        http_client.fetch(url, current_callback, method='GET')
        yield wakeup_condition.wait(timeout=timedelta(seconds=interval))

def handle_response(req_time,  response):
    resp_time = datetime.now()
    write_to_log(req_time, resp_time, resp_time - req_time) #opens the log and writes to it

当我在本地服务器上测试时,它工作正常,请求按时发送,往返时间显然很小。 但是,当我针对远程服务器测试它时,往返时间较长(特别是对于更高的请求负载),请求时间会被多秒搞乱:每个请求之间的等待时间变得远大于期望的时间段。

为什么?我认为异步代码不会受到往返时间的影响,因为它在等待响应时没有阻塞。有没有任何已知的解决方案?

1 个答案:

答案 0 :(得分:1)

经过一些修修补补和tcpdumping后,我得出的结论是,有两件事真的在减慢我的协程速度。有了这两个纠正的停顿极大地下降了,timeout中的yield wakeup_condition.wait(timeout=timedelta(seconds=interval))得到了更好的尊重:

  1. 我正在运行的计算机似乎没有缓存DNS,对于AsyncHTTPClient似乎是阻塞网络调用。因此,每个协同程序发送请求都有额外的时间等待DNS解析。龙卷风文档说:
  2.   

    在DNS上的默认配置块中的tornado.httpclient   解决方案但不在其他网络访问上(以减轻此用途   ThreadedResolvertornado.curl_httpclient   正确配置的libcurl)构建。

    ......并在the AsynHTTPClient docs

      

    要选择curl_httpclient,请在启动时调用AsyncHTTPClient.configure:

         

    AsyncHTTPClient.configure("tornado.curl_httpclient.CurlAsyncHTTPClient")

    我最终实现了我自己的解析和缓存DNS的线程,并且通过直接向IP地址发出请求解决了这个问题。

    1. 我使用的网址是HTTPS,更改为HTTP网址提高了性能。对于我的用例并非总是可行,但能够本地化部分问题是件好事