本文目录导读:

我来详细介绍如何编写分布式任务脚本,包括架构设计、技术选型和具体实现方案。
分布式任务核心架构
基本架构模式
┌─────────────┐ ┌──────────────┐
│ 调度器 │────▶│ 任务队列 │
└─────────────┘ └──────┬───────┘
│
┌─────────────┼─────────────┐
│ │ │
┌─────▼────┐ ┌─────▼────┐ ┌─────▼────┐
│ Worker 1 │ │ Worker 2 │ │ Worker 3 │
└──────────┘ └──────────┘ └──────────┘
主流方案对比
# 方案1: Celery (最成熟) # 方案2: Redis Queue (轻量级) # 方案3: Apache Airflow (DAG工作流) # 方案4: 自建RabbitMQ + 工作进程
完整实现示例
基础分布式架构实现
# scheduler.py - 任务调度器
import redis
import json
import uuid
from typing import Callable, Dict, Any
import pickle
class DistributedTaskScheduler:
def __init__(self, redis_host='localhost', redis_port=6379):
self.redis_client = redis.Redis(host=redis_host, port=redis_port)
self.task_queue = 'task_queue'
self.result_backend = 'task_results'
def submit_task(self, func_path: str, *args, **kwargs) -> str:
"""提交分布式任务"""
task_id = str(uuid.uuid4())
task = {
'id': task_id,
'func_path': func_path,
'args': args,
'kwargs': kwargs,
'status': 'pending'
}
# 序列化并推送任务到队列
self.redis_client.rpush(self.task_queue, json.dumps(task))
return task_id
def get_task_result(self, task_id: str) -> Dict:
"""获取任务执行结果"""
result = self.redis_client.get(f'{self.result_backend}:{task_id}')
return json.loads(result) if result else None
工作节点实现
# worker.py - 任务执行器
import redis
import json
import importlib
import time
from typing import Dict, Any
class TaskWorker:
def __init__(self, worker_id: str, redis_host='localhost', redis_port=6379):
self.worker_id = worker_id
self.redis_client = redis.Redis(host=redis_host, port=redis_port)
self.task_queue = 'task_queue'
self.result_backend = 'task_results'
def _load_function(self, func_path: str):
"""动态加载任务函数"""
module_path, func_name = func_path.rsplit('.', 1)
module = importlib.import_module(module_path)
return getattr(module, func_name)
def _execute_task(self, task: Dict[str, Any]) -> Dict:
"""执行单个任务"""
try:
func = self._load_function(task['func_path'])
result = func(*task['args'], **task['kwargs'])
return {
'status': 'completed',
'result': result,
'worker_id': self.worker_id
}
except Exception as e:
return {
'status': 'failed',
'error': str(e),
'worker_id': self.worker_id
}
def start_working(self):
"""开始持续处理任务"""
print(f"Worker {self.worker_id} started")
while True:
# 阻塞获取任务(超时10秒)
task_data = self.redis_client.blpop(self.task_queue, timeout=10)
if task_data:
task = json.loads(task_data[1])
print(f"Processing task: {task['id']}")
# 执行任务
result = self._execute_task(task)
# 保存结果
result_key = f'{self.result_backend}:{task["id"]}'
self.redis_client.set(result_key, json.dumps(result))
time.sleep(0.1)
任务函数定义
# tasks.py - 具体的分布式任务
import time
import random
def compute_pi(iterations: int) -> float:
"""计算π的近似值(耗时任务示例)"""
pi = 0
for i in range(iterations):
pi += 4 * ((-1) ** i) / (2 * i + 1)
time.sleep(0.01) # 模拟计算延迟
return pi
def process_image(image_path: str, filters: list) -> dict:
"""图像处理任务示例"""
# 模拟图像处理
time.sleep(random.uniform(1, 3))
return {
'image_path': image_path,
'filters_applied': filters,
'processed': True
}
def batch_data_analysis(data_chunk: list) -> dict:
"""数据分析任务示例"""
return {
'count': len(data_chunk),
'sum': sum(data_chunk),
'mean': sum(data_chunk) / len(data_chunk) if data_chunk else 0
}
使用Celery实现(生产环境推荐)
# celery_app.py
from celery import Celery
from celery.signals import task_failure, task_success
app = Celery('distributed_tasks',
broker='redis://localhost:6379/0',
backend='redis://localhost:6379/1')
# Celery配置
app.conf.update(
task_serializer='json',
accept_content=['json'],
result_serializer='json',
timezone='Asia/Shanghai',
enable_utc=True,
worker_max_tasks_per_child=100, # 每个worker最大任务数
task_acks_late=True, # 任务确认延迟
worker_prefetch_multiplier=1, # 预取因子
)
# 定义任务
@app.task(bind=True, max_retries=3, default_retry_delay=60)
def long_running_task(self, data: list):
try:
# 耗时计算
result = process_data(data)
return result
except Exception as exc:
raise self.retry(exc=exc)
@app.task(bind=True, rate_limit='10/m') # 限速
def rate_limited_task(self, item: str):
return f"Processed: {item}"
使用Redis实现负载均衡
# balanced_worker.py - 带负载均衡的工作节点
import redis
import json
import psutil
import time
class BalancedWorker:
def __init__(self, worker_id: str, max_load: float = 0.8):
self.worker_id = worker_id
self.max_load = max_load
self.redis_client = redis.Redis()
self.current_tasks = 0
self.max_concurrent_tasks = 5
def get_system_load(self) -> float:
"""获取系统负载"""
return psutil.cpu_percent() / 100.0
def can_accept_task(self) -> bool:
"""判断是否可以接受新任务"""
return (self.current_tasks < self.max_concurrent_tasks and
self.get_system_load() < self.max_load)
def register_worker(self):
"""注册worker到服务发现"""
worker_info = {
'id': self.worker_id,
'load': self.get_system_load(),
'capacity': self.max_concurrent_tasks - self.current_tasks,
'last_heartbeat': time.time()
}
self.redis_client.hset('workers', self.worker_id, json.dumps(worker_info))
def heartbeat(self):
"""定期发送心跳"""
while True:
self.register_worker()
time.sleep(5)
监控和状态管理
# monitor.py - 任务监控器
import redis
import json
from datetime import datetime
from typing import Dict, List
class TaskMonitor:
def __init__(self, redis_host='localhost'):
self.redis_client = redis.Redis(host=redis_host)
def get_queue_status(self) -> Dict:
"""获取队列状态"""
queue_length = self.redis_client.llen('task_queue')
workers = self.redis_client.hgetall('workers')
return {
'pending_tasks': queue_length,
'active_workers': len(workers),
'workers': {
k.decode(): json.loads(v.decode())
for k, v in workers.items()
}
}
def get_task_statistics(self) -> Dict:
"""获取任务统计信息"""
completed = 0
failed = 0
# 扫描结果后端
for key in self.redis_client.scan_iter('task_results:*'):
result = json.loads(self.redis_client.get(key))
if result['status'] == 'completed':
completed += 1
elif result['status'] == 'failed':
failed += 1
return {
'completed': completed,
'failed': failed,
'total': completed + failed
}
启动和管理脚本
# manage.py - 分布式任务管理系统
import subprocess
import sys
import time
from multiprocessing import Process
def start_worker(worker_id: str, count: int = 3):
"""启动多个worker"""
processes = []
for i in range(count):
p = Process(target=run_worker, args=(f'{worker_id}-{i}',))
p.start()
processes.append(p)
return processes
def run_worker(worker_id: str):
"""运行单个worker"""
from worker import TaskWorker
worker = TaskWorker(worker_id)
worker.start_working()
def submit_test_task():
"""提交测试任务"""
from scheduler import DistributedTaskScheduler
scheduler = DistributedTaskScheduler()
# 提交多个计算任务
task_ids = []
for i in range(10):
task_id = scheduler.submit_task(
'tasks.compute_pi',
iterations=1000 + i * 500
)
task_ids.append(task_id)
print(f"Submitted task {task_id}")
return task_ids
if __name__ == '__main__':
if len(sys.argv) < 2:
print("Usage: python manage.py [start|stop|status|test]")
sys.exit(1)
command = sys.argv[1]
if command == 'start':
print("Starting distributed task system...")
start_worker('worker', count=3)
elif command == 'test':
print("Submitting test tasks...")
submit_test_task()
高级特性和最佳实践
任务优先级处理
# priority_queue.py
class PriorityTaskScheduler:
def __init__(self):
self.redis_client = redis.Redis()
self.queues = {
'high': 'task_queue:high',
'medium': 'task_queue:medium',
'low': 'task_queue:low'
}
def submit_with_priority(self, task_func, priority='medium', **kwargs):
queue = self.queues.get(priority, self.queues['medium'])
task = {
'id': str(uuid.uuid4()),
'func': task_func,
'args': kwargs.get('args', ()),
'kwargs': kwargs.get('kwargs', {}),
'priority': priority
}
self.redis_client.rpush(queue, json.dumps(task))
任务重试和容错
# retry_handler.py
class TaskRetryHandler:
MAX_RETRIES = 3
RETRY_DELAYS = [10, 30, 60] # 指数退避
def handle_failed_task(self, task: Dict, error: str) -> bool:
"""处理失败任务"""
retries = task.get('retries', 0)
if retries < self.MAX_RETRIES:
# 延迟重试
delay = self.RETRY_DELAYS[retries]
task['retries'] = retries + 1
task['next_retry'] = time.time() + delay
# 重新入队
self.redis_client.zadd('delayed_tasks',
{json.dumps(task): task['next_retry']})
return True
# 最大重试次数后移入死信队列
self.redis_client.rpush('dead_letter_queue', json.dumps(task))
return False
部署和运维建议
-
使用容器化部署:
# Dockerfile FROM python:3.9-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY . . CMD ["python", "manage.py", "start"]
-
监控和告警配置:
# 集成Prometheus指标 from prometheus_client import Counter, Histogram, start_http_server
task_count = Counter('tasks_processed_total', 'Number of processed tasks') task_duration = Histogram('task_duration_seconds', 'Task duration in seconds')
3. **配置管理**:
```yaml
# config.yaml
redis:
host: localhost
port: 6379
password:
db: 0
worker:
max_concurrent: 5
max_retries: 3
heartbeat_interval: 10
task_queue:
max_size: 10000
priority_levels: [high, medium, low]
这套分布式任务脚本系统支持:
- 任务队列管理和调度
- 多worker并行执行
- 负载均衡和健康检查
- 任务优先级处理
- 重试和容错机制
- 监控和统计功能
可以根据具体需求选择合适的实现方案和配置参数。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播