dar*_*roo 79 django multiprocessing
背景:
我正在使用一个使用Django和Postgres数据库的项目.我们也在使用mod_wsgi以防万一,因为我的一些网络搜索提到了它.在Web表单提交中,Django视图启动了一项需要花费大量时间的工作(超过用户想要等待的时间),因此我们在后台通过系统调用启动工作.现在运行的作业需要能够读取和写入数据库.因为这项工作需要很长时间,所以我们使用多处理来并行运行部分工作.
问题:
顶级脚本具有数据库连接,当它生成子进程时,似乎父级的连接可供子级使用.然后有一个例外,关于如何在查询之前调用SET TRANSACTION ISOLATION LEVEL.研究表明,这是因为尝试在多个进程中使用相同的数据库连接.我发现一个线程建议在子进程的开头调用connection.close(),这样Django会在需要时自动创建一个新连接,因此每个子进程都有一个唯一的连接 - 即不共享.这对我来说不起作用,因为在子进程中调用connection.close()会导致父进程抱怨连接丢失.
其他调查结果:
我读过的一些东西似乎表明你不能真正做到这一点,而且多处理,mod_wsgi和Django不能很好地结合在一起.我觉得这似乎很难相信.
有人建议使用芹菜,这可能是一个长期的解决方案,但我目前无法安装芹菜,等待一些批准程序,所以现在不是一个选项.
在SO和其他地方找到了关于持久数据库连接的几个参考资料,我认为这是一个不同的问题.
还找到了关于psycopg2.pool和pgpool的引用以及关于bouncer的内容.不可否认,我不理解我正在阅读的大部分内容,但它肯定不会像我一样对我跳出来.
目前的"解决方案":
就目前而言,我已经恢复了只是连续运行的东西,它可以工作,但比我想要的慢.
关于如何使用多处理并行运行的任何建议?好像我可以让父母和两个孩子都拥有与数据库的独立连接,事情就可以了,但我似乎无法得到那种行为.
谢谢,抱歉这个长度!
lec*_*hup 65
多处理在进程之间复制连接对象,因为它会分叉进程,因此会复制父进程的所有文件描述符.话虽这么说,与SQL服务器的连接只是一个文件,您可以在linux下的/ proc // fd/....中看到它.任何打开的文件都将在分叉进程之间共享.你可以在这里找到更多关于分叉的信息.
我的解决方案只是在启动进程之前简单地关闭数据库连接,每个进程在需要时自动重新创建连接(在django 1.4中测试):
from django import db
db.connections.close_all()
def db_worker():
some_paralell_code()
Process(target = db_worker,args = ())
Run Code Online (Sandbox Code Playgroud)
Pgbouncer/pgpool与多线程意义上的线程无关.这是在每个请求上不关闭连接的解决方案=在高负载下加速连接到postgres.
更新:
要完全删除数据库连接问题,只需将与数据库连接的所有逻辑移动到db_worker - 我想将QueryDict作为参数传递...更好的想法是简单地传递ID列表...请参阅QueryDict和values_list('id',flat =真的),别忘了把它变成清单!list(QueryDict)在传递给db_worker之前.多亏了我们不复制模型数据库连接.
def db_worker(models_ids):
obj = PartModelWorkerClass(model_ids) # here You do Model.objects.filter(id__in = model_ids)
obj.run()
model_ids = Model.objects.all().values_list('id', flat=True)
model_ids = list(model_ids) # cast to list
process_count = 5
delta = (len(model_ids) / process_count) + 1
# do all the db stuff here ...
# here you can close db connection
from django import db
db.connections.close_all()
for it in range(0:process_count):
Process(target = db_worker,args = (model_ids[it*delta:(it+1)*delta]))
Run Code Online (Sandbox Code Playgroud)
Mou*_*nir 16
使用多个数据库时,应关闭所有连接.
from django import db
for connection_name in db.connections.databases:
db.connections[connection_name].close()
Run Code Online (Sandbox Code Playgroud)
编辑
请使用与提及的@lechup相同的关闭所有连接(不确定从哪个django版本添加此方法):
from django import db
db.connections.close_all()
Run Code Online (Sandbox Code Playgroud)
我在顺序运行 Django测试用例时遇到了“关闭连接”问题。除了测试之外,还有另一个过程在测试执行期间有意修改数据库。这个过程在每个测试用例setUp()中启动。
一个简单的修复方法是继承我的测试类而TransactionTestCase不是TestCase. 这可以确保数据库确实被写入,并且其他进程具有数据的最新视图。
小智 5
对于 Python 3 和 Django 1.9,这对我有用:
import multiprocessing
import django
django.setup() # Must call setup
def db_worker():
for name, info in django.db.connections.databases.items(): # Close the DB connections
django.db.connection.close()
# Execute parallel code here
if __name__ == '__main__':
multiprocessing.Process(target=db_worker)
Run Code Online (Sandbox Code Playgroud)
请注意,如果没有 django.setup() 我无法让它工作。我猜需要为多处理再次初始化某些东西。
| 归档时间: |
|
| 查看次数: |
40601 次 |
| 最近记录: |