|
AsyncHTTPClient是 tornado.httpclinet 提供的一个异步http客户端。使用也比较简单。与服务进程一样,AsyncHTTPClient也可以callback和yield两种使用方式。前者不会返回结果,后者则会返回response。 示例: 1 class AsyncHandler(tornado.web.RequestHandler): 2 @tornado.web.asynchronous 3 def get(self, *args, **kwargs): 4 5 url = 'https://api.github.com/' 6 http_client = tornado.httpclient.AsyncHTTPClient() 7 http_client.fetch(url, self.on_response) 8 self.finish('It works') 9 10 @tornado.gen.coroutine 11 def on_response(self, response): 12 print response.code 同样,为了获取response的结果,只需要yield函数。使用yield的时候,handler是需要 tornado.gen.coroutine。 1 class AsyncResponseHandler(tornado.web.RequestHandler): 2 @tornado.web.asynchronous 3 @tornado.gen.coroutine 4 def get(self, *args, **kwargs): 5 6 url = 'https://api.github.com/' 7 http_client = tornado.httpclient.AsyncHTTPClient() 8 response = yield tornado.gen.Task(http_client.fetch, url) 9 print response.code 10 print response.body 如果业务处理并不是在handlers写的,而是在别的地方,当无法直接使用tornado.gen.coroutine的时候,可以构造请求,使用callback的方式。 1 body = urllib.urlencode(params) 2 req = tornado.httpclient.HTTPRequest( 3 url=url, 4 method='POST', 5 body=body, 6 validate_cert=False) 7 8 http_client.fetch(req, self.handler_response) 9 10 def handler_response(self, response): 11 12 print response.code AsyncHTTPClient中的fetch方法,第一个参数其实是一个HTTPRequest实例对象,因此对于一些和http请求有关的参数,例如method和body,可以使用HTTPRequest先构造一个请求,再扔给fetch方法 1 def getURL(): 2 2 # 接口地址 3 3 url = "http://ip:port/Get2" 4 4 5 5 6 6 payload = {"key":"914683196200","timestamp":"2019-07-11 11:27:21","partner_id":"1","sign":"C77CAAA496FE0D385410A"} 7 7 # verify = False 忽略SSH 验证 8 8 9 9 try: 10 response = requests.post(url, json=payload, timeout=5) # 超时的时候回报错并重试 11 print(r.json()) 12 except ReadTimeout: 13 # 超时异常 14 print('Timeout') 15 return 1 16 except ConnectionError: 17 # 连接异常 18 print('Connection error') 19 return 2 20 except RequestException as e: 21 # 请求异常 22 print('Error') 23 print('str(Exception):\t', str(Exception)) 24 print('str(e):\t\t', str(e)) 25 print('repr(e):\t', repr(e)) 注意:使用异步,必须tornado.ioloop.IOLoop.instance().start 启动 IOLoop 的实例,启动事件循环机制,配合非阻塞的 HTTP Server 工作
callback_async 1 @coroutine 2 def post ( self, url, body, domain=None ) : 3 try : 4 request = AsyncHTTPClient() 5 response = yield request.fetch(url, method="POST", body=body) 6 logger.info("url: {0} code: {1}".format(url, response.code)) 7 self.retry() 8 raise Return(True) 9 except Return : 10 pass 11 except Exception as e : 12 print('str(Exception):\t', str(Exception)) 13 print('str(e):\t\t', str(e)) 14 print('repr(e):\t', repr(e)) 15 print('e.message:\t', e.message) 16 logger.exception("url: {0}".format(url)) 17 self.push(uri, body, domain) 18 self.reload_domain() 19 raise Return(False) 20 21 22 @coroutine 23 def post_callback ( self, url, body, domain=None, call_back=None, error_back=None, retry_times=3 ) : 24 try : 25 request = AsyncHTTPClient() 26 27 response = yield request.fetch(url, method="POST", body=body) 28 logger.info("url: {0} code: {1}".format(url, response.code)) 29 if call_back : 30 call_back(response) 31 except Exception as e : 32 print('str(Exception):\t', str(Exception)) 33 print('str(e):\t\t', str(e)) 34 print('repr(e):\t', repr(e)) 35 print('e.message:\t', e.message) 36 if retry_times > 0 : 37 logger.info("url: {0} retry: {1}".format(url, retry_times)) 38 retry_times -= 1 39 IOLoop.instance().call_later(1, self.post_callback, uri, body, domain, call_back, error_back, 40 retry_times) 41 else : 42 logger.exception("url: {0}".format(url)) 43 if error_back : 44
|