Gunicorn 动态反映更改的代码
Gunicorn reflect changed code dynamically
我正在开发一个 django web 应用程序,用户可以在应用程序本身中修改某些 类 的代码,通过 UI 使用 ace editor(认为是 gitlab/github 在那里你可以在线更改代码)。但是这些 类 是 django 和 celery worker 在某些时候 运行。
保存代码更改后,由于 gunicorn,django 不会选择这些更改,但由于 celery 的过程不同,因此可以正常工作。 (运行 它在本地使用 runserver
工作正常并且 django 和 celery 都选择了更改)。
有没有办法让 gunicorn 在不重新加载整个应用程序的情况下反映包含 类 的特定目录的更改?如果需要重新加载,有没有办法在不停机的情况下一个接一个地重新加载 gunicorn 的工人?
gunicron 命令:
/usr/local/bin/gunicorn config.wsgi --bind 0.0.0.0:5000 --chdir=/app
wsgi配置文件:
import os
import sys
from django.core.wsgi import get_wsgi_application
app_path = os.path.abspath(os.path.join(
os.path.dirname(os.path.abspath(__file__)), os.pardir))
sys.path.append(os.path.join(app_path, 'an_application'))
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.production")
application = get_wsgi_application()
重新加载选项“用于开发”。没有强硬的措辞说你不应该在生产中使用它。您不应该在生产中使用它的原因是因为人们会打错字,更改一个文件,可能需要对其他文件进行其他几处更改,等等。因此,您可以使您的网站无法访问,然后您就没有可用的应用程序再次修复它。
对于开发人员来说,这没有问题,因为您可以查看 shell 中的 logs/output 并重新启动它。这就是为什么@Krzysztof 的建议是最好的。将代码更改推送到您的存储库,使其通过 CI/CD 并切换 pod。如果 CI 失败,那么 CD 不会发生,所以你很好。
当然,对于问答网站来说,这个范围太大了。
为什么不将代码保存在单独的文本文件或数据库中,相关方法可以简单地将代码作为字符串动态加载并使用 exec()
执行?
假设您有一个可以由用户编辑的函数 function1
。当用户提交更改时,处理输入(将函数分开,以便您知道哪个函数有什么定义),并将它们全部单独保存,如 function1
、function2
等,在数据库中或作为字符串的文本文件。
你需要执行一个 function1
,只需加载你保存的值并使用 exec
来执行代码。
这样,您就不需要重新加载 gunicorn
,因为所有 worker 总是会在 运行 时间获取更新的函数定义!
行中的内容:
def function1_original():
# load function definition
f = open("function1.txt", "r")
# execute the string
exec(f.read()) # this will just load the function definition
function1() # this will execute the user defined function
因此用户将定义:
def function1():
# user defined code
# blah blah
...
我能够通过将 python 脚本的扩展名更改为除 .py
以外的任何内容来解决这个问题
然后我使用以下函数加载了这些文件:
from importlib import util
from immportlib.machinary import SourceFileLoader
def load_module(module_name, modele_path):
module_path = path.join(path.dirname(__file__), "/path/to/your/files{}.anyextension".format(module_name))
spec = util.spec_from_loader(module_name,
SourceFileLoader(module_name, module_path))
module = util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
在这种情况下,它们不是由 Gunicorn 在 RAM 中加载的,我能够即时应用更改而无需应用 eval
或 exec
函数。
我正在开发一个 django web 应用程序,用户可以在应用程序本身中修改某些 类 的代码,通过 UI 使用 ace editor(认为是 gitlab/github 在那里你可以在线更改代码)。但是这些 类 是 django 和 celery worker 在某些时候 运行。
保存代码更改后,由于 gunicorn,django 不会选择这些更改,但由于 celery 的过程不同,因此可以正常工作。 (运行 它在本地使用 runserver
工作正常并且 django 和 celery 都选择了更改)。
有没有办法让 gunicorn 在不重新加载整个应用程序的情况下反映包含 类 的特定目录的更改?如果需要重新加载,有没有办法在不停机的情况下一个接一个地重新加载 gunicorn 的工人?
gunicron 命令:
/usr/local/bin/gunicorn config.wsgi --bind 0.0.0.0:5000 --chdir=/app
wsgi配置文件:
import os
import sys
from django.core.wsgi import get_wsgi_application
app_path = os.path.abspath(os.path.join(
os.path.dirname(os.path.abspath(__file__)), os.pardir))
sys.path.append(os.path.join(app_path, 'an_application'))
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.production")
application = get_wsgi_application()
重新加载选项“用于开发”。没有强硬的措辞说你不应该在生产中使用它。您不应该在生产中使用它的原因是因为人们会打错字,更改一个文件,可能需要对其他文件进行其他几处更改,等等。因此,您可以使您的网站无法访问,然后您就没有可用的应用程序再次修复它。
对于开发人员来说,这没有问题,因为您可以查看 shell 中的 logs/output 并重新启动它。这就是为什么@Krzysztof 的建议是最好的。将代码更改推送到您的存储库,使其通过 CI/CD 并切换 pod。如果 CI 失败,那么 CD 不会发生,所以你很好。
当然,对于问答网站来说,这个范围太大了。
为什么不将代码保存在单独的文本文件或数据库中,相关方法可以简单地将代码作为字符串动态加载并使用 exec()
执行?
假设您有一个可以由用户编辑的函数 function1
。当用户提交更改时,处理输入(将函数分开,以便您知道哪个函数有什么定义),并将它们全部单独保存,如 function1
、function2
等,在数据库中或作为字符串的文本文件。
你需要执行一个 function1
,只需加载你保存的值并使用 exec
来执行代码。
这样,您就不需要重新加载 gunicorn
,因为所有 worker 总是会在 运行 时间获取更新的函数定义!
行中的内容:
def function1_original():
# load function definition
f = open("function1.txt", "r")
# execute the string
exec(f.read()) # this will just load the function definition
function1() # this will execute the user defined function
因此用户将定义:
def function1():
# user defined code
# blah blah
...
我能够通过将 python 脚本的扩展名更改为除 .py
然后我使用以下函数加载了这些文件:
from importlib import util
from immportlib.machinary import SourceFileLoader
def load_module(module_name, modele_path):
module_path = path.join(path.dirname(__file__), "/path/to/your/files{}.anyextension".format(module_name))
spec = util.spec_from_loader(module_name,
SourceFileLoader(module_name, module_path))
module = util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
在这种情况下,它们不是由 Gunicorn 在 RAM 中加载的,我能够即时应用更改而无需应用 eval
或 exec
函数。