面试题答案
一键面试设计方案
- 连接池管理:使用
aiohttp
的ClientSession
并配置连接池大小,以控制并发连接数,避免资源耗尽。 - 异步I/O操作:利用
asyncio
的异步特性,对文件的读写和网络请求进行异步操作,提高效率。 - 错误处理与重试:在网络丢包或请求失败时,实现重试机制,确保文件传输的可靠性。
关键代码片段
import asyncio
import aiohttp
import os
async def upload_file(session, file_path, server_url):
max_retries = 3
retries = 0
while retries < max_retries:
try:
async with session.post(server_url, data=open(file_path, 'rb')) as response:
if response.status == 200:
return True
else:
print(f"Upload failed with status {response.status}")
except (aiohttp.ClientError, OSError) as e:
print(f"Upload error: {e}")
retries += 1
await asyncio.sleep(1)
return False
async def download_file(session, file_path, server_url):
max_retries = 3
retries = 0
while retries < max_retries:
try:
async with session.get(server_url) as response:
if response.status == 200:
with open(file_path, 'wb') as f:
while True:
chunk = await response.content.read(1024)
if not chunk:
break
f.write(chunk)
return True
else:
print(f"Download failed with status {response.status}")
except (aiohttp.ClientError, OSError) as e:
print(f"Download error: {e}")
retries += 1
await asyncio.sleep(1)
return False
async def main():
# 配置连接池大小,例如设置为10
connector = aiohttp.TCPConnector(limit=10)
async with aiohttp.ClientSession(connector=connector) as session:
upload_tasks = []
download_tasks = []
# 示例上传任务
for file in os.listdir('.'):
if os.path.isfile(file):
upload_tasks.append(upload_file(session, file, 'http://server/upload'))
# 示例下载任务
for i in range(5):
download_tasks.append(download_file(session, f'download_{i}.txt', 'http://server/download'))
await asyncio.gather(*upload_tasks, *download_tasks)
if __name__ == "__main__":
asyncio.run(main())
在上述代码中:
upload_file
和download_file
函数分别实现了文件的上传和下载功能,在遇到错误时会进行重试。main
函数中创建了aiohttp.ClientSession
并通过TCPConnector
设置了连接池大小为10,以此控制并发连接数。- 同时创建了多个上传和下载任务,并使用
asyncio.gather
并发执行这些任务。