Hướng dẫn nâng cấp aiohttp 2.x: Phân tích thay đổi lớn ở client và server
Giới thiệu
aiohttp - framework HTTP đồng bộ/asynchronous hàng đầu trong hệ sinh thái Python đã có nhiều cải tiến quan trọng trong phiên bản 2.x. Bài viết này sẽ phân tích chi tiết các thay đổi này, giúp lập trình viên thực hiện quá trình nâng cấp một cách hiệu quả. Chúng ta sẽ tìm hiểu cụ thể từng thay đổi ở cả hai thành phần client và server.
Thay đổi ở phía client
Tối ưu cơ chế truyền dữ liệu
Mã hóa phân đoạn (chunking)
Phiên bản 2.x loại bỏ hỗ trợ tùy chỉnh kích thước phân đoạn. Người dùng cần tự quản lý việc chia nhỏ luồng dữ liệu. Khi bật chế độ chunked, aiohttp sẽ tự động thêm header "Transfer-encoding: chunked".
Điểm thay đổi chính:
- Không còn tự động kích hoạt mã hóa phân đoạn dù có header transfer-encoding
- Phải thiết lập tham số chunked để kích hoạt
- Không cho phép đồng thời header Transfer-encoding và content-length khi dùng chunked
Nén dữ liệu (compression)
Tính năng nén dữ liệu phải được kích hoạt qua tham số compress:
- Không cho phép thêm header content-encoding khi nén
- Nén tự động kích hoạt mã hóa chunked
- Không thể sử dụng cùng lúc Content-Length khi nén
Tái cấu trúc connector
Các thay đổi quan trọng trong connector:
- Mô hình giới hạn kết nối:
- Trước: giới hạn kết nối theo host
- Bây giờ:
limitđiều khiển tổng kết nối đồng thờilimit_per_hostđiều khiển kết nối mỗi host- Mặc định không giới hạn host
- Phương thức đóng kết nối:
BaseConnector.closechuyển thành phương thức thông thường
- Thời gian chờ:
BaseConnector.conn_timeoutdi chuyển sangClientSession
Cải tiến xử lý response
Response object được tái thiết kế hoàn toàn:
- Không cần gọi
releasethủ công - Kết nối tự động trả về pool sau khi nhận đủ dữ liệu
- Kết nối bị đóng nếu dữ liệu chưa được đọc hết
Sửa đổi hệ thống exception
Cấu trúc exception được thay đổi lớn:
- Giảm loại exception:
- Chỉ giữ lại exception liên quan đến kết nối và phản hồi server
- Lỗi code sai tiếp tục dùng exception chuẩn Python
- Thêm lỗi nội dung:
- Có thể gặp
ClientPayloadErrorkhi đọc nội dung phản hồi
- Điều chỉnh module:
- Tất cả exception di chuyển từ
aiohttp.errorssangaiohttp
Hệ thống payload mới
Hệ thống Payload được giới thiệu để xử lý dữ liệu form:
- Thay đổi FormData:
FormData.__call__loại bỏ tham số encoding- Trả về Payload instance thay vì iterator/bytes
- Tự động hỗ trợ các kiểu dữ liệu phổ biến (str, byte, io.IOBase)
- Giải pháp thay thế generator:
- Hỗ trợ generator bị loại bỏ
- Sử dụng decorator
@aiohttp.streamerđể upload luồng
Ví dụ:
@aiohttp.streamer
def file_sender(writer, file_path=None):
with open(file_path, 'rb') as f:
while chunk := f.read(2**16):
yield from writer.write(chunk)
async with session.post(url, data=file_sender('large_file')) as resp:
print(await resp.text())
Các thay đổi khác
- Tham số mã hóa:
- Tham số encoding trong
ClientSession.request()đã bị loại bỏ - Quyết định mã hóa tại cấp độ Payload
- Tham số phiên bản:
- Tham số version trong
ClientSession.request()bị xóa - Thiết lập phiên bản qua constructor
ClientSession
- Hằng số kiểu:
aiohttp.MsgTypethay bằngaiohttp.WSMsgType
- Xử lý URL:
ClientResponse.urltrả về instanceyarl.URLurl_objbị loại bỏ
- Kiểm tra trạng thái:
ClientResponse.raise_for_status()némaiohttp.ClientResponseError
- Đọc JSON nghiêm ngặt:
ClientResponse.json()kiểm tra chặt chẽ content-type- Dùng
content_type=Noneđể tắt kiểm tra
Thay đổi ở phía server
Tái thiết kế giao thức
Thay đổi lớn để cải thiện hiệu năng và hỗ trợ HTTP pipelining:
ServerHttpProtocolbị loại bỏ- Gộp chức năng vào
RequestHandler - Nhiều API cấp thấp bị xóa
Ứng dụng (Application)
- Xử lý vòng lặp sự kiện:
- Tham số
looptrong constructor bị loại bỏ - Vòng lặp được cấu hình tự động qua
run_app
- Đường dẫn con:
Application.router.add_subappbị xóa- Thay bằng
Application.add_subapp
- Sự kiện hoàn thành:
Application.finishedbị xóa- Thay bằng
Application.cleanup
Request/Response
- Xử lý tham số:
- Thuộc tính
GETvàPOSTbị xóa - Sử dụng
querythay thếGET
- Mã hóa phân đoạn:
- Không còn hỗ trợ tùy chỉnh kích thước phân đoạn
- Người dùng tự quản lý logic phân đoạn
- Hỗ trợ payload:
- Có thể dùng Payload làm nội dung phản hồi
- Dùng nội dung phản hồi client làm body cho
WebResponse
- API gửi file:
FileSenderbị xóa- Thay bằng
FileResponselinh hoạt hơn
Ví dụ:
async def handle(request):
return web.FileResponse('document.txt')
- Thuộc tính WebSocket:
WebSocketResponse.protocolđổi tên thànhws_protocol- Thuộc tính
protocolhiện là instanceRequestHandler
Lỗi payload request
Thêm exception RequestPayloadError hoạt động tương tự ClientPayloadError để xử lý lỗi đọc payload request.
Hỗ trợ WSGI
- Loại bỏ hoàn toàn hỗ trợ WSGI
- Bao gồm worker WSGI cho gunicorn
- Vẫn giữ worker gunicorn mặc định và uvloop cho
web.Application
Gợi ý nâng cấp
- Nâng cấp từng bước:
- Xử lý client trước, server sau
- Bắt đầu từ các module đơn giản
- Kiểm tra trọng tâm:
- Logic xử lý lỗi
- Triển khai upload/download
- Cấu hình pool kết nối
- Chiến lược test:
- Tăng cường test trường hợp biên
- Tập trung vào tình huống truyền luồng
- Tối ưu hiệu năng:
- Tận dụng tham số giới hạn kết nối mới
- Kiểm tra sử dụng RAM với tải khác nhau
Bài viết trên đã phân tích chi tiết các thay đổi lớn của aiohttp 2.x. Phiên bản mới cải thiện đáng kể hiệu năng và tính nhất quán của API, xứng đáng để dành thời gian nâng cấp.