Flask和/或Tornado - 处理外部Web服务的耗时调用

 儒妹妹_761 发布于 2022-12-18 19:58

我有一个烧瓶应用程序连接到给定URL到外部服务(具有不同但通常很长的响应时间)并在那里搜索一些东西.之后,对检索到的数据进行了大量的CPU操作.这也需要一些时间.

我的问题:来自外部的回应可能需要一些时间.你不能做很多事情,但当你同时有多个请求时它会成为一个大问题 - 对外部服务的烧瓶请求会阻塞线程,其余的则在等待.

明显浪费时间,它正在杀死应用程序.

我听说这个叫做Tornado的异步图书馆.还有我的问题:

    这是否意味着它可以设法处理多个请求并在外部响应后立即触发回调?

    我可以用我目前的烧瓶应用程序实现这一点(可能不是因为WSGI我猜?)或者我可能需要将整个应用程序重写为Tornado?

    那些CPU繁重的操作怎么样 - 会阻塞我的线程吗?无论如何做一些负载平衡是一个好主意,但我很好奇Tornado如何处理它.

    可能的陷阱,陷阱?

dano.. 6

内置于烧瓶中的Web服务器并不意味着在生产中使用,正是因为您列出的原因 - 它是单线程的,并且如果任何请求阻塞了非常重要的时间,则很容易陷入困境.flask文档列出了在生产环境中部署它的几个选项 ; mod_wsgi,gunicorn,uSWGI等.所有的这些部署选项提供了用于处理并发机制,或者通过线程,进程,或非阻塞I/O.但请注意,如果您正在进行CPU绑定操作,那么将提供真正并发性的唯一选择是使用多个进程.

如果要使用tornado,则需要以tornado样式重写应用程序.由于其体系结构基于显式异步I/O,因此如果将其部署为WSGI应用程序,则无法使用其异步功能." tornado样式"基本上意味着对所有I/O操作使用非阻塞API,并使用子进程处理任何长时间运行的CPU绑定操作.该tornado文档介绍了如何进行异步I/O调用,但这是一个如何工作的基本示例:

from tornado import gen

@gen.coroutine
def fetch_coroutine(url):
    http_client = AsyncHTTPClient()
    response = yield http_client.fetch(url)
    return response.body

response = yield http_client.fetch(curl)调用实际上是异步的; 它会在请求开始时将控制权返回给龙卷风事件循环,并在收到响应后再次恢复.这允许多个异步HTTP请求在一个线程内并发运行.做不过请注意,任何你的里面做fetch_coroutine的是不是异步I/O将阻止事件循环,并没有其他的要求,同时该代码运行处理.

要处理长时间运行的CPU绑定操作,您需要将工作发送到子进程以避免阻塞事件循环.对于Python,这通常意味着使用multiprocessingconcurrent.futures.我将看一下这个问题,了解有关如何最好地集成这些库的更多信息tornado.请注意,您不希望维护一个大于系统上CPU数量的进程池,因此请考虑在确定如何在任何给定时间运行多少并发CPU绑定操作将其扩展到一台机器之外.

龙卷风文档还有一个专门用于在负载均衡器后面运行的部分.他们建议将NGINX用于此目的.

1 个回答
  • 内置于烧瓶中的Web服务器并不意味着在生产中使用,正是因为您列出的原因 - 它是单线程的,并且如果任何请求阻塞了非常重要的时间,则很容易陷入困境.flask文档列出了在生产环境中部署它的几个选项 ; mod_wsgi,gunicorn,uSWGI等.所有的这些部署选项提供了用于处理并发机制,或者通过线程,进程,或非阻塞I/O.但请注意,如果您正在进行CPU绑定操作,那么将提供真正并发性的唯一选择是使用多个进程.

    如果要使用tornado,则需要以tornado样式重写应用程序.由于其体系结构基于显式异步I/O,因此如果将其部署为WSGI应用程序,则无法使用其异步功能." tornado样式"基本上意味着对所有I/O操作使用非阻塞API,并使用子进程处理任何长时间运行的CPU绑定操作.该tornado文档介绍了如何进行异步I/O调用,但这是一个如何工作的基本示例:

    from tornado import gen
    
    @gen.coroutine
    def fetch_coroutine(url):
        http_client = AsyncHTTPClient()
        response = yield http_client.fetch(url)
        return response.body
    

    response = yield http_client.fetch(curl)调用实际上是异步的; 它会在请求开始时将控制权返回给龙卷风事件循环,并在收到响应后再次恢复.这允许多个异步HTTP请求在一个线程内并发运行.做不过请注意,任何你的里面做fetch_coroutine的是不是异步I/O将阻止事件循环,并没有其他的要求,同时该代码运行处理.

    要处理长时间运行的CPU绑定操作,您需要将工作发送到子进程以避免阻塞事件循环.对于Python,这通常意味着使用multiprocessingconcurrent.futures.我将看一下这个问题,了解有关如何最好地集成这些库的更多信息tornado.请注意,您不希望维护一个大于系统上CPU数量的进程池,因此请考虑在确定如何在任何给定时间运行多少并发CPU绑定操作将其扩展到一台机器之外.

    龙卷风文档还有一个专门用于在负载均衡器后面运行的部分.他们建议将NGINX用于此目的.

    2022-12-18 19:59 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有