gunicorn结合django启动后台线程

Posted shengulong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了gunicorn结合django启动后台线程相关的知识,希望对你有一定的参考价值。

 

preload 为True的情况下,会将辅助线程或者进程开在master里,加重master的负担(master最好只是用来负责监听worker进程)

 

django应用的gunicorn示例:只在主线程里开启后台线程,worker里不启动后台线程

gunicorn -w 5 --preload -b 127.0.0.1:8088 application_name.wsgi:application

wsgi.py文件:

"""
WSGI config for erebus project.

It exposes the WSGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/2.1/howto/deployment/wsgi/
"""

import os

from django.core.wsgi import get_wsgi_application
from erebus.get_wsgi_application import get_wsgi_application
from whitenoise import WhiteNoise
os.environ.setdefault(DJANGO_SETTINGS_MODULE, erebus.settings)

application = get_wsgi_application()
application = WhiteNoise(application, root=./static/)
# application.add_files(/path/to/more/static/files, prefix=more-files/)

重写的get_wsgi_application.py文件:

 

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
    @Author      : xxxxx
    
    @Date        : 2019-02-27 19:26
    
    @Description : 本文件的作用描述
    
    @File        : get_wsgi_application.py 
"""

import django
from django.core.handlers.wsgi import WSGIHandler


def get_wsgi_application():
    """
    The public interface to Djangos WSGI support. Return a WSGI callable.

    Avoids making django.core.handlers.WSGIHandler a public API, in case the
    internal WSGI implementation changes or moves in the future.
    """
    django.setup(set_prefix=False)
    # 把主进程中的kafka consumer线程放入启动过程中(即放入gunicorn的master进程中),
    # 以使用gunicorn的preload参数控制这些线程的启动个数。
    from utils.kafka_consumer_daemon import start_kafka_consumer_daemon
    start_kafka_consumer_daemon()
    return WSGIHandler()

 

后台线程:

# 使用线程池子
def start_kafka_consumer_daemon():
    try:
        for _ in range(CONSUMER_THREAD_NUM):
            consumer = threading.Thread(target=consume_kafka)
            consumer.setDaemon(True)
            consumer.start()
    except Exception as e:
        logger.error(e)
        logger.error(traceback.format_exc())

 

 

 

 

配置参考:https://github.com/benoitc/gunicorn/blob/29f0394cdd381df176a3df3c25bb3fdd2486a173/examples/example_config.py

配置解读:http://docs.gunicorn.org/en/stable/settings.html

 

 

假设程序如下:

1 if __name__ == __main__:
2     t = Thread(target=test)
3     t.start()
4     app.run(host=0.0.0.0‘,port=8080,debug=False)

      gunicorn在启动过程只会从flask的app文件中取出app使用,并不会执行main函数,如果希望在gunicorn中仍旧能启动后台线程并保证后台线程不因为gunicorn的子进程重复执行,有三种方式。

1.  使用gunicorn的preload参数。在worker进程被复制(派生)之前载入应用的代码。这种方式,线程执行代码需要写在app文件的全局部分,利用预加载只执行一下。

2. 使用flask的app的钩子函数before_first_request。在before_first_request中执行线程。但这种方式必须要有第一个请求才能触发线程启动。

3. 使用文件锁。这种方式与第一种方式相同,需要把线程执行的代码写在app文件的全局部分。在第一个子进程启动时创建文件并加锁,在后续的子进程启动时判断锁的状态,如果有锁则不执行。

   以上通过奇怪的操作启动后台线程。但不推荐。可以考虑使用celery或者cron等方式实现需求。

 

 

参考:

1、https://www.jianshu.com/p/509985f98416

2、https://www.cnblogs.com/chenxianpao/p/9931483.html

3、

4、

以上是关于gunicorn结合django启动后台线程的主要内容,如果未能解决你的问题,请参考以下文章

Django如何监听启动,开启另外后台线程

015 输入理解时间片

Django异步任务线程池

python爬取英雄联盟皮肤结合多线程的方法

Django如何自定义manage.py命令? 达到启动后台进程的目的?

如何在后台线程中启动 GPS 定位?