Python FastAPI+Celery+RabbitMQ實(shí)現(xiàn)分布式圖片水印處理系統(tǒng)
實(shí)現(xiàn)思路
- FastAPI 服務(wù)器
- Celery 任務(wù)隊(duì)列
- RabbitMQ 作為消息代理
- 定時(shí)任務(wù)處理
完整步驟
首先創(chuàng)建項(xiàng)目結(jié)構(gòu):
c:\Users\Administrator\Desktop\meitu\
├── app/
│ ├── __init__.py
│ ├── main.py
│ ├── celery_app.py
│ ├── tasks.py
│ └── config.py
├── requirements.txt
└── celery_worker.py
1.首先創(chuàng)建 requirements.txt:
fastapi==0.104.1 uvicorn==0.24.0 celery==5.3.4 python-dotenv==1.0.0 requests==2.31.0
2.創(chuàng)建配置文件:
from dotenv import load_dotenv
import os
load_dotenv()
# RabbitMQ配置
RABBITMQ_HOST = os.getenv("RABBITMQ_HOST", "localhost")
RABBITMQ_PORT = os.getenv("RABBITMQ_PORT", "5672")
RABBITMQ_USER = os.getenv("RABBITMQ_USER", "guest")
RABBITMQ_PASS = os.getenv("RABBITMQ_PASS", "guest")
# Celery配置
CELERY_BROKER_URL = f"amqp://{RABBITMQ_USER}:{RABBITMQ_PASS}@{RABBITMQ_HOST}:{RABBITMQ_PORT}//"
CELERY_RESULT_BACKEND = "rpc://"
# 定時(shí)任務(wù)配置
CELERY_BEAT_SCHEDULE = {
'process-images-every-hour': {
'task': 'app.tasks.process_images',
'schedule': 3600.0, # 每小時(shí)執(zhí)行一次
},
'daily-cleanup': {
'task': 'app.tasks.cleanup_old_images',
'schedule': 86400.0, # 每天執(zhí)行一次
}
}
3.創(chuàng)建 Celery 應(yīng)用:
from celery import Celery
from app.config import CELERY_BROKER_URL, CELERY_RESULT_BACKEND, CELERY_BEAT_SCHEDULE
celery_app = Celery(
'image_processing',
broker=CELERY_BROKER_URL,
backend=CELERY_RESULT_BACKEND,
include=['app.tasks']
)
# 配置定時(shí)任務(wù)
celery_app.conf.beat_schedule = CELERY_BEAT_SCHEDULE
celery_app.conf.timezone = 'Asia/Shanghai'
4.創(chuàng)建任務(wù)文件:
from app.celery_app import celery_app
from app.watermark import ImageWatermarker
import os
from datetime import datetime, timedelta
@celery_app.task
def add_watermark_task(image_path, text, position='center'):
"""異步添加水印任務(wù)"""
watermarker = ImageWatermarker()
try:
result_path = watermarker.add_watermark(
image_path=image_path,
text=text,
position=position
)
return {"status": "success", "output_path": result_path}
except Exception as e:
return {"status": "error", "message": str(e)}
@celery_app.task
def process_images():
"""定時(shí)處理圖片任務(wù)"""
image_dir = "images/pending"
if not os.path.exists(image_dir):
return {"status": "error", "message": "Pending directory not found"}
processed = 0
for image in os.listdir(image_dir):
if image.lower().endswith(('.png', '.jpg', '.jpeg')):
add_watermark_task.delay(
os.path.join(image_dir, image),
"自動(dòng)處理水印",
'center'
)
processed += 1
return {"status": "success", "processed": processed}
@celery_app.task
def cleanup_old_images():
"""清理舊圖片任務(wù)"""
output_dir = "images/processed"
if not os.path.exists(output_dir):
return {"status": "error", "message": "Output directory not found"}
threshold_date = datetime.now() - timedelta(days=7)
cleaned = 0
for image in os.listdir(output_dir):
image_path = os.path.join(output_dir, image)
if os.path.getctime(image_path) < threshold_date.timestamp():
os.remove(image_path)
cleaned += 1
return {"status": "success", "cleaned": cleaned}
5.創(chuàng)建 FastAPI 應(yīng)用:
from fastapi import FastAPI, File, UploadFile, BackgroundTasks
from fastapi.responses import JSONResponse
import os
from app.tasks import add_watermark_task
from app.celery_app import celery_app
app = FastAPI(title="圖片水印處理服務(wù)")
@app.post("/upload/")
async def upload_image(
file: UploadFile = File(...),
text: str = "水印文本",
position: str = "center"
):
# 保存上傳的文件
file_path = f"images/uploads/{file.filename}"
os.makedirs(os.path.dirname(file_path), exist_ok=True)
with open(file_path, "wb") as buffer:
content = await file.read()
buffer.write(content)
# 創(chuàng)建異步任務(wù)
task = add_watermark_task.delay(file_path, text, position)
return JSONResponse({
"status": "success",
"message": "圖片已上傳并加入處理隊(duì)列",
"task_id": task.id
})
@app.get("/task/{task_id}")
async def get_task_status(task_id: str):
task = celery_app.AsyncResult(task_id)
if task.ready():
return {"status": "completed", "result": task.result}
return {"status": "processing"}
@app.get("/tasks/scheduled")
async def get_scheduled_tasks():
return {"tasks": celery_app.conf.beat_schedule}
6.創(chuàng)建 Celery worker 啟動(dòng)文件:
from app.celery_app import celery_app
if __name__ == '__main__':
celery_app.start()
使用說明
首先安裝依賴:
pip install -r requirements.txt
確保 RabbitMQ 服務(wù)已啟動(dòng)
啟動(dòng) FastAPI 服務(wù)器:
uvicorn app.main:app --reload
啟動(dòng) Celery worker:
celery -A celery_worker.celery_app worker --loglevel=info
啟動(dòng) Celery beat(定時(shí)任務(wù)):
celery -A celery_worker.celery_app beat --loglevel=info
這個(gè)系統(tǒng)提供以下功能:
- 通過 FastAPI 接口上傳圖片并異步處理水印
- 使用 Celery 處理異步任務(wù)隊(duì)列
- 使用 RabbitMQ 作為消息代理
- 支持定時(shí)任務(wù):
- 每小時(shí)自動(dòng)處理待處理圖片
- 每天清理一周前的舊圖片
- 支持任務(wù)狀態(tài)查詢
- 支持查看計(jì)劃任務(wù)列表
API 端點(diǎn):
- POST /upload/ - 上傳圖片并創(chuàng)建水印任務(wù)
- GET /task/{task_id} - 查詢?nèi)蝿?wù)狀態(tài)
- GET /tasks/scheduled - 查看計(jì)劃任務(wù)列表
以上就是Python FastAPI+Celery+RabbitMQ實(shí)現(xiàn)分布式圖片水印處理系統(tǒng)的詳細(xì)內(nèi)容,更多關(guān)于Python圖片水印的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
python腳本監(jiān)聽域名證書過期時(shí)間并通知消息到釘釘(最新推薦)
這篇文章主要介紹了python腳本監(jiān)聽域名證書過期時(shí)間并通知消息到釘釘(最新推薦),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-11-11
使用python tkinter實(shí)現(xiàn)各種個(gè)樣的撩妹鼠標(biāo)拖尾效果
這篇文章主要介紹了使用python tkinter實(shí)現(xiàn)各種個(gè)樣的撩妹鼠標(biāo)拖尾效果,本文通過實(shí)例代碼,給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09
python sqlobject(mysql)中文亂碼解決方法
在使用python寫項(xiàng)目的時(shí)候,用到了sqlobject庫函數(shù)connectionForURI連接mysql,但是遇到了中文顯示亂碼的問題,在添加記錄的時(shí)候還拋出異常2008-11-11
Python實(shí)現(xiàn)批量填補(bǔ)遙感影像的無效值NoData
這篇文章主要為大家介紹了如何基于Python中ArcPy模塊,對大量柵格遙感影像文件批量進(jìn)行無效值(NoData值)填充的方法,感興趣的小伙伴可以了解一下2023-06-06

