我有一个Django应用程序,该应用程序在内存中使用大型数据结构(由于性能限制)。这不会有问题,但是我使用的是Heroku,如果python网络进程启动耗时超过30秒,它将被停止,因为它被认为是超时错误。由于上述问题,我使用了守护进程(Heroku中的worker)来处理数据结构的构造,并使用Redis来处理进程之间传递的消息。
当工作人员完成操作(大约1分钟)时,它将数据结构(50Mb左右)存储在Redis中。
现在问题的关键了……Django遵循了请求/响应范例,并且已经同步。这意味着应该存在 Django视图,以处理来自宣布其完成的工作程序的回调。即使我使用像Redis中的pub / sub这样的更高级的东西,我仍然被迫在视图中评估发布者填充的队列。
如何避免使用Django视图的必要性?没有异步的方法吗?
下面是我在视图内使用发布/订阅的解决方案。这似乎很糟糕,但我想不出另一种方法。
views.py
...
# data_handler can enqueue tasks on the default queue
data_handler = DataHandler()
strict_redis = redis.from_url(settings.DEFAULT_QUEUE)
pub_sub = strict_redis.pubsub()
# this puts the job of constructing the large data structures
# on the default queue so a worker can pick it up. Being async,
# it returns with an empty set of data structures.
data_structures = data_handler.start()
pub_sub.subscribe(settings.FINISHED_DATA_STRUCTURES_CHANNEL)
@require_http_methods(['POST'])
def store_and_fetch(request):
user_data = json.load(request.body.decode('utf8'))
message = pub_sub.get_message()
if message:
command = message['data'] if 'data' in message else ''
if command == settings.FINISHED_DATA_STRUCTURES_INIT.encode('utf-8'):
# this takes the data from redis and updates data_structures
data_handler.update(data_structures)
return HttpResponse(compute_response(user_data, data_structures))
更新:经过数月的研究,我现在可以说,弄弄Django的请求/响应周期肯定更好(更明智)不。诸如Django RQ Scheduler或Celery之类的东西可以很好地执行异步任务。如果您想在完成一些可重复的工作后更新主Web流程,则使用python requests 包之类的东西更简单,将POST发送给Web进程的工作人员做了预定的工作。这样,我们就不会绕过Django的机制,更重要的是,总体上更简单。
关于我在帖子开头提到的Heroku约束。在我写这个问题的那一刻,我对heroku还是个新手,对发布阶段并不了解。在发布阶段,我们可以设置主流程所需的所有复杂逻辑。因此,在发布阶段结束时,我们只需要按照我上面描述的方式通知Web进程,并使用一些分布式内存缓冲区(即使Redis也可以正常工作)。