首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Uvicorn + Gunicorn + Starlette在发球时被卡住了,如果没有sigkill,就不能重新启动服务

Uvicorn + Gunicorn + Starlette在发球时被卡住了,如果没有sigkill,就不能重新启动服务
EN

Stack Overflow用户
提问于 2020-11-30 07:57:41
回答 1查看 1.3K关注 0票数 1

我是在一个VM上服务的模型通过火奴鲁恩+ uvicorn。

它由监督机构自动启动,运行api.sh

api.sh包含:

代码语言:javascript
运行
复制
source /home/asd/.virtual_envs/myproject/bin/activate

/home/asd/.virtual_envs/myproject/bin/gunicorn --max-requests-jitter 30 -w 6 -b 0.0.0.0:4080 api:app -k uvicorn.workers.UvicornWorker

在不涉及太多api.py的情况下,它包含以下主要部分:

代码语言:javascript
运行
复制
from starlette.applications import Starlette
from models import SomeModelClass


app = Starlette(debug=False)
model = SomeModelClass()


@app.route('/do_things', methods=['GET', 'POST', 'HEAD'])
async def add_styles(request):
    if request.method == 'GET':
        params = request.query_params
    elif request.method == 'POST':
        params = await request.json()
    elif request.method == 'HEAD':
        return UJSONResponse([])

    # Doing things
    result = model(params)
    return UJSONResponse(result)

在api运行几天之后,我开始得到这些错误:

代码语言:javascript
运行
复制
[INFO] Starting gunicorn 20.0.3
[ERROR] Connection in use: ('0.0.0.0', 4080)
[ERROR] Retrying in 1 second.
[ERROR] Connection in use: ('0.0.0.0', 4080)
[ERROR] Retrying in 1 second.
[ERROR] Connection in use: ('0.0.0.0', 4080)
[ERROR] Retrying in 1 second.
[ERROR] Connection in use: ('0.0.0.0', 4080)
[ERROR] Retrying in 1 second.
...

在supervisord中重新启动api什么也不做,我得到的消息与上面相同。我发现起作用的唯一方法是:

在supervisord

  • See中运行的sudo netstat -tulpn | grep LISTEN

  • Kill

  • Stop api,pid在4080端口上运行(一个python3.8进程):sudo netstat -tulpn | grep LISTEN

  • Kill它运行kill -9 [PID]

  • Repeat步骤2-3 1-2次,直到没有占用4080端口

  • ,在监控的

中启动api。

你有什么办法解决这个问题吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-01-19 07:38:36

代码实际上使用了来自multiprocessingmultiprocessing,这很可能是造成这个问题的原因。

示例:

代码语言:javascript
运行
复制
from starlette.applications import Starlette
from models import SomeModelClass
from multiprocessing import Pool
from utils import myfun


app = Starlette(debug=False)
model = SomeModelClass()


@app.route('/do_things', methods=['GET', 'POST', 'HEAD'])
async def add_styles(request):
    if request.method == 'GET':
        params = request.query_params
    elif request.method == 'POST':
        params = await request.json()
    elif request.method == 'HEAD':
        return UJSONResponse([])

    # Doing things
    result = model(params)
    # Start of the offending code
    pool = Pool(4)
    result = pool.map(myfun, result, chunksize=1)
    # End of the offending code
    return UJSONResponse(result)

解决方案是将multiprocessing替换为concurrency

代码语言:javascript
运行
复制
from starlette.applications import Starlette
from models import SomeModelClass
import concurrent.futures
from utils import myfun


app = Starlette(debug=False)
model = SomeModelClass()


@app.route('/do_things', methods=['GET', 'POST', 'HEAD'])
async def add_styles(request):
    if request.method == 'GET':
        params = request.query_params
    elif request.method == 'POST':
        params = await request.json()
    elif request.method == 'HEAD':
        return UJSONResponse([])

    # Doing things
    result = model(params)
    # Start of the fix
    with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
        result = executor.map(myfun, result)
    result = list(result)
    # End of the fix
    return UJSONResponse(result)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65069823

复制
相关文章

相似问题

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