运行 异步调用时 UWSGI 和 Gunicorn 的区别
Differences between UWSGI and Gunicorn when running async calls
我有一个 Django 应用程序,在我的一个观点中,我实际上正在对发送电子邮件的函数进行异步调用。我都使用了 threading.thread(with start())以及一个叫做 after_response 的小 django 包,它基本上做同样的事情。
这是我所做的:
def my_synchronous_function(instance):
send_email_asynchronous.after_response(instance.id)
return "We are done here, but async call will continue."
@after_response.enable
def send_email_asynchronous(instance_id):
time.sleep(5)
print "Async has started"
instance = Instance.objects.get(pk=instance_id)
subject = "A subject"
ctx = {'username': instance.username}
message = get_template("email-template.html").render(ctx)
msg = EmailMessage(subject, message, to=[instance.email], from_email='loic@example.com')
print "about to send email"
time.sleep(5)
msg.content_subtype = 'html'
msg.send()
print "message sent"
此代码在 运行ning django manage.py 运行server 时运行良好;它在使用 nginx + gunicorn 时也能正常工作。但是,我注意到在使用 UWSGI 和 Nginx 时,send_email_asynchronous 函数永远不会被调用。使用 after_response 以及更长的 threading.Thread 版本时也是如此:
class SendNotification(threading.Thread):
"""
Sends notifications async.
"""
def __init__(self, instance_id):
"""
Sends notifications asynchronously provided an instance id.
"""
print "instance id: %s" % instance_id
self.instance = Instance.objects.get(pk=instance_id)
super(SendNotification, self).__init__()
def run (self):
time.sleep(5)
print "Async has started"
subject = "A subject"
ctx = {'username': self.instance.username}
message = get_template("email-template.html").render(ctx)
msg = EmailMessage(subject, message, to=[self.instance.email], from_email='loic@example.com')
print "about to send email"
time.sleep(5)
msg.content_subtype = 'html'
msg.send()
print "message sent"
这是按以下方式启动的:
SendNotification(instance.id).start()
同样,在开发服务器 "runserver" 上也能正常工作,在 gunicorn 上也能正常工作,但在 uwsgi 上不行,我有点困惑为什么会这样。使用 uwsgi,我实际上看到了来自 init 的打印语句,但没有看到来自 运行 方法的打印语句,当然也没有电子邮件。由于这个问题,我已经改用 gunicorn,所以我问这个问题更多是出于好奇。
谢谢,
你没有 post 你的 uWSGI 配置,但考虑到这是关于后台线程而不是 运行 你很有可能在启动 uWSGI 时 need to add --enable-threads
:
If you start uWSGI without threads, the Python GIL will not be
enabled, so threads generated by your application will never run. You
may not like that choice, but remember that uWSGI is a
language-independent server, so most of its choices are for
maintaining it “agnostic”.
But do not worry, there are basically no choices made by the uWSGI
developers that cannot be changed with an option.
If you want to maintain Python threads support without starting
multiple threads for your application, just add the --enable-threads
option (or enable-threads = true in ini style).
我有一个 Django 应用程序,在我的一个观点中,我实际上正在对发送电子邮件的函数进行异步调用。我都使用了 threading.thread(with start())以及一个叫做 after_response 的小 django 包,它基本上做同样的事情。
这是我所做的:
def my_synchronous_function(instance):
send_email_asynchronous.after_response(instance.id)
return "We are done here, but async call will continue."
@after_response.enable
def send_email_asynchronous(instance_id):
time.sleep(5)
print "Async has started"
instance = Instance.objects.get(pk=instance_id)
subject = "A subject"
ctx = {'username': instance.username}
message = get_template("email-template.html").render(ctx)
msg = EmailMessage(subject, message, to=[instance.email], from_email='loic@example.com')
print "about to send email"
time.sleep(5)
msg.content_subtype = 'html'
msg.send()
print "message sent"
此代码在 运行ning django manage.py 运行server 时运行良好;它在使用 nginx + gunicorn 时也能正常工作。但是,我注意到在使用 UWSGI 和 Nginx 时,send_email_asynchronous 函数永远不会被调用。使用 after_response 以及更长的 threading.Thread 版本时也是如此:
class SendNotification(threading.Thread):
"""
Sends notifications async.
"""
def __init__(self, instance_id):
"""
Sends notifications asynchronously provided an instance id.
"""
print "instance id: %s" % instance_id
self.instance = Instance.objects.get(pk=instance_id)
super(SendNotification, self).__init__()
def run (self):
time.sleep(5)
print "Async has started"
subject = "A subject"
ctx = {'username': self.instance.username}
message = get_template("email-template.html").render(ctx)
msg = EmailMessage(subject, message, to=[self.instance.email], from_email='loic@example.com')
print "about to send email"
time.sleep(5)
msg.content_subtype = 'html'
msg.send()
print "message sent"
这是按以下方式启动的: SendNotification(instance.id).start()
同样,在开发服务器 "runserver" 上也能正常工作,在 gunicorn 上也能正常工作,但在 uwsgi 上不行,我有点困惑为什么会这样。使用 uwsgi,我实际上看到了来自 init 的打印语句,但没有看到来自 运行 方法的打印语句,当然也没有电子邮件。由于这个问题,我已经改用 gunicorn,所以我问这个问题更多是出于好奇。
谢谢,
你没有 post 你的 uWSGI 配置,但考虑到这是关于后台线程而不是 运行 你很有可能在启动 uWSGI 时 need to add --enable-threads
:
If you start uWSGI without threads, the Python GIL will not be enabled, so threads generated by your application will never run. You may not like that choice, but remember that uWSGI is a language-independent server, so most of its choices are for maintaining it “agnostic”.
But do not worry, there are basically no choices made by the uWSGI developers that cannot be changed with an option.
If you want to maintain Python threads support without starting multiple threads for your application, just add the --enable-threads option (or enable-threads = true in ini style).