TL; DR
如何在单独的进程中安全地await
执行函数(在str
和int
作为参数并且不需要任何其他上下文)?
长篇故事
我有aiohtto.web
网络API使用Boost.Python
包装进行C++
扩展,在gunicorn
下运行(我打算在Heroku上部署它),由{{进行测试1}}。
关于扩展:它只有一个执行非阻塞操作的函数 - 接受一个字符串(和一个整数用于超时管理),用它进行一些计算并返回一个新字符串。对于每个输入字符串,它只是一个可能的输出(超时除外,但在这种情况下,必须引发locust
异常并由Boost.Python转换为与Python兼容的异常。)
简而言之,特定URL的处理程序执行以下代码:
C++
其中res = await loop.run_in_executor(executor, func, *args)
是executor
实例,ProcessPoolExecutor
-function来自C ++扩展模块。 (在实际项目中,此代码位于类的coroutine方法中,func
- 它func
仅执行classmethod
函数并返回结果)
捕获错误
当新请求到达时,我会通过C++
提取它的POST数据,然后将其存储到名为request.post()
的自定义类的实例中(因为我有不知道如何以另一种方式命名它)。因此Call
对象包含请求附带的所有输入数据(字符串),请求接收时间和唯一call
。
然后它进入名为id
的类(不是Handler
请求处理程序),将其传递给另一个类'内部有aiohttp
的方法。但loop.run_in_executor
有一个像中间件一样工作的日志系统 - 读取每个传入的Handler
对象的id和接收时间,并使用一条消息记录它,告诉你它刚开始执行,成功执行或获取麻烦。此外,call
具有Handler
并将所有错误存储在try/except
对象中,以便日志记录中间件知道发生了什么错误,或者返回了哪个输出扩展
测试
我有单元测试,只用这个代码创建256个协同程序,执行程序有256个工作程序,它运行良好。
但是当使用Locust进行测试时出现问题。我使用了4名Gunicorn工人和4名遗嘱执行人员进行这种测试。在某些时候应用程序刚开始返回错误的输出。
我的Locust的call
被配置为使用所有可用信息记录每个故障响应:输出字符串,错误字符串,输入字符串(由应用程序返回),id。所有模拟请求都是相同的,但TaskSet
对每个模拟请求都是唯一的。
将Gunicorn的id
选项设置为max_requests
请求时,情况会更好,但失败仍然存在。
有趣的是,有时我会触发"错误的输出"只需停止并启动Locust的测试就可以了。
我需要100%保证我的网络API能够正常运行。
更新&溶液
刚刚让我的队友回顾C ++代码 - 问题出在全局变量中。在某种程度上,对于256个并行协程来说,这不是一个问题,但是对于Gunicorn而言。