python - Flask APScheduler + Gunicorn worker - 在套接字修复后仍然运行两次任务

标签 python flask gunicorn apscheduler

我有一个 Flask 应用程序,我使用 Flask-APScheduler 在我的数据库上运行预定查询并通过 cron 作业发送电子邮件。

我使用以下配置通过 Gunicorn 运行我的应用程序并通过主管进行控制:

[program:myapp]
command=/home/path/to/venv/bin/gunicorn -b localhost:8000 -w 4 myapp:app --preload
directory=/home/path/here
user=myuser
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true

作业详细信息存储在我的 config.py 中:
...config stuff
JOBS = [
    {
        'id': 'sched_email',
        'func': 'app.tasks:sched_email',
        'trigger': 'cron',
        'hour': 9,
    },
]
SCHEDULER_API_ENABLED = True

最初,由于 4 名工作人员初始化应用程序和调度程序,电子邮件被发送了 4 次。我发现了一篇类似的文章,它建议在应用程序初始化时打开一个套接字,这样其他 worker 就无法抢到工作。

我的 初始化 .py:
# Third-party imports
import logging
from logging.handlers import SMTPHandler, RotatingFileHandler
import os
from flask import Flask
from flask_mail import Mail, Message
from flask_sqlalchemy import SQLAlchemy
from flask_apscheduler import APScheduler
from flask_migrate import Migrate
from flask_login import LoginManager
import sys, socket

# Local imports
from config import app_config

# Create initial instances of extensions
mail = Mail()
db = SQLAlchemy()
scheduler = APScheduler()
migrate = Migrate()
login_manager = LoginManager()

# Construct the Flask app instance
def create_app(config_name):
    app = Flask(__name__)
    app.config.from_object(app_config[config_name])
    app_config[config_name].init_app(app)

    migrate.init_app(app, db)
    mail.init_app(app)
    db.init_app(app)

    # Fix to ensure only one Gunicorn worker grabs the scheduled task
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.bind(("127.0.0.1", 47200))
    except socket.error:
        pass
    else:
        scheduler.init_app(app)
        scheduler.start()

    login_manager.init_app(app)
    login_manager.login_message = "You must be logged in to access this page."
    login_manager.login_message_category = 'danger'
    login_manager.login_view = "admin.login"

    # Initialize blueprints
    from .errors import errors as errors_blueprint
    app.register_blueprint(errors_blueprint)

    from .main import main as main_blueprint
    app.register_blueprint(main_blueprint)

    from .admin import admin as admin_blueprint
    app.register_blueprint(admin_blueprint)

    # Setup logging when not in debug mode
    if not app.debug:
        ... logging email config

        ... log file config

    return app

现在电子邮件被发送了两次!

谁能建议为什么会这样?有没有我可以深入研究的日志来弄清楚发生了什么?

我还阅读了有关使用 @app.before_first_request 装饰器的信息,但由于我使用的是应用程序工厂模式,我不确定如何合并它。

谢谢!

最佳答案

所以事实证明这个问题是我犯的一个愚蠢的错误。

我没有正确配置主管,所以我的 --preload 标志实际上没有被应用。

在我修复主管并重新加载后,我的任务现在可以正常运行并且我收到一封电子邮件。

我希望我上面的设置能帮助其他人,因为我是初学者,这花了我很长时间才开始工作。

关于python - Flask APScheduler + Gunicorn worker - 在套接字修复后仍然运行两次任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53307712/

相关文章:

python - Django 当我使用基于类的 View 时,如何在表单中传递 request.user(当前登录用户)?

python - 对象不在正确的状态;哪个异常(exception)是合适的?

python - 如何在启动 Tkinter 应用程序时隐藏控制台窗口,但在按下 GUI 按钮运行 python 脚本时重新打开它?

python - Flask中的路径路由

javascript - 将数组从 Flask 传递到 Javascript 以创建下拉菜单选项

http - 在 Gunicorn 中,如何添加连接 : Close to the response once server shutdown has begun?

python - 根据条件替换来自不同文件的字符串

python - 使用 render_template 有条件地呈现 HTML 片段

python - 枪兽 : Failed to find application object 'App' in 'run'

python - 随后运行多个 tensorflow session