异步并发怎么做?

news/2024/9/23 3:09:00/

异步并发

    • 1、flask异步并发
      • 问题
      • 解决办法
      • 实现方案
        • (1)flask + 异步视图装饰器
        • (2)WSGI启动服务
    • 2、fastapi异步编程

flask_1">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,如果一个请求超时,就直接返回错误,不再等待它完成。这样可以避免一个请求阻塞住整个服务器。

实现方案

flask___15">(1)flask + 异步视图装饰器

本质: 多线程并发。虽然宏观上看好像是异步并发(单线程的并发)。

虽然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_workers=1)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}--3:response sizes: {[len(res) for res in responses]},耗时{time2 - time1}s\n')return responses if __name__ == "__main__":# app.run(debug=False, use_reloader=False,threaded=False)  app.run(debug=False, use_reloader=False)
(2)WSGI启动服务

本质: 多线程、多进程的并发。

如何在 uwsgi 配置中传递自定义参数?

2、fastapi异步编程

本质: 协程(单线程)并发。

待续。。。。。。。。。


http://www.ppmy.cn/news/1435908.html

相关文章

介绍TCP协议标志位

TCP协议中的控制位(Flags)是TCP头部中的6个标志位,用于控制TCP连接的建立、维护和终止过程,以及在数据传输中的一些特定行为。以下是对每个标志位的详细介绍: SYN (Synchronize): 功能:用于建立…

MATLAB实现蚁群算法栅格路径优化

蚁群算法是一种模拟自然界中蚂蚁觅食行为的优化算法,常用于解决路径规划问题。在栅格路径优化中,蚁群算法可以帮助找到从起点到终点的最优路径。以下是蚁群算法栅格路径优化的基本流程步骤: 初始化参数: (1)设置蚂蚁数量&#xff…

常用的MQ有哪些?

1. 背景 最近有新同事接触了项目中使用的RocketMQ,问了一个问题:MQ有哪几种?基于此,本文介绍一下目前市面上常用的消息队列(MQ)有哪些。 2. 五种主流消息队列(MQ) 2.1 RocketMQ …

Ansible 中的copy 复制模块应用详解

作者主页:点击! Ansible专栏:点击! 创作时间:2024年4月25日13点40分 Ansible 中的 copy 模块用于将文件或目录从本地计算机或远程主机复制到远程主机上的特定位置。它是一个功能强大的模块,可用于各种文…

【C++】从零开始认识泛型编程 — 模版

送给大家一句话: 尽管眼下十分艰难,可日后这段经历说不定就会开花结果。总有一天我们都会成为别人的回忆,所以尽力让它美好吧。 – 岩井俊二 \\\ ⱶ˝୧(๑ ⁼̴̀ᐜ⁼̴́๑)૭兯 //// &#…

获取公募基金持仓【数据分析系列博文】

摘要 从指定网址获取公募基金持仓数据,快速解析并存储数据。 (该博文针对自由学习者获取数据;而在投顾、基金、证券等公司,通常有Wind、聚源、通联等厂商采购的数据) 1. 导入必要的库: pandas 用于数据处理…

rust - 捕获全局panic并记录进程退出日志

本文提供了捕获全局panic并记录进程退出日志的方法。 1. 使用 panic::set_hook 注册异常处理 use human_panic::setup_panic; use log::error; use std::{boxed::Box, panic};fn hook(panic_info: &panic::PanicInfo) {if cfg!(debug_assertions) {let err_message form…

vulfocus靶场redis 未授权访问漏洞之CNVD-2015-07557

目标系统的权限不够redis用户无法写计划任务和公钥,而且也没有开放ssh端口。 主从复制getshell,写入恶意的so文件达到执行系统命令的目的。 github上有一键可以利用的脚本 https://github.com/n0b0dyCN/redis-rogue-server.git 利用条件:需…