本文目录导读:

我来为你介绍几种Python实现削峰填谷同步任务流量的方法:
使用队列和速率限制
生产者-消费者模式
import threading
import time
from queue import Queue
import random
class TrafficShapingSync:
def __init__(self, max_queue_size=100, rate_limit=10):
self.task_queue = Queue(maxsize=max_queue_size)
self.rate_limit = rate_limit # 每秒处理的任务数
self.last_time = time.time()
self.tokens = 0
self.lock = threading.Lock()
def token_bucket(self):
"""令牌桶算法控制速率"""
with self.lock:
now = time.time()
elapsed = now - self.last_time
self.tokens += elapsed * self.rate_limit
self.tokens = min(self.tokens, self.rate_limit * 2) # 最大积攒2秒的令牌
self.last_time = now
if self.tokens >= 1:
self.tokens -= 1
return True
return False
def producer(self, task_id):
"""生产者-添加任务"""
task = {
'id': task_id,
'data': f"Task_{task_id}",
'timestamp': time.time()
}
try:
self.task_queue.put(task, timeout=1)
print(f"生产者添加任务: {task_id}, 队列大小: {self.task_queue.qsize()}")
except:
print(f"生产者: 队列已满,丢弃任务 {task_id}")
def consumer(self, worker_id):
"""消费者-处理任务"""
while True:
if self.token_bucket():
try:
task = self.task_queue.get(timeout=0.1)
# 模拟任务处理
process_time = random.uniform(0.1, 0.5)
time.sleep(process_time)
print(f"消费者{worker_id}完成: 任务{task['id']}, 耗时:{process_time:.2f}s")
self.task_queue.task_done()
except:
time.sleep(0.1)
else:
time.sleep(0.05) # 等待令牌
# 使用示例
if __name__ == "__main__":
traffic = TrafficShapingSync(max_queue_size=50, rate_limit=5)
# 启动消费者
consumers = []
for i in range(3):
t = threading.Thread(target=traffic.consumer, args=(i,), daemon=True)
t.start()
consumers.append(t)
# 模拟突发流量
for i in range(100):
traffic.producer(i)
if i % 10 == 0:
# 模拟突发流量
for _ in range(5):
traffic.producer(i + 1000)
使用asyncio实现异步流量控制
import asyncio
import time
import random
class AsyncTrafficShaper:
def __init__(self, rate_limit=10, burst_size=20):
self.rate_limit = rate_limit
self.burst_size = burst_size
self.tokens = burst_size
self.last_refill = time.monotonic()
self.lock = asyncio.Lock()
async def _refill_tokens(self):
"""补充令牌"""
now = time.monotonic()
elapsed = now - self.last_refill
new_tokens = elapsed * self.rate_limit
self.tokens = min(self.burst_size, self.tokens + new_tokens)
self.last_refill = now
async def acquire(self):
"""获取处理权限"""
while True:
async with self.lock:
await self._refill_tokens()
if self.tokens >= 1:
self.tokens -= 1
return True
await asyncio.sleep(1.0 / self.rate_limit)
async def process_task(self, task_id, task_data):
"""处理单个任务"""
await self.acquire() # 等待令牌
# 模拟任务处理
process_time = random.uniform(0.1, 0.3)
await asyncio.sleep(process_time)
print(f"任务 {task_id} 完成,处理时间: {process_time:.2f}s")
return task_data
class AsyncScheduler:
def __init__(self, max_concurrent=5):
self.semaphore = asyncio.Semaphore(max_concurrent)
self.shaper = AsyncTrafficShaper(rate_limit=10)
async def safe_process(self, task_id, task_data):
"""安全处理任务(限流+并发控制)"""
async with self.semaphore: # 控制并发数
result = await self.shaper.process_task(task_id, task_data)
return result
async def process_batch(self, tasks):
"""批量处理任务"""
tasks_list = [self.safe_process(i, data) for i, data in enumerate(tasks)]
results = await asyncio.gather(*tasks_list, return_exceptions=True)
return results
# 使用示例
async def main():
scheduler = AsyncScheduler(max_concurrent=5)
# 模拟100个突发任务
tasks = [f"data_{i}" for i in range(100)]
# 分批处理,每批20个
batch_size = 20
for i in range(0, len(tasks), batch_size):
batch = tasks[i:i+batch_size]
print(f"\n处理批次 {i//batch_size + 1}, 任务数: {len(batch)}")
results = await scheduler.process_batch(batch)
await asyncio.sleep(1) # 批次间隔
if __name__ == "__main__":
asyncio.run(main())
使用第三方库实现高级控制
aio-limit 示例
pip install aio-limit
from aio_limit import Limiter
import asyncio
import time
class AdvancedTrafficController:
def __init__(self):
# 创建限流器:每秒10个请求,最大积攒20个
self.limiter = Limiter(rate=10, burst=20)
async def limited_task(self, task_id):
"""限流任务"""
async with self.limiter:
# 模拟任务处理
await asyncio.sleep(0.1)
print(f"任务 {task_id} 在 {time.time():.2f} 执行")
return task_id
async def main():
controller = AdvancedTrafficController()
# 模拟突发流量
tasks = [controller.limited_task(i) for i in range(50)]
results = await asyncio.gather(*tasks)
print(f"完成 {len(results)} 个任务")
if __name__ == "__main__":
asyncio.run(main())
使用Redis实现分布式限流
import redis
import time
import threading
class RedisTrafficShaper:
def __init__(self, redis_client, rate_limit=10, window_size=1):
self.redis = redis_client
self.rate_limit = rate_limit
self.window_size = window_size # 窗口大小(秒)
def acquire(self, key="traffic_shaper"):
"""获取处理权限"""
window_key = f"{key}:{int(time.time() / self.window_size)}"
# 使用Redis事务
pipe = self.redis.pipeline()
pipe.incr(window_key)
pipe.expire(window_key, self.window_size * 2)
current_count = pipe.execute()[0]
if current_count <= self.rate_limit:
return True
return False
# 使用示例
if __name__ == "__main__":
r = redis.Redis(host='localhost', port=6379, db=0)
shaper = RedisTrafficShaper(r, rate_limit=10)
def worker(worker_id):
for i in range(20):
if shaper.acquire():
print(f"Worker {worker_id}: 任务 {i} 执行")
time.sleep(0.1)
else:
print(f"Worker {worker_id}: 任务 {i} 限流")
time.sleep(0.2)
# 启动多个worker
threads = []
for i in range(3):
t = threading.Thread(target=worker, args=(i,))
t.start()
threads.append(t)
for t in threads:
t.join()
选择建议
| 场景 | 推荐方案 |
|---|---|
| 单机简单限流 | 令牌桶 + threading |
| 高并发异步任务 | asyncio + 信号量 |
| 精确速率控制 | aio-limit 第三方库 |
| 分布式系统 | Redis 实现 |
| 需要背压处理 | 队列 + 水位控制 |
选择合适的方法需要考虑:
- 并发量级
- 是否需要分布式支持
- 精度要求
- 系统复杂度
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播