Forked and Threaded Servers

当使用Pyramid和一些流行的包时,分叉和线程服务器共享公共的“gotchas”和解决方案。

分叉的和线程化的服务器倾向于使用“写时复制”实现细节来优化它们的工作方式和共享内存。当某些操作在fork或thread分派之前发生时,例如打开文件或文件描述符或初始化随机数生成器时,这可能会产生问题。

许多服务器都有内置的Hook或事件,允许您轻松处理这些情况。

服务器

已知以下服务器具有内置Hook或事件来处理由“写时复制”问题引起的问题。此列表不完整;下面的一个省略并不意味着给定的服务器不受这些问题的影响,或者服务器不提供必要的Hook/事件。

Gunicorn

Gunicorn在应用程序生命周期中提供了几个Hook。

Postfork例程作为配置python脚本中的函数提供。

例如脚本 config.py 可能如下所示。

def post_fork(server, worker):
    log.debug("gunicorn - post_fork")

调用脚本如下所示。

gunicorn --paste production.ini -c config.py

documentation for the post_fork hook .

UWSGI

Uwsgi提供一个装饰来处理分叉。

您的应用程序应该包括如下代码。

1from uwsgidecorators import postfork
2
3@postfork
4def my_setup():
5    log.debug("uwsgi - postfork")

documentation for the postfork decorator .

Waitress

Waitress不是分叉服务器,但它的线程可以创建类似于分叉服务器的问题。

已知包

在分叉或线程服务器上部署时,已知以下包存在潜在问题。此列表不完整;下面的省略并不意味着给定的包不受这些部署问题的影响。

SQLAlchemy

许多人使用SQLAlchemy作为其Pyramid应用程序堆栈的一部分。

SQLAlchemy中的数据库连接和连接池在跨进程边界(分叉或线程)共享时不安全。连接和连接池是在第一次使用时懒惰地创建的,因此大多数Pyramid用户不会遇到问题,因为数据库交互通常基于每个请求进行。

但是,如果您的Pyramid应用程序在应用程序启动期间连接到数据库,则必须使用 Engine.dispose 重置连接。如下所示。

@postfork
def reset_sqlalchemy():
    models.engine.dispose()

有关此主题的其他文档可从SQLAlchemy的文档中获得。

PyCrypto

这个 PyCrypto 类库为 Crypto.Random.atfork 函数在进程分叉时重置伪随机数生成器。