我有一个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次电子邮件。我发现了一篇类似的文章,该文章建议在应用程序初始化时打开一个套接字,以免其他工人无法抓住工作。
我的 init .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装饰器的信息,但是当我使用应用程序工厂模式时,我不确定如何将其合并。
谢谢!
答案 0 :(得分:1)
所以事实证明,这个问题是我犯的一个愚蠢的错误。
我没有正确配置超级用户,因此我的--preload标志实际上没有被应用。
我固定了主管并重新加载后,我的任务现在可以正常运行,并且收到一封电子邮件。
我希望以上设置能够帮助其他人,因为他们是一个初学者,这花了我很长时间才能开始工作。