uwsgi worker 在退出时挂起,但前提是它使用了 async trio 模块
uwsgi worker hangs on exit, but only if it used async trio module
我有一个 Django 站点,它使用 trio_cdp
包使用无头 Google Chrome 生成 PDF。这个包是异步的,但是我的 Django 项目是同步的,所以它必须在 trio.run()
里面 运行
它还使用 uwsgi 锁,这样一次只有一个客户端可以生成 PDF(无头 Chrome 在单个虚拟选项卡中加载页面,因此一次只能生成一个)
代码如下:
import trio
import base64
import requests
from django.conf import settings
from trio_cdp import open_cdp, page, target
try:
import uwsgi
have_uwsgi = True
except ModuleNotFoundError:
have_uwsgi = False
async def render_pdf_task(url, params):
r = requests.get(url=settings.CDP_URL)
if r.status_code == 200:
out = r.json()
ws_url = out[0]['webSocketDebuggerUrl']
else:
return None
async with open_cdp(ws_url) as conn:
targets = await target.get_targets()
target_id = targets[0].target_id
async with conn.open_session(target_id) as session:
async with session.page_enable():
async with session.wait_for(page.LoadEventFired):
await page.navigate(url)
await trio.sleep(0.5)
pdf = await page.print_to_pdf(**params)
pdfdata = base64.b64decode(pdf[0])
await conn.aclose()
return pdfdata
def render_pdf(url, params):
if have_uwsgi:
uwsgi.lock(1)
pdfdata = trio.run(render_pdf_task, url, params)
if have_uwsgi:
uwsgi.unlock(1)
return pdfdata
恼人的是,任何具有 运行 这个特定任务的 uwsgi worker 稍后都会在退出时挂起,直到它被强行杀死。如果 uwsgi 运行s 并且没有人访问 PDF 生成页面,则所有 uwsgi worker 都正常退出。 运行 需要被杀死的 render_pdf 函数始终是 uwsgi worker。
例如,pid 20887 有 运行 render_pdf,后来当试图关闭 uwsgi 时,发生了这样的事情:
SIGINT/SIGQUIT received...killing workers...
worker 10 buried after 1 seconds
worker 9 buried after 1 seconds
worker 7 buried after 1 seconds
worker 6 buried after 1 seconds
worker 5 buried after 1 seconds
worker 4 buried after 1 seconds
worker 3 buried after 1 seconds
worker 2 buried after 1 seconds
worker 1 buried after 1 seconds
Tue Jan 25 22:44:42 2022 - worker 8 (pid: 20887) is taking too much time to die...NO MERCY !!!
worker 8 buried after 1 seconds
goodbye to uWSGI.
我该如何解决这个问题?非常感谢任何帮助:)
我自己解决了这个问题。 uWSGI 的 SIGINT
处理程序被 trio.run()
覆盖,但前提是 trio.run()
在主线程中。我在另一个线程中通过 运行 解决了这个问题。
我有一个 Django 站点,它使用 trio_cdp
包使用无头 Google Chrome 生成 PDF。这个包是异步的,但是我的 Django 项目是同步的,所以它必须在 trio.run()
它还使用 uwsgi 锁,这样一次只有一个客户端可以生成 PDF(无头 Chrome 在单个虚拟选项卡中加载页面,因此一次只能生成一个)
代码如下:
import trio
import base64
import requests
from django.conf import settings
from trio_cdp import open_cdp, page, target
try:
import uwsgi
have_uwsgi = True
except ModuleNotFoundError:
have_uwsgi = False
async def render_pdf_task(url, params):
r = requests.get(url=settings.CDP_URL)
if r.status_code == 200:
out = r.json()
ws_url = out[0]['webSocketDebuggerUrl']
else:
return None
async with open_cdp(ws_url) as conn:
targets = await target.get_targets()
target_id = targets[0].target_id
async with conn.open_session(target_id) as session:
async with session.page_enable():
async with session.wait_for(page.LoadEventFired):
await page.navigate(url)
await trio.sleep(0.5)
pdf = await page.print_to_pdf(**params)
pdfdata = base64.b64decode(pdf[0])
await conn.aclose()
return pdfdata
def render_pdf(url, params):
if have_uwsgi:
uwsgi.lock(1)
pdfdata = trio.run(render_pdf_task, url, params)
if have_uwsgi:
uwsgi.unlock(1)
return pdfdata
恼人的是,任何具有 运行 这个特定任务的 uwsgi worker 稍后都会在退出时挂起,直到它被强行杀死。如果 uwsgi 运行s 并且没有人访问 PDF 生成页面,则所有 uwsgi worker 都正常退出。 运行 需要被杀死的 render_pdf 函数始终是 uwsgi worker。
例如,pid 20887 有 运行 render_pdf,后来当试图关闭 uwsgi 时,发生了这样的事情:
SIGINT/SIGQUIT received...killing workers...
worker 10 buried after 1 seconds
worker 9 buried after 1 seconds
worker 7 buried after 1 seconds
worker 6 buried after 1 seconds
worker 5 buried after 1 seconds
worker 4 buried after 1 seconds
worker 3 buried after 1 seconds
worker 2 buried after 1 seconds
worker 1 buried after 1 seconds
Tue Jan 25 22:44:42 2022 - worker 8 (pid: 20887) is taking too much time to die...NO MERCY !!!
worker 8 buried after 1 seconds
goodbye to uWSGI.
我该如何解决这个问题?非常感谢任何帮助:)
我自己解决了这个问题。 uWSGI 的 SIGINT
处理程序被 trio.run()
覆盖,但前提是 trio.run()
在主线程中。我在另一个线程中通过 运行 解决了这个问题。