uWSGI + 构建 Go .so 不工作

uWSGI + builded Go .so not working

问题: .so(shared object) as library in python 在 python 调用它时运行良好但在 uWSGI-[=81= 中失败]ning python(Django) 应用程序。

更多信息:我使用 go build -buildmode=c-shared -o output.so input.go 构建了 Go 模块,以便在 Python 中使用

调用它
from ctypes import cdll

lib = cdll.LoadLibrary('path_to_library/output.so')

当通过 uWSGI 提供 django 项目时,调用 Go 库 的请求处理程序冻结,导致 Nginx 中的未来 504。进入"so called freeze"后,uWSGI就被锁在那里,只有重启才能让app活跃起来。完全没有日志!它只是冻结。

当我在同一台机器上 python 解释器 运行 时,一切正常。

我的想法:我试过调试它并在库中放置了很多日志消息,但它不会提供太多信息,因为库一切正常(因为它适用于解释器)。库加载正确,因为我已将一些日志消息放入库中。我认为这是某种 uWSGI 限制。我不认为放置 uwsgi.ini 文件有什么帮助。

附加信息:

uWSGI 在这种类型的共享对象工作中有哪些限制,是否有办法克服这些限制?

首先,您是否绝对确定需要从 uWSGI 进程将 Go 作为库调用?

uWSGI 通常用于 PHP、Python、Ruby 等解释型语言。它引导解释器并管理 master/worker 进程来处理请求。在 Go 库上使用它似乎很奇怪。

您提到将 nginx 作为您的网络服务器,为什么不直接使用您的 Go 程序作为 http 服务器(它做得很好)并直接使用它从 nginx 调用它 URL:

location /name/ {
    proxy_pass http://127.0.0.1/go_url/;
}

See nginx docs.

如果你真的想通过 .so 模块将 Go 作为 python 导入的库使用,你必须知道 Go 有自己的运行时、线程管理,并且可能无法与处理 threads/processes 以不同的方式。在这种情况下,我无法帮助您,因为我从未真正尝试过。

如果你能澄清你的问题,你实际上想做什么,我们可能会更有帮助地回答。

尝试与思考

我试图避免共享库与我的 python 代码分离,因为它需要至少一个进程的支持,而且我将不得不重写一些库来创建新的 api.

由于 请注意:

Go has its own runtime, thread management and may not work well with uWSGI which handles threads/processes in a different way

因为 uWSGI 是我开始在那里寻找解决方案的问题。希望之一是安装 GCCGO uWSGI plugin 以某种方式解决该问题。但即使在旧操作系统上也很难安装,因为它缺少 pre-builded 插件,手动构建也不太顺利,它没有帮助,没有任何改变,它仍然冻结。

然后我想我不想禁用协程和那种与 uWSGI 不同的东西,我能做的改变之一是设置 GOMAXPROCS

GOMAXPROCS sets the maximum number of CPUs that can be executing simultaneously and returns the previous setting. If n < 1, it does not change the current setting. The number of logical CPUs on the local machine can be queried with NumCPU. This call will go away when the scheduler improves.

而且效果非常好!!!

解决方案

import (
    ...
    "runtime"
)
...
//export yourFunc
func yourFunc(yourArgs argType) {
    runtime.GOMAXPROCS(1)
    ...
}

我的 在某些情况下有效。但是,当我尝试 运行 另一台服务器上的相同项目时,相同的 OS、相同的 Python、相同的 uWSGI(版本、插件、配置文件)、相同的要求、相同的 .so 文件, 它冻结了我在回答中描述的保存方式。

我个人不希望 运行 这作为单独的进程并将其绑定到 socket/port 并创建 API 用于与共享库通信。

解决方法:

只需要单独的过程。 运行 与 celery.

一些注意事项:

1.You 无法使用 task.apply() 运行 任务,因为它在主应用程序中是 运行,而不是 celery:

result = task.apply_async()
while result.ready():
    time.wait(5)

2.You 需要 运行 celerysolo 执行池

celery -A app worker -P solo