You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Azure中让Python Flask Web App的指定任务仅在单个实例运行?

解决方案:Azure多实例Flask App中控制单实例任务运行

1. 利用Azure实例标记与环境变量

  • 在Azure门户给目标实例添加自定义标记(比如is_scheduler_instance: true),并通过应用设置注入对应的环境变量IS_SCHEDULER_INSTANCE=true
  • Flask启动时读取该环境变量,仅在标记实例上启动调度任务
  • 代码示例:
import os
from flask import Flask
from apscheduler.schedulers.background import BackgroundScheduler

app = Flask(__name__)

def scheduled_job():
    # 你的调度任务逻辑
    print(f"Task running on instance: {os.getenv('WEBSITE_INSTANCE_ID')}")

@app.before_first_request
def init_scheduler():
    # 判断当前实例是否为调度专用实例
    if os.getenv("IS_SCHEDULER_INSTANCE", "false").lower() == "true":
        scheduler = BackgroundScheduler()
        scheduler.add_job(scheduled_job, 'interval', minutes=15)
        scheduler.start()

if __name__ == '__main__':
    app.run()
  • 扩展时,只需给需要运行任务的实例保留标记,其他实例不启动调度器

2. 分布式锁实现自动单实例控制

  • 用Azure Blob Storage或Redis实现分布式锁,确保同一时间仅一个实例能获取锁并执行任务
  • 代码示例(基于Azure Blob Storage):
from azure.storage.blob import BlobServiceClient
import os
from flask import Flask
from apscheduler.schedulers.background import BackgroundScheduler

app = Flask(__name__)

STORAGE_CONN_STR = os.getenv("AZURE_STORAGE_CONN_STR")
LOCK_BLOB = "task-lock"

def get_lock():
    try:
        blob_client = BlobServiceClient.from_connection_string(STORAGE_CONN_STR).get_blob_client("locks", LOCK_BLOB)
        # 创建独占锁,超时设为任务周期的2倍,避免死锁
        blob_client.upload_blob(b"locked", overwrite=False, lease_duration=1800)
        return True
    except:
        return False

def release_lock():
    try:
        blob_client = BlobServiceClient.from_connection_string(STORAGE_CONN_STR).get_blob_client("locks", LOCK_BLOB)
        blob_client.delete_blob()
    except:
        pass

def run_task():
    if get_lock():
        try:
            # 任务逻辑
            print(f"Task executed on instance: {os.getenv('WEBSITE_INSTANCE_ID')}")
        finally:
            release_lock()

@app.before_first_request
def start_scheduler():
    scheduler = BackgroundScheduler()
    scheduler.add_job(run_task, 'interval', minutes=15)
    scheduler.start()

if __name__ == '__main__':
    app.run()
  • 这种方式无需手动标记实例,动态扩展时自动维持单实例运行

3. 部署槽位隔离方案

  • 将调度任务实例放在单独的Azure部署槽位(比如scheduler-slot),主槽位仅处理Web请求
  • 扩展时只增加主槽位的实例数,调度槽位保持单实例
  • 优点是任务与Web服务完全隔离,避免互相影响

注意事项

  • 若使用Gunicorn等WSGI服务器,需配置worker数量与调度器启动逻辑,避免多worker重复启动任务(可结合进程锁或仅在主worker启动调度器)
  • 容器化部署(Azure Container Apps)时,可通过设置调度任务容器的replicas: 1,结合环境变量控制任务启动

内容的提问来源于stack exchange,提问作者justanotherdeveloper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 22:03:15