首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Gunicorn + ThreadPoolExecutor:如何同时处理多个用户请求?

Gunicorn + ThreadPoolExecutor:如何同时处理多个用户请求?
EN

Stack Overflow用户
提问于 2021-11-21 14:31:08
回答 1查看 150关注 0票数 0

我想提供一个能够同时处理多个用户请求的falcon API。每个请求都会触发一个长时间的处理任务,因此我使用了来自concurrent.futuresThreadPoolExecutor,如下所示:

代码语言:javascript
运行
复制
import falcon
from concurrent.futures import ThreadPoolExecutor

executor = ThreadPoolExecutor(max_workers=10)

class Resource:

    def on_post(self, req, resp):
        
        def some_long_task():
            # here is the code for the long task
            
        executor.submit(some_long_task)
        
        resp.body = 'OK'
        resp.status = falcon.HTTP_201
        
app = falcon.App()

resource = Resource()

app.add_route('/', resource)

# Serve...

我使用gunicorn来提供API,参数如下:gunicorn main:app --timeout 10000

当我连续执行两个对API的请求时,两个长任务都是在后台连续触发的。但是,一旦启动的第一个长任务完成,它就会停止执行第二个任务。我怎样才能避免这种情况?

EN

回答 1

Stack Overflow用户

发布于 2021-11-26 21:28:42

通过用time.sleep(10)替换您的长时间运行的任务,我无法重现您的问题:

代码语言:javascript
运行
复制
import logging
import time
import uuid

import falcon
from concurrent.futures import ThreadPoolExecutor

logging.basicConfig(
    format='%(asctime)s [%(levelname)s] %(message)s', level=logging.INFO)
executor = ThreadPoolExecutor(max_workers=10)


class Resource:

    def on_post(self, req, resp):

        def some_long_task():
            # here is the code for the long task

            time.sleep(10)
            logging.info(f'[task {taskid}] complete')

        taskid = str(uuid.uuid4())
        executor.submit(some_long_task)
        logging.info(f'[task {taskid}] submitted')

        resp.media = {'taskid': taskid}
        resp.status = falcon.HTTP_ACCEPTED


app = falcon.App()
resource = Resource()
app.add_route('/', resource)

正如预期的那样,所有任务都正确运行到完成:

代码语言:javascript
运行
复制
[2021-11-26 21:45:25 +0100] [8242] [INFO] Starting gunicorn 20.1.0
[2021-11-26 21:45:25 +0100] [8242] [INFO] Listening at: http://127.0.0.1:8000 (8242)
[2021-11-26 21:45:25 +0100] [8242] [INFO] Using worker: sync
[2021-11-26 21:45:25 +0100] [8244] [INFO] Booting worker with pid: 8244
2021-11-26 21:45:29,565 [INFO] [task 5b45b1f5-15ac-4628-94d8-3e1fd0710d21] submitted
2021-11-26 21:45:31,133 [INFO] [task 4553e018-cfc6-4809-baa4-f873579a9522] submitted
2021-11-26 21:45:33,724 [INFO] [task c734d89e-5f75-474c-ad78-59f178eef823] submitted
2021-11-26 21:45:39,575 [INFO] [task 5b45b1f5-15ac-4628-94d8-3e1fd0710d21] complete
2021-11-26 21:45:41,142 [INFO] [task 4553e018-cfc6-4809-baa4-f873579a9522] complete
2021-11-26 21:45:43,735 [INFO] [task c734d89e-5f75-474c-ad78-59f178eef823] complete

问题会不会出在你的长任务代码中?

有一些不是微不足道的陷阱需要注意:

  • Gunicorn使用预分叉服务器设计的变体。如果你碰巧执行高级设置,比如启动线程,或者打开文件句柄,那么当Gunicorn派生一个worker时,事情可能会崩溃。另请参阅:Gunicorn: multiple background worker threads。理想情况下,您应该仅在以这种方式对executor执行forking.
  • Submitting工作之后才初始化executor,而不检查实际结果,这可能会掩盖任务中的异常,这可能看起来像是停止执行。也许完成第一个任务会在第二个任务中引发异常?尝试用一个try... except来包围你的任务,我自己从来没有遇到过这个问题,但是从并行线程导入可能会导致死锁,例如,ThreadPoolExecutor + Requests == deadlock?这通常不应该是一个问题,但它可能是由并行任务试图在运行时导入插件造成的,就像在请求的情况下。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70055448

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档