当前位置: 首页 > 知识库问答 >
问题:

如何取消错误的应该在典型的aiohttp网络服务器中处理?

方鸿振
2023-03-14

我有一个aiohttp web服务器应用程序,其处理程序如下:

async def handler(request):
    async with request.app["db"].acquire() as db:
        row = await query(db)

    return aiohttp.web.json_response(row)

其中,app[“db”]是某种集合资源(aiopgaioredis,现在无关紧要)。这在今天之前一直很有效。无缘无故,所有客户端都会在超时时开始断开连接,并且应用程序日志中充满了如下跟踪

[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

这里的关键点是,在从池中获取数据库连接时,它正在接收CanceledError(客户端因超时而断开连接):

  File "/visio-longer/visio_longer/views/communicate/__init__.py", line 81, in legacy_communicate
    async with request.app["db"].acquire() as db:

我有一个协程运行,每5秒钟打印一次池状态(sizeFreesize),目前池中有很多免费连接!

经过数小时的调查,理论上认为,在执行池的上下文管理器时接收到CanceledError\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。我在asyncpg中发现了一个用于修复该行为的commit,aioredis包含类似的html" target="_blank">代码,我还对aiopg进行了一个外观笨拙的修复。所有这些都没有帮助-我仍然从aioredisaiopg中得到相同的错误。

这种情况通过替换来解决

async def handler(request):
    async with request.app["db"].acquire() as db:
        row = await query(db)

    return aiohttp.web.json_response(row)

通过使用asyncio包装使用连接池的每段代码。屏蔽

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包装我的池。屏蔽。解决这个问题的正确方法是什么(显然图书馆自己无法解决)?

共有1个答案

滑文昌
2023-03-14

我看不出这与任何其他例外有什么不同<代码>取消错误只是另一个错误。您的所有上下文管理器退出函数都会运行,因此它们应该有机会释放资源。这看起来像是某种与连接池中的锁相关的未来被取消了。这似乎有问题,似乎应该与被取消的客户端连接无关。我假设有一个与正在进行的请求相对应的协同路由,并且当连接丢失时应该取消该协同路由。调用任务。cancel将在协同程序内引发CanceledError。假设CanceledError最终从协同程序中引发,那么任务的结果将是CanceledError。然而,我不明白锁相关的未来是如何被取消的。

如果您正在等待上下文管理器、finally块或其他清理代码的退出函数中的某些内容,则可能需要更加小心。例如,如果您需要退出函数中的锁来返回某些资源,那么您可能需要一个while循环来捕获CanceledError(并最终重新引发它)或使用async。盾我只会围绕退出函数/清理处理程序中的特定代码,而不是围绕整个请求。此外,考虑是否使用回调来返回资源(通过<代码> Ro.Call Simuly)可能是一个更好的选择,而不是等待在侧清理代码中。如果清理代码未等待,则无法在其中引发新的CanceledError。上下文管理器退出功能和最终块可能由CanceledError在其他地方触发,即使它们不等待,但这与任何其他异常都没有区别

 类似资料:
  • 每次我尝试用截击的POST方法时,我都会犯严重的错误。我在getCause中得到null值,在getNetworkResponse中得到一些默认值。toString()。 如果我使用GET方法,这工作正常(我从我的网址得到响应)。 有人能帮忙吗?我能做什么? 错误日志: 错误:错误:com.android.volley.服务器错误 更新:networkResponse。statusCode是404

  • 问题内容: 我正在向我的API发出请求,并且正在使用AngularJS $ resource模块。它与$ http不同,因此我不知道如何处理错误。 我的服务: 我的控制器: 我想要类似这样的东西..如果我的API无法正常工作,我不知道如何处理错误。 问题答案: 您可以将错误处理程序作为第二个参数传递给。 编辑: 为了使事情更清楚一些,例如:

  • Twisted Twisted 是一个事件驱动的网络引擎。他可以被用来构建多种网络协议的应用程序,包括:HTTP 服务器和客户端;使用 SMTP、POP3、IMAP 或者 SSH 协议测应用程序和 IM (即时消息)等应用 更多。 PyZMQ PyZMQ 是 ZeroMQ 的 Python 绑定。ZeroMQ 是一个高性能的异步消息库,它的一个很大的优势在于其可以被用作一个消息队列而不需要消息代理

  • 问题内容: 我有一个新编码的GWT / GAE应用,该应用在客户端上使用RequestFactory和Editors,在背面使用自定义的Objectify DAO服务。 flush()然后persist()路径在成功时可以正常工作。客户端JSR 303也可以正常工作。 我的问题是如何触发服务器警告/错误并处理UI更新? 我在http://turbomanage.wordpress.com/2010

  • 问题内容: 我想用纯Java实现我自己的Web服务器,该Web服务器应仅支持静态资源(即html,js,css,图片,电影等)。 您能推荐有关如何实现这种事情的教程或文章吗?我应该使用几个进程或线程池,还是应该考虑像NodeJS这样的面向循环事件的对象? 我知道有一些免费的网络服务器可以完全满足我的需求,但我想以此为自己的锻炼。 问题答案: 我建议您熟悉HTTP请求格式http://datatra

  • 有人知道netty服务器处理程序取消从web服务器接收数据的最佳方法吗?我有一个服务器处理程序,它将HttpRequests代理到web服务器。但是,当请求客户端取消请求时,我希望在不关闭服务器处理程序和web服务器之间的连接的情况下停止从web服务器接收服务器通道上的数据。 有谁知道我怎么才能做到这一点。你的答复将不胜感激。 非常感谢。