你好 gunicorn 维护者,
环境:
python 3.6.1
pyramid==1.9.2
2019 年 9 月 12 日,根据 Stack Overflow 的建议,我重构了内部pyramid
服务器的部署方式,将waitress
替换为gunicorn
:
https://stackoverflow.com/a/26872261/10491481
在进行内部 PR 时, gunicorn
的最新版本是 19.9.0。
今天我被要求再次审查实施,特别是测试我们的开发和生产CentOS 6.5
服务器上的更改。 我决定用我们的代码库中的一个新的git clone
来做这件事。
在我做 PR 的时候,我没有在setup.py
中指定gunicorn
的版本,因此当我今天运行pip install
时,它(意外)下载并安装gunicorn==20.0.0
。
不清楚为什么我在 $ [server:main]
development.ini
#$ 中的设置在启动时没有反映。
需要明确的是,在我们的development.ini
中使用以下设置:
[server:main]
use = egg:gunicorn#main
host = 0.0.0.0
port = 9090
workers = 1
worker_class = gevent
certfile=/etc/ssl/certs/current/webserver.cer
keyfile=/etc/ssl/certs/current/private.key.u
ca_certs=/etc/ssl/certs/current/intermediate.cert
gunicorn 19.9.0
:
$ gunicorn --version
gunicorn (version 19.9.0)
$ gunicorn --paste development.ini
[2019-11-12 12:42:59 -0800] [16733] [INFO] Starting gunicorn 19.9.0
[2019-11-12 12:42:59 -0800] [16733] [INFO] Listening at: https://0.0.0.0:9090 (16733)
[2019-11-12 12:42:59 -0800] [16733] [INFO] Using worker: gevent
[2019-11-12 12:42:59 -0800] [16744] [INFO] Booting worker with pid: 16744
gunicorn 20.0.0
$ gunicorn --version
gunicorn (version 20.0.0)
$ gunicorn --paste development.ini
[2019-11-12 12:45:28 -0800] [17295] [INFO] Starting gunicorn 20.0.0
[2019-11-12 12:45:28 -0800] [17295] [INFO] Listening at: http://127.0.0.1:8000 (17295)
[2019-11-12 12:45:28 -0800] [17295] [INFO] Using worker: sync
[2019-11-12 12:45:28 -0800] [17300] [INFO] Booting worker with pid: 17300
两个输出之间的注意事项:
gunicorn 20.0.0
的输出是http
)host
参数不再正确(使用默认127.0.0.1
而不是0.0.0.0
)port
参数不再正确(使用默认8000
而不是9090
)我查看了gunicorn 20.0.0
的更改日志:
http://docs.gunicorn.org/en/stable/news.html
但是似乎没有提到对--paste
参数的任何故意破坏性更改。
对于它的价值,如果我在命令行中使用gunicorn 20.0.0
传递我可以传递的参数,服务器将按预期启动:
$ gunicorn \
--paste development.ini \
-b 0.0.0.0:9090
--workers 1 \
--certfile /etc/ssl/certs/current/webserver.cer \
--keyfile /etc/ssl/certs/current/private.key.u
[2019-11-12 12:54:08 -0800] [18979] [INFO] Starting gunicorn 20.0.0
[2019-11-12 12:54:08 -0800] [18979] [INFO] Listening at: https://0.0.0.0:9090 (18979)
[2019-11-12 12:54:08 -0800] [18979] [INFO] Using worker: sync
[2019-11-12 12:54:08 -0800] [18985] [INFO] Booting worker with pid: 18985
任何有助于理解此问题的帮助将不胜感激。
如果我可以提供有关我的环境的更多详细信息以使其可重现,请告诉我。
谢谢,
科里
我很抱歉。 更改日志条目仅显示“简化粘贴部署文档”,我应该在这里帮助准备更好的新闻条目。
公关在这里: https ://github.com/benoitc/gunicorn/pull/1957
以前,我们已经弃用use = egg:gunicorn#main
,但它不再被弃用。 此更改旨在阐明 Gunicorn 在 Paste Deploy 兼容环境中的作用。
将 Gunicorn 与这种风格的.ini
文件一起使用有两种选择。
第一个选项是使用gunicorn
CLI。 执行此操作时,您必须使用 Gunicorn 自己的 CLI 标志或 Gunicorn 自己的配置模块(默认gunicorn.conf.py
)来配置服务器参数。 Gunicorn 绑定的套接字,管理重新加载,写入 PID 文件等。 Gunicorn 可以使用 $#$ .ini
$#$ 中的app
部分来配置应用程序可调用。
第二种选择是使用粘贴脚本运行器,例如pserve
。 在这种情况下,此脚本运行器管理重新加载、写入 PID 文件等。 大多数其他选项应该仍然有效,但是要使用.ini
文件的server
块,您需要调用与粘贴兼容的脚本运行器。 Gunicorn 不再是这样的脚本运行者。
让我知道是否可以增加更多清晰度。
在您的情况下,您应该能够像以前一样继续,但使用pserve
而不是gunicorn
来启动您的应用程序。 然后,Gunicorn 的所有服务器配置都可以在您的server
块中,就像您似乎已经完成的那样。
先前的行为可能会造成混淆,因为它允许在命令行上指定与文件冲突的选项。 我们还要求添加在.ini
文件中指定用于插值的配置变量的功能,并指定不同的server
块(除了不同的app
块)。 因此,决定弃用 Gunicorn 作为 Paste _server_ 运行程序,而不是尝试添加对所有这些功能的支持。 Gunicorn CLI 现在支持读取 Paste Deploy .ini
文件来构建应用程序,但使用server
块留给该生态系统中的专用工具。
在您的情况下,您应该能够像以前一样继续,但使用
pserve
而不是gunicorn
来启动您的应用程序。
感谢@tilgovi 的快速回复!
根据您的建议:
$ pserve development.ini
# ...
Starting server in PID 40148.
[2019-11-12 14:26:30 -0800] [40148] [INFO] Starting gunicorn 20.0.0
[2019-11-12 14:26:30 -0800] [40148] [INFO] Listening at: https://0.0.0.0:9090 (40148)
[2019-11-12 14:26:30 -0800] [40148] [INFO] Using worker: gevent
[2019-11-12 14:26:30 -0800] [40263] [INFO] Booting worker with pid: 40263
太好了,因为我打开的部分内部 PR 涉及必须将命令pserve
更改为gunicorn
,我有点担心,因为我不是我们的原始开发人员内部 API 服务器。
这解决了我的问题,请随时关闭此问题 =)
谢谢,
科里
最后一点,然后我想我已经添加了我能回忆起的所有细节。 即使 $# gunicorn --paste production.ini
server
块指定了egg:gunicorn#main
_!
由于 Gunicorn 主要是一个服务器和进程管理器,因此将 Gunicorn 用作调用任意粘贴兼容服务器的通用 CLI 是没有意义的。 相反,Gunicorn 是一个支持 Paste Deploy 应用程序的服务器,它是一个与 Paste 兼容的服务器。 不过,它_不是_ 一个粘贴脚本运行器 CLI!
我为此在 Pyramid 食谱上打开了一个问题: https ://github.com/Pylons/pyramid_cookbook/issues/222
我以为我已经在 Gunicorn 中彻底记录了这一点,但一开始我找不到参考资料。 它在这里: http ://docs.gunicorn.org/en/stable/run.html#paste -deployment
@tilgovi 提醒一下,这对我的团队来说也是一个重大变化。 也许值得转移到变更日志的重大变更部分?
我将重新打开问题并自行分配。 当我更新变更日志以使其在此处更清晰时,我将关闭它。
再次,我很抱歉最初没有在变更日志中更清楚地指出它。
@tilgovi颠簸
请让我知道这是否应该作为一个单独的问题打开。
这可能是我们代码库的一个孤立问题,但经过更多测试后,我的团队注意到对于我们的 API 服务器, gunicorn 20.0.0
破坏了函数pyramid_ldap3.get_ldap_connector
。
gunicorn 20.0.0
:$ pip list | grep gunicorn
gunicorn 20.0.0
$ pserve bioapps/development.ini
[2019-11-20 15:55:30 -0800] [9902] [INFO] Starting gunicorn 20.0.0
[2019-11-20 15:55:30 -0800] [9902] [INFO] Listening at: https://0.0.0.0:10999 (9902)
[2019-11-20 15:55:30 -0800] [9902] [INFO] Using worker: gevent
[2019-11-20 15:55:30 -0800] [10034] [INFO] Booting worker with pid: 10034
/home/colim/Projects/bioapps/bioapps.api.ssl/centos7venv/lib/python3.6/site-packages/gunicorn/workers/ggevent.py:53: MonkeyPatchWarning: Monkey-patching ssl after ssl has already been imported may lead to errors, including RecursionError on Python 3.6. It may also silently lead to incorrect behaviour on Python 3.7. Please monkey-patch earlier. See https://github.com/gevent/gevent/issues/1016. Modules that had direct imports (NOT patched): ['urllib3.util.ssl_ (/home/colim/Projects/bioapps/bioapps.api.ssl/centos7venv/lib/python3.6/site-packages/urllib3/util/ssl_.py)', 'urllib3.util (/home/colim/Projects/bioapps/bioapps.api.ssl/centos7venv/lib/python3.6/site-packages/urllib3/util/__init__.py)'].
monkey.patch_all()
[2019-11-20 15:57:54,189] INFO [access:342][DummyThread-1] 10.9.202.54 - - "POST https://bioappsdev02.bcgsc.ca:10999/session HTTP/1.1" {'username': 'colim', 'password': ''}
[2019-11-20 15:57:57,276] ERROR [exc_logger:114][DummyThread-1] 'https://bioappsdev02.bcgsc.ca:10999/session'
Traceback (most recent call last):
File "/home/colim/Projects/bioapps/bioapps.api.ssl/centos7venv/lib/python3.6/site-packages/pyramid/tweens.py", line 39, in excview_tween
response = handler(request)
File "/home/colim/Projects/bioapps/bioapps.api.ssl/centos7venv/lib/python3.6/site-packages/pyramid/router.py", line 156, in handle_request
view_name
File "/home/colim/Projects/bioapps/bioapps.api.ssl/centos7venv/lib/python3.6/site-packages/pyramid/view.py", line 642, in _call_view
response = view_callable(context, request)
File "/home/colim/Projects/bioapps/bioapps.api.ssl/centos7venv/lib/python3.6/site-packages/pyramid/config/views.py", line 181, in __call__
return view(context, request)
File "/home/colim/Projects/bioapps/bioapps.api.ssl/centos7venv/lib/python3.6/site-packages/pyramid/viewderivers.py", line 390, in attr_view
return view(context, request)
File "/home/colim/Projects/bioapps/bioapps.api.ssl/centos7venv/lib/python3.6/site-packages/pyramid/viewderivers.py", line 368, in predicate_wrapper
return view(context, request)
File "/home/colim/Projects/bioapps/bioapps.api.ssl/centos7venv/lib/python3.6/site-packages/pyramid/viewderivers.py", line 439, in rendered_view
result = view(context, request)
File "/home/colim/Projects/bioapps/bioapps.api.ssl/centos7venv/lib/python3.6/site-packages/pyramid/viewderivers.py", line 148, in _requestonly_view
response = view(request)
File "/home/colim/Projects/bioapps/bioapps.api.ssl/centos7venv/lib/python3.6/site-packages/cornice/service.py", line 493, in wrapper
response = view_(request)
File "/home/colim/Projects/bioapps/bioapps.api.ssl/bioapps/api/endpoints/session.py", line 139, in session_post
username, request.validated['password'], request,
File "/home/colim/Projects/bioapps/bioapps.api.ssl/bioapps/api/endpoints/session.py", line 27, in get_ldap_groups
auth = connector.authenticate(username, password)
File "/home/colim/Projects/bioapps/bioapps.api.ssl/centos7venv/lib/python3.6/site-packages/pyramid_ldap3/__init__.py", line 208, in authenticate
password=escape_for_search(password))
File "/home/colim/Projects/bioapps/bioapps.api.ssl/centos7venv/lib/python3.6/site-packages/pyramid_ldap3/__init__.py", line 82, in execute
with manager.connection() as conn:
File "/home/colim/Projects/bioapps/bioapps.api.ssl/centos7venv/lib/python3.6/site-packages/pyramid_ldap3/__init__.py", line 165, in connection
auto_bind=True, lazy=False, read_only=True)
File "/home/colim/Projects/bioapps/bioapps.api.ssl/centos7venv/lib/python3.6/site-packages/ldap3/core/connection.py", line 326, in __init__
self.do_auto_bind()
File "/home/colim/Projects/bioapps/bioapps.api.ssl/centos7venv/lib/python3.6/site-packages/ldap3/core/connection.py", line 343, in do_auto_bind
self.bind(read_server_info=True)
File "/home/colim/Projects/bioapps/bioapps.api.ssl/centos7venv/lib/python3.6/site-packages/ldap3/core/connection.py", line 585, in bind
_, result = self.get_response(response)
File "/home/colim/Projects/bioapps/bioapps.api.ssl/centos7venv/lib/python3.6/site-packages/ldap3/strategy/base.py", line 370, in get_response
raise LDAPResponseTimeoutError('no response from server')
ldap3.core.exceptions.LDAPResponseTimeoutError: no response from server
[2019-11-20 15:57:57,298] INFO [access:362][DummyThread-1] 10.9.202.54 - - "POST https://bioappsdev02.bcgsc.ca:10999/session HTTP/1.1" 500 206
gunicorn 19.9.0
$ pip install gunicorn==19.9.0
Collecting gunicorn==19.9.0
Using cached https://files.pythonhosted.org/packages/8c/da/b8dd8deb741bff556db53902d4706774c8e1e67265f69528c14c003644e6/gunicorn-19.9.0-py2.py3-none-any.whl
Installing collected packages: gunicorn
Found existing installation: gunicorn 20.0.0
Uninstalling gunicorn-20.0.0:
Successfully uninstalled gunicorn-20.0.0
Successfully installed gunicorn-19.9.0
$ pip list | grep unicorn
gunicorn 19.9.0
$ gunicorn --paste bioapps/development.ini
[2019-11-20 16:03:45 -0800] [12015] [INFO] Starting gunicorn 19.9.0
[2019-11-20 16:03:45 -0800] [12015] [INFO] Listening at: https://0.0.0.0:10999 (12015)
[2019-11-20 16:03:45 -0800] [12015] [INFO] Using worker: gevent
[2019-11-20 16:03:45 -0800] [12018] [INFO] Booting worker with pid: 12018
[2019-11-20 16:04:39,292] INFO [access:342][DummyThread-1] 10.9.202.54 - - "POST https://bioappsdev02.bcgsc.ca:10999/session HTTP/1.1" {'username': 'colim', 'password': ''}
[2019-11-20 16:04:39,527] INFO [access:362][DummyThread-1] 10.9.202.54 - - "POST https://bioappsdev02.bcgsc.ca:10999/session HTTP/1.1" 200 639
在gunicorn 20.0.0
和gunicorn 19.9.0
development.ini
进行任何更改。
有趣的是,如果我们使用以下命令启动服务器,我们可以使用gunicorn 20.0.0
停止错误:
$ pip list | grep unicorn
gunicorn 20.0.0
$ gunicorn --paste bioapps/development.ini -b 0.0.0.0:8999 --workers 1 --certfile /etc/ssl/certs/current/webserver.cer --keyfile /etc/ssl/certs/current/private.key.u
[2019-11-20 16:14:27 -0800] [14783] [INFO] Starting gunicorn 20.0.0
[2019-11-20 16:14:27 -0800] [14783] [INFO] Listening at: https://0.0.0.0:8999 (14783)
[2019-11-20 16:14:27 -0800] [14783] [INFO] Using worker: sync
[2019-11-20 16:14:27 -0800] [14798] [INFO] Booting worker with pid: 14798
[2019-11-20 16:16:39,550] INFO [access:342][MainThread] 10.9.202.54 - - "POST https://bioappsdev02.bcgsc.ca:8999/session HTTP/1.1" {'username': 'colim', 'password': ''}
[2019-11-20 16:16:39,768] INFO [access:362][MainThread] 10.9.202.54 - - "POST https://bioappsdev02.bcgsc.ca:8999/session HTTP/1.1" 200 639
我不确定它是否相关,但使用gunicorn 20.0.0
和pserve
启动服务器是我们唯一看到此警告的时间:
/home/colim/Projects/bioapps/bioapps.api.ssl/centos7venv/lib/python3.6/site-packages/gunicorn/workers/ggevent.py:53: MonkeyPatchWarning: Monkey-patching ssl after ssl has already been imported may lead to errors, including RecursionError on Python 3.6. It may also silently lead to incorrect behaviour on Python 3.7. Please monkey-patch earlier. See https://github.com/gevent/gevent/issues/1016. Modules that had direct imports (NOT patched): ['urllib3.util.ssl_ (/home/colim/Projects/bioapps/bioapps.api.ssl/centos7venv/lib/python3.6/site-packages/urllib3/util/ssl_.py)', 'urllib3.util (/home/colim/Projects/bioapps/bioapps.api.ssl/centos7venv/lib/python3.6/site-packages/urllib3/util/__init__.py)'].
monkey.patch_all()
@tilgovi您会在更改日志中更改什么?
@benoitc我想呼吁在 Gunicorn CLI 中删除对 Paste Deploy 服务器定义的支持。 我今天可以做到这一点。
如果我追溯修改更改日志以使其更清晰(在 20.0 版本中进行重大更改部分),是否可以?
@CorreyL有趣! 您绝对可以使用命令行上指定的选项运行gunicorn
。 我认为这是运行gunicorn
的首选和最安全的方式。 与pserve
的集成很方便,但很高兴知道它会在这里引起问题。 我希望我没有错误地取消弃用它。
如果我追溯修改更改日志以使其更清晰(在 20.0 版本中进行重大更改部分),是否可以?
@tilgovi是的
@tilgovi您今天可以添加此更改吗? 拥有 20.0.1 会很酷 :)
在 c25563f 中添加了一行注释。 自更改发生以来,文档已经更新。 希望任何看到该注释的人都能找到文档和这些问题。 😅
@tilgovi谢谢
只是想添加另一个确认受到此意外影响。 就我而言,这并不是很重要,但我很困惑为什么 gunicorn 自升级以来停止在 dev 中自动重新加载以及其他一些小的行为变化。 我今天花了一些时间试图弄清楚,并意识到我的--paste
INI 文件中的设置不再有效,这帮助我找到了解决这个问题的方法。
我不知道这是否可行,但是如果 gunicorn 检测到您仍在尝试通过 Paster 文件设置服务器参数,是否可以让 gunicorn 输出警告?
我为中断道歉,@Deimos。 我会审查 PR,但我没有具体计划在这里添加更多内容。
如果您实际上想将 --paste 与 --config 一起使用,情况如何? 在我们的例子中(RhodeCode),对于我们在 gunicorn 配置中获得的内存监控的特殊逻辑来说,这是一个很大的要求。
@marcinkuzminski这是理想的用例。 只需指定--paste
和--config
。 但是,Gunicorn 不会读取粘贴 ini 文件的“服务器”部分,因为期望您将在 gunicorn 配置文件中配置服务器。
那真不幸。
我们在安装程序中将 gunicorn 发送给客户,所有逻辑和配置都已委托给 .ini 文件。 这也是 Internet 上大多数示例为 Pyramid 项目指定的方式。
这种变化打破了这一点,我们可能更容易分叉 gunicorn 以将其恢复,然后将逻辑和委托配置更改为 gunicorn_conf.py :(
如果使用特殊前缀读取 --paste 选项呢? 例如,您可以使用 --paste 配置 gunicorn,但它只会读取以gunicorn.
为前缀的配置选项
例如
gunicorn.workers = 2
gunicor.XXX = YYY
您不需要使用--config
。 您可以完全使用粘贴 INI。 为此使用pserve
而不是gunicorn
。 请参阅文档: https: //docs.gunicorn.org/en/stable/run.html#paste -deployment
所做的更改只是删除了对使用 Gunicorn 作为可以运行服务器的通用粘贴部署 CLI 的支持。 Gunicorn 仍然_是一个_粘贴兼容服务器本身。
进行此更改是为了消除.ini
文件将在其server
块中指定服务员或任何其他服务器的潜在混淆,但使用gunicorn --paste production.ini
运行它实际上不会使用女服务员。 人们还经常要求能够指定除server:main
之外的备用server
块。 当像pserve
这样完美的 CLI 存在时,保持对这些功能的支持似乎没有意义。
gunicorn
CLI 可以从 INI 文件中读取应用程序定义,但它使用自己的配置文件来配置服务器。 如果您想使用 INI 文件来配置 Gunicorn 服务器,请使用另一个工具(如pserve
)作为脚本/进程运行器。
但根据我的第一条评论,我们必须将 --config 与 --paste 一起使用。
在我们的项目中,一切都由单个配置文件 (.ini) 管理。有很多升级/自动缩放逻辑只是调整 .ini 文件。 然后我们也使用 --config 来指定一个自定义的 python 配置来设置
Gunicorn 是 Paste 兼容的,但这种方式的功能受到限制,它给我们带来了一个问题,我们无法从中恢复,因为我们不能有 2 个配置文件,而且移动到另一个文件上的配置比实际分叉更多的工作Gunicorn 并维护该分叉只是为了恢复这种行为。
我知道这张票的基本原理,但我们曾经一起使用 gunicorn 和 waitress,我认为运行 gunicorn 二进制文件已经足够明确了,恕我直言。 此外,我认为您甚至可以检测用户是否使用不同的鸡蛋并使其成为硬错误。
如果我记得的话,我们没有考虑过这种用法。 我们可能可以带回来
作为用例的支持听起来不错。 有一个可以吗
记录警告吗?
2020 年 10 月 16 日星期五 08:28 Marcin Kuźmiński [email protected]
写道:
但我们必须将 --config 与 --paste 一起使用,根据我的第一次
评论。
在我们的项目中,一切都由单个配置文件(.ini)管理
有很多升级/自动缩放逻辑只是调整 .ini 文件。
然后我们也使用 --config 来指定一个自定义的 python 配置来设置
- 自定义记录器格式(这在技术上是不可能的
使用 .ini 文件指定)- 工作者内存管理
Gunicorn 是粘贴兼容的,但是这样限制了功能,
它给我们带来了一个我们无法恢复的问题。我知道原因,但我们曾经一起使用gunicorn和服务员,
我认为运行 gunicorn 二进制文件已经足够明确了,恕我直言。—
你收到这个是因为你被提到了。
直接回复此邮件,在 GitHub 上查看
https://github.com/benoitc/gunicorn/issues/2169#issuecomment-709838842 ,
或退订
https://github.com/notifications/unsubscribe-auth/AAADRIQR2CLVUOYK6FDY2ZDSK7RZFANCNFSM4JMI65YA
.>
从我的手机发送
如果可能的话,我实际上考虑了另一种解决方案。 将 pserve 与 unicorn egg 一起使用时,最好将配置文件设置在 .ini 文件中。
例如
use = egg:gunicorn#main
workers = 2
config = /path/to/gunicorn_conf.py
所以它会像 --config=/path/to/gunicorn_conf.py 一样加载 gunicorn_conf.py
所以上面对我们有用,它也解决了这张票的问题。 不确定实施起来有多容易和可行。
否则,如果您可以在运行 gunicorn 二进制文件时带来从 .ini 文件加载配置的功能,那就太棒了,这将为我们省去很多麻烦。 有一个警告是没有问题的
如果可能的话,我实际上考虑了另一种解决方案。 将 pserve 与 unicorn egg 一起使用时,最好将配置文件设置在 .ini 文件中。
这应该有效并记录在案。 如果没有,请提交错误!
好的,我们会检查这个。 但是 AFAIR 在 gunicorn 与 pserve 二进制文件的工作方式上有细微的变化。 如果我记得, gunicorn --paste 可以访问 .ini 文件路径,而 pserve 使用 gunicorn egg 没有。 如果需要,我们会检查并打开相关票证。
最有用的评论
我将重新打开问题并自行分配。 当我更新变更日志以使其在此处更清晰时,我将关闭它。
再次,我很抱歉最初没有在变更日志中更清楚地指出它。