现在我们考虑一个问题,当日志发送到远程服务器过程中,如果远程服务器处理的很慢,会耗费一定的时间, 那么这时记录日志就会都变慢修改服务器日志处理类,让其停顿5秒钟,模拟长时间的处理流程
async def post(self):
print(self.getParam('log'))
await asyncio.sleep(5)
self.write({"msg": 'ok'})
此时我们再打印上面的日志
logger.debug("今天天气不错")
logger.debug("是风和日丽的")
得到的输出为
[2020-09-23 11:47:33] [DEBUG] 今天天气不错
[2020-09-23 11:47:38] [DEBUG] 是风和日丽的
我们注意到,它们的时间间隔也是5秒。
那么现在问题来了,原本只是一个记录日志,现在却成了拖累整个脚本的累赘,所以我们需要异步的来 处理远程写日志。
1
使用多线程处理
首先想的是应该是用多线程来执行发送日志方法
def emit(self, record):
msg = self.format(record)
if self.method == "GET":
if (self.url.find("?") >= 0):
sep = '&'
else:
sep = '?'
url = self.url + "%c%s" % (sep, urllib.parse.urlencode({"log": msg}))
t = threading.Thread(target=requests.get, args=(url,))
t.start()
else:
headers = {
"Content-type": "application/x-www-form-urlencoded",
"Content-length": str(len(msg))
}
t = threading.Thread(target=requests.post, args=(self.url,), kwargs=
{"data":{'log': msg},
这种方法是可以达到不阻塞主目的,但是每打印一条日志就需要开启一个线程,也是挺浪费资源的。
我们也 可以使用线程池来处理
2
使用线程池处理
python 的 concurrent.futures 中有ThreadPoolExecutor, ProcessPoolExecutor类,是线程池和进程池, 就是在初始化的时候先定义几个线程,之后让这些线程来处理相应的函数,这样不用每次都需要新创建线程
线程池的基本使用
exector = ThreadPoolExecutor(max_workers=1) # 初始化一个线程池,只有一个线程
exector.submit(fn, args, kwargs) # 将函数submit到线程池中
如果线程池中有n个线程,当提交的task数量大于n