내가 좋아하는 핸들러 aiohttp 웹 서버 응용 프로그램이 있습니다 app["db"]
는 (지금 문제, aiopg
, aioredis
하지 않습니다) 풀링 된 자원의 일종입니다CancelledError는 일반적인 aiohttp 웹 서버에서 어떻게 처리되어야합니까?
async def handler(request):
async with request.app["db"].acquire() as db:
row = await query(db)
return aiohttp.web.json_response(row)
. 이것은 오늘날까지 훌륭했습니다. 아무 이유없이 모든 클라이언트가
처럼 흔적으로 가득 시간 제한 및 응용 프로그램 로그에 의해 분리 시작[2017-05-21 17:58:24,254] ERROR [aiohttp.server] Error handling request
Traceback (most recent call last):
File "/virtualenv/lib/python3.6/site-packages/aiohttp/web_server.py", line 61, in handle_request
resp = yield from self._handler(request)
File "/virtualenv/lib/python3.6/site-packages/aiohttp/web.py", line 249, in _handle
resp = yield from handler(request)
File "/visio-longer/visio_longer/views/communicate/__init__.py", line 81, in legacy_communicate
async with request.app["db"].acquire() as db:
File "/virtualenv/src/aiopg/aiopg/utils.py", line 140, in __aenter__
self._conn = yield from self._coro
File "/virtualenv/src/aiopg/aiopg/sa/engine.py", line 162, in _acquire
raw = yield from self._pool.acquire()
File "/virtualenv/src/aiopg/aiopg/utils.py", line 67, in __iter__
resp = yield from self._coro
File "/virtualenv/src/aiopg/aiopg/pool.py", line 168, in _acquire
with (yield from self._cond):
File "/usr/lib/python3.6/asyncio/locks.py", line 67, in __iter__
yield from self.acquire()
File "/usr/lib/python3.6/asyncio/locks.py", line 176, in acquire
yield from fut
concurrent.futures._base.CancelledError
풀에서 데이터베이스 연결을 획득하면서
CancelledError
(타임 아웃에 의해 클라이언트 연결 해제)를 수신하고 여기에
요점 :
File "/visio-longer/visio_longer/views/communicate/__init__.py", line 81, in legacy_communicate
async with request.app["db"].acquire() as db:
을
나는 5 초마다 풀 상태 (size
및 freesize
)를 인쇄하는 코 루틴을 실행했으며 현재 풀에 충분한 연결이있었습니다!
시간의 조사 결과 풀의 컨텍스트 관리자 __atexit__
을 수행하는 동안 CancelledError
을 수신하면 풀에 연결을 반환하는 프로세스가 풀 오작동을 초래한다는 결론을 얻었습니다. 나는 asyncpg
에있는 그 행동을 고치고있는 commit을 찾았고, 에 awkward-looking fix을 만들었습니다. 이것의 아무도 도왔다 - 나는 아직도 aioredis
와 aiopg
둘 다에서 동일한 과실을 얻고 있었다. (인수, 리턴을 포함한
async def handler(request):
async def process():
async with request.app["db"].acquire() as db:
row = await query(db)
return aiohttp.web.json_response(asyncio.shield(process(row)))
그래서
이 중단 요청이 여전히 끝에 처리 된 :
상황
는asyncio.shield
으로 연결 풀을 사용하는 코드의 모든 조각을 포장하여
async def handler(request):
async with request.app["db"].acquire() as db:
row = await query(db)
return aiohttp.web.json_response(row)
를 대체하여 해결 리소스를 풀에 추가).
이 방법이 필요합니까? 이제 내 코드가 무서워 보이고 다음에 풀을 asyncio.shield
으로 감싸는 것을 잊지 않을 것이라는 보장은 없습니다. 이 문제를 해결하는 적절한 방법은 무엇입니까 (분명히 라이브러리는 스스로 해결할 수 없습니다)?
https://vorpus.org/blog/control -c-handling-in-python-and-trio/interesting. –