优化asyncio性能及解决资源竞争的措施
- 数据库连接池:使用连接池管理数据库连接,避免每次请求都创建新的连接,减少连接开销。例如使用
aiomysql
库的连接池:
import aiomysql
async def get_connection():
pool = await aiomysql.create_pool(
host='127.0.0.1',
port=3306,
user='user',
password='password',
db='test',
autocommit=True
)
async with pool.acquire() as conn:
async with conn.cursor() as cur:
await cur.execute('SELECT * FROM some_table')
result = await cur.fetchall()
pool.close()
await pool.wait_closed()
return result
- 合理使用协程数量:根据服务器资源(如CPU、内存等)设置合适的并发协程数量。可以使用信号量(
Semaphore
)来限制并发数。
import asyncio
semaphore = asyncio.Semaphore(100) # 允许同时运行100个协程
async def handle_request():
async with semaphore:
# 处理请求,从数据库读取数据等操作
await asyncio.sleep(1) # 模拟I/O操作
return "Response"
async def main():
tasks = [handle_request() for _ in range(1000)]
results = await asyncio.gather(*tasks)
print(results)
- 避免阻塞操作:确保在协程中不执行阻塞I/O或CPU密集型操作。对于CPU密集型任务,可以使用
concurrent.futures.ProcessPoolExecutor
或 ThreadPoolExecutor
在单独的线程或进程中执行,然后通过 await loop.run_in_executor
来调用。
import asyncio
import concurrent.futures
def cpu_intensive_task():
# 模拟CPU密集型操作
result = 0
for i in range(1000000):
result += i
return result
async def main():
loop = asyncio.get_running_loop()
with concurrent.futures.ProcessPoolExecutor() as executor:
result = await loop.run_in_executor(executor, cpu_intensive_task)
print(result)
- 锁机制:当多个协程需要访问共享资源(如全局变量)时,使用锁(
Lock
)来防止资源竞争。
import asyncio
lock = asyncio.Lock()
shared_variable = 0
async def modify_shared_variable():
global shared_variable
async with lock:
shared_variable += 1
await asyncio.sleep(0.1) # 模拟I/O操作
shared_variable -= 1
async def main():
tasks = [modify_shared_variable() for _ in range(10)]
await asyncio.gather(*tasks)
print(shared_variable) # 输出应为0,表明没有资源竞争
- 优化事件循环:尽量减少事件循环中的不必要操作,确保事件循环能够高效地调度协程。例如,合理安排任务的优先级,避免长时间占用事件循环。
- 缓存机制:对于频繁读取且不经常变化的数据,可以使用缓存(如
functools.lru_cache
或分布式缓存如 Redis
)来减少数据库的读取压力。
import functools
@functools.lru_cache(maxsize=128)
def cached_function():
# 从数据库读取数据的操作
return "Data from database"
async def handle_cached_request():
result = cached_function()
return result