我正在使用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
当我在本地服务器上测试时,它工作正常,请求按时发送,往返时间显然很小。 但是,当我针对远程服务器测试它时,往返时间较长(特别是对于更高的请求负载),请求时间会被多秒搞乱:每个请求之间的等待时间变得远大于期望的时间段。
为什么?我认为异步代码不会受到往返时间的影响,因为它在等待响应时没有阻塞。有没有任何已知的解决方案?
答案 0 :(得分:1)
经过一些修修补补和tcpdumping后,我得出的结论是,有两件事真的在减慢我的协程速度。有了这两个纠正的停顿极大地下降了,timeout
中的yield wakeup_condition.wait(timeout=timedelta(seconds=interval))
得到了更好的尊重:
在DNS上的默认配置块中的tornado.httpclient 解决方案但不在其他网络访问上(以减轻此用途
ThreadedResolver
或tornado.curl_httpclient
正确配置的libcurl
)构建。
......并在the AsynHTTPClient docs
要选择curl_httpclient,请在启动时调用AsyncHTTPClient.configure:
AsyncHTTPClient.configure("tornado.curl_httpclient.CurlAsyncHTTPClient")
我最终实现了我自己的解析和缓存DNS的线程,并且通过直接向IP地址发出请求解决了这个问题。