本文目录导读:

在Python中动态调整异步并发量,主要有以下几种方法:
使用信号量(Semaphore)控制并发
import asyncio
import random
class DynamicConcurrencyController:
def __init__(self, initial_concurrency=5):
self.semaphore = asyncio.Semaphore(initial_concurrency)
self.current_concurrency = initial_concurrency
self.max_concurrency = 20
async def adjust_concurrency(self, new_limit):
"""动态调整并发量"""
old_limit = self.current_concurrency
self.current_concurrency = min(new_limit, self.max_concurrency)
if new_limit > old_limit:
# 增加并发:创建新的信号量
self.semaphore = asyncio.Semaphore(self.current_concurrency)
# 注意:减少并发需要等待当前任务完成
print(f"并发数调整: {old_limit} -> {self.current_concurrency}")
async def process_task(self, task_id):
async with self.semaphore:
print(f"处理任务 {task_id},当前并发: {self.current_concurrency}")
# 模拟异步任务
await asyncio.sleep(random.uniform(0.5, 2))
return f"任务 {task_id} 完成"
async def run(self, tasks):
"""运行任务集合"""
# 启动一个后台任务定期调整并发
adjust_task = asyncio.create_task(self.auto_adjust())
# 处理所有任务
results = []
for task_id in tasks:
result = await self.process_task(task_id)
results.append(result)
adjust_task.cancel()
return results
async def auto_adjust(self):
"""自动调整并发量的示例"""
while True:
await asyncio.sleep(3)
# 模拟根据系统负载调整
new_limit = random.randint(3, 10)
await self.adjust_concurrency(new_limit)
# 使用示例
async def main():
controller = DynamicConcurrencyController(initial_concurrency=3)
tasks = list(range(1, 12))
results = await controller.run(tasks)
print("所有任务完成:", results)
# asyncio.run(main())
使用队列 + 工作线程模式
import asyncio
from collections import deque
class DynamicAsyncPool:
def __init__(self, max_workers=10, min_workers=1):
self.max_workers = max_workers
self.min_workers = min_workers
self.current_workers = min_workers
self.task_queue = asyncio.Queue()
self.workers = []
self.running = True
# 启动初始工作线程
for _ in range(min_workers):
self._start_worker()
def _start_worker(self):
"""启动一个工作线程"""
worker = asyncio.create_task(self._worker_loop())
self.workers.append(worker)
async def _worker_loop(self):
"""工作线程主循环"""
while self.running:
try:
task = await asyncio.wait_for(
self.task_queue.get(),
timeout=1.0
)
try:
await task
finally:
self.task_queue.task_done()
except asyncio.TimeoutError:
continue
async def adjust_workers(self, target_count):
"""调整工作线程数量"""
target_count = max(self.min_workers,
min(self.max_workers, target_count))
while len(self.workers) < target_count:
self._start_worker()
print(f"添加工作线程,当前: {len(self.workers)}")
while len(self.workers) > target_count:
worker = self.workers.pop()
worker.cancel()
print(f"移除工作线程,当前: {len(self.workers)}")
self.current_workers = len(self.workers)
async def submit_task(self, coro):
"""提交任务"""
await self.task_queue.put(coro)
async def wait_completion(self):
"""等待所有任务完成"""
await self.task_queue.join()
# 使用示例
async def example_task(task_id, delay):
print(f"开始任务 {task_id}")
await asyncio.sleep(delay)
print(f"完成任务 {task_id}")
return task_id
async def main():
pool = DynamicAsyncPool(max_workers=10, min_workers=2)
# 提交多个任务
for i in range(20):
task = example_task(i, 1.0)
await pool.submit_task(task)
# 动态调整并发
await asyncio.sleep(2)
await pool.adjust_workers(5) # 增加到5个worker
await asyncio.sleep(2)
await pool.adjust_workers(3) # 减少到3个worker
await pool.wait_completion()
print("所有任务完成")
# asyncio.run(main())
基于系统负载的自适应调整
import asyncio
import psutil # 需要安装: pip install psutil
import time
class AdaptiveConcurrencyManager:
def __init__(self,
min_concurrency=1,
max_concurrency=50,
target_cpu_usage=70.0,
target_memory_usage=80.0):
self.min_concurrency = min_concurrency
self.max_concurrency = max_concurrency
self.target_cpu_usage = target_cpu_usage
self.target_memory_usage = target_memory_usage
self.current_concurrency = min_concurrency
self.semaphore = asyncio.Semaphore(min_concurrency)
self.adjusting = False
async def monitor_and_adjust(self):
"""监控系统资源并动态调整"""
while True:
if not self.adjusting:
self.adjusting = True
try:
# 获取系统资源使用情况
cpu_percent = psutil.cpu_percent(interval=1)
memory_percent = psutil.virtual_memory().percent
# 根据负载调整并发
new_concurrency = self._calculate_optimal_concurrency(
cpu_percent, memory_percent
)
if new_concurrency != self.current_concurrency:
await self._apply_concurrency_change(new_concurrency)
print(f"CPU: {cpu_percent}%, 内存: {memory_percent}%, "
f"并发: {self.current_concurrency}")
finally:
self.adjusting = False
await asyncio.sleep(5) # 每5秒检查一次
def _calculate_optimal_concurrency(self, cpu_percent, memory_percent):
"""计算最优并发数"""
usage_ratio = max(cpu_percent / self.target_cpu_usage,
memory_percent / self.target_memory_usage)
if usage_ratio > 1.0:
# 负载过高,减少并发
new_concurrency = int(self.current_concurrency / usage_ratio)
else:
# 负载可接受,考虑增加并发
ratio = 1.0 / usage_ratio if usage_ratio > 0 else 1.0
new_concurrency = int(self.current_concurrency * min(ratio, 1.5))
return max(self.min_concurrency,
min(self.max_concurrency, new_concurrency))
async def _apply_concurrency_change(self, new_concurrency):
"""应用并发数变更"""
old_concurrency = self.current_concurrency
if new_concurrency > old_concurrency:
# 增加并发
self.semaphore = asyncio.Semaphore(new_concurrency)
self.current_concurrency = new_concurrency
print(f"增加并发: {old_concurrency} -> {new_concurrency}")
elif new_concurrency < old_concurrency:
# 减少并发需要等待
print(f"准备减少并发: {old_concurrency} -> {new_concurrency}")
self.current_concurrency = new_concurrency
# 在实际应用中,这里需要更复杂的逻辑来等待活跃任务完成
async def execute_with_limit(self, task_func, *args, **kwargs):
"""在并发限制下执行任务"""
async with self.semaphore:
return await task_func(*args, **kwargs)
# 使用示例
async def main():
manager = AdaptiveConcurrencyManager(
min_concurrency=1,
max_concurrency=10,
target_cpu_usage=70.0
)
# 启动监控任务
monitor_task = asyncio.create_task(manager.monitor_and_adjust())
async def cpu_intensive_task(task_id):
"""模拟CPU密集型任务"""
print(f"开始任务 {task_id}")
# 模拟计算
for _ in range(10**6):
_ = 2 ** 10
await asyncio.sleep(0.5)
print(f"完成任务 {task_id}")
return task_id
# 执行多个任务
tasks = []
for i in range(20):
tasks.append(manager.execute_with_limit(cpu_intensive_task, i))
results = await asyncio.gather(*tasks)
monitor_task.cancel()
print(f"所有任务完成: {results}")
# asyncio.run(main())
使用第三方库:aiolimiter
import asyncio
from aiolimiter import AsyncLimiter # 需要安装: pip install aiolimiter
async def dynamic_limiter_example():
"""使用aiolimiter实现动态限流"""
limiter = AsyncLimiter(5, 1) # 初始每秒5个请求
async def adjust_rate(new_rate):
"""动态调整速率限制"""
limiter.max_rate = new_rate
# 注意:aiolimiter不支持直接改变rate,这里需要重建
nonlocal limiter
limiter = AsyncLimiter(new_rate, 1)
print(f"调整速率: {new_rate}")
async def task(item):
# 使用限流器控制并发
async with limiter:
print(f"处理项目: {item}")
await asyncio.sleep(0.2)
return item
# 模拟动态调整
tasks = [task(i) for i in range(10)]
await asyncio.sleep(1)
await adjust_rate(10) # 增加到每秒10个
results = await asyncio.gather(*tasks)
print(f"结果: {results}")
# asyncio.run(dynamic_limiter_example())
关键要点
- 安全调整:增加并发相对安全,但减少并发时需要等待活跃任务完成
- 资源监控:结合实际系统资源(CPU、内存、网络)动态调整
- 平滑过渡:避免频繁大幅调整,使用渐进式变化
- 回调机制:可以在并发调整前后添加回调函数
选择哪种方法取决于你的具体需求:
- 简单的并发控制:使用Semaphore
- 需要队列管理:使用工作线程模式
- 系统自适应:使用资源监控方案
- 速率限制:使用aiolimiter等专业库
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播