福州做网站公司有哪些,中小企业网站制作塞尼铁克,asp.net 3.5网站开发全程解析 ,做薆视频网站异步并发 1、flask的异步并发问题解决办法实现方案#xff08;1#xff09;flask 异步视图装饰器#xff08;2#xff09;WSGI启动服务 2、fastapi异步编程 1、flask的异步并发
问题
flask在开发环境下是单线程的#xff0c;如果某个请求长时间无响应#xff08;阻塞1flask 异步视图装饰器2WSGI启动服务 2、fastapi异步编程 1、flask的异步并发
问题
flask在开发环境下是单线程的如果某个请求长时间无响应阻塞会导致其他请求也无法响应。flask原生并不提供异步并发能力。也就是说如果使用flask开发的app接口即使该接口使用了协程异步编程但在外部并发请求时flask还是会把这些 已经异步编程的接口当成 同步接口执行。
解决办法
1、使用多线程或者多进程的服务器例如使用 Gunicorn 或者 uWSGI 部署 Flask 或 FastAPI 应用。这些服务器可以同时处理多个请求。2、使用异步非阻塞的服务器例如 Tornado 或者 Twisted。这些服务器可以在处理一个请求的时候如果遇到 IO 阻塞就先去处理其他的请求等 IO 完成后再回来继续处理这个请求。3、使用异步编程例如 asyncio 或者 gevent。这些库可以让你的代码在遇到 IO 阻塞的时候自动切换到其他的任务从而提高整体的并发性能。 但flask并不真正提供异步运行的能力推荐支持异步编程的 Web 框架如fastapi【fastapi官方文档】、aiohttp【aiohttp官方文档】。 备注 aiohttp既可以做客服端发起请求又可以做服务端接受并处理请求支持http协议因此可以做web框架。 但aiohttp比较底层写起来代码较多。 客户端-浅度测评requests、aiohttp、httpx 我应该用哪一个 【异步并发编程】使用aiohttp构建Web应用程序4、对于超时的请求可以考虑设置一些超时机制例如使用 future 或者 promise如果一个请求超时就直接返回错误不再等待它完成。这样可以避免一个请求阻塞住整个服务器。
实现方案
1flask 异步视图装饰器 本质 多线程并发。虽然宏观上看好像是异步并发单线程的并发。 虽然asynic await关键字旨在实现同一线程里的并发但flask并不原生支持这一能力“不支持”不是说“不能使用这些关键字”。 所以同一时间、同一线程、多个请求并发请求时不管有无asynic await关键字修饰请求接口flask都是一个一个顺序的、同步处理他们而不是并发处理。
这里的装饰器实现的功能 在 Making Flask async and Quart sync, Quart 的作者 PG Jones 给出了一个 Flask 异步化的代码route 方法可加上 async 关键字和 run_async 装饰 当并发请求时给每个请求开创一个线程单独的处理这样并发的请求就被放到了多线程里从宏观上看就是并发了这样也不会因为某个接口请求阻塞而导致其他接口也无法响应的问题。 但这种异步装饰器只是宏观上的“像”协程并发协程单线程下的并发其实是多线程并发。 #!/usr/bin/env python
# -*- coding: UTF-8 -*-Project hippo-ai-py
Author cf
Date 2024/4/2
Desc : api公用信息
import asyncio
from concurrent.futures import Future, ThreadPoolExecutor
from functools import wrapsfrom flask import Flask, has_request_context, copy_current_request_contextdef run_async(func):flask异步视图装饰器。Args:func: 调用的方法Returns:wraps(func)def _wrapper(*args, **kwargs):call_result Future()def _run():loop asyncio.new_event_loop()try:result loop.run_until_complete(func(*args, **kwargs))except Exception as error:call_result.set_exception(error)else:call_result.set_result(result)finally:loop.close()loop_executor ThreadPoolExecutor(max_workers1)if has_request_context():_run copy_current_request_context(_run)loop_future loop_executor.submit(_run)loop_future.result()return call_result.result()return _wrapperapp Flask(__name__)async def fetch(url):print(f{threading.current_thread().name}:{url})return requests.get(url).textasync def main(t):await asyncio.sleep(t)tasks [fetch(url) for url in [https://baidu.com, https://bing.com, https://yanbin.blog]]return await asyncio.gather(*tasks)app.route(/)
run_async
async def index():time1 time.time()responses await main(3)time2 time.time()print(f{threading.current_thread().name}--3response sizes: {[len(res) for res in responses]}耗时{time2 - time1}s\n)return responses if __name__ __main__:# app.run(debugFalse, use_reloaderFalse,threadedFalse) app.run(debugFalse, use_reloaderFalse)2WSGI启动服务 本质 多线程、多进程的并发。 如何在 uwsgi 配置中传递自定义参数
2、fastapi异步编程 本质 协程单线程并发。 待续。。。。。。。。。