封装了对外发送批量请求的 request 方法,接收一次性发送的数据多少,和数据综合,在外部使用时,只需要构建好网络请求对象的数据,设定好请求池大小即可,同时,设置了重试功能,进行了 4 次重试,防止在网络抖动的时候,单个数据的网络请求发送失败。
在使用协程重构网络请求模块之后,当数据量在 1000 的时候,由之前的 816s,提升到 424s,快了一倍,且请求池大小加大的时候,效果更明显,由于第三方平台同时建立连接的数据限制,我们设定了 40 的阀值。可以看到,优化的程度很显著。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
| import aiohttp
import asyncio
from inspect import isfunction
import time
import logger
@logging_utils.exception(logger)
def request(pool, data_list):
loop = asyncio.get_event_loop()
loop.run_until_complete(exec(pool, data_list))
async def exec(pool, data_list):
tasks = []
sem = asyncio.Semaphore(pool)
for item in data_list:
tasks.append(
control_sem(sem,
item.get("method", "GET"),
item.get("url"),
item.get("data"),
item.get("headers"),
item.get("callback")))
await asyncio.wait(tasks)
async def control_sem(sem, method, url, data, headers, callback):
async with sem:
count = 0
flag = False
while not flag and count < 4:
flag = await fetch(method, url, data, headers, callback)
count = count + 1
print("flag:{},count:{}".format(flag, count))
if count == 4 and not flag:
raise Exception('EAS service not responding after 4 times of retry.')
async def fetch(method, url, data, headers, callback):
async with aiohttp.request(method, url=url, data=data, headers=headers) as resp:
try:
json = await resp.read()
print(json)
if resp.status != 200:
return False
if isfunction(callback):
callback(json)
return True
except Exception as e:
print(e)
|
外部接收一些文件,每个文件里有一组数据,其中,这组数据需要通过 http 的方式,发向第三方平台,并获得结果。
由于同一个文件的每一组数据没有前后的处理逻辑,在之前通过 Requests 库发送的网络请求,串行执行,下一组数据的发送需要等待上一组数据的返回,显得整个文件的处理时间长,这种请求方式,完全可以由协程来实现。
为了更方便的配合协程发请求,我们使用 aiohttp 库来代替 requests 库,关于 aiohttp,这里不做过多剖析,仅做下简单介绍。
aiohttp 是 asyncio 和 Python 的异步 HTTP 客户端 / 服务器,由于是异步的,经常用在服务区端接收请求,和客户端爬虫应用,发起异步请求,这里我们主要用来发请求。
aiohttp 支持客户端和 HTTP 服务器,可以实现单线程并发 IO 操作,无需使用 Callback Hell 即可支持 Server WebSockets 和 Client WebSockets,且具有中