HTTP/3 – giao thức thế hệ mới có gì hot?

HTTP/3 – giao thức thế hệ mới có gì hot?
Photo by Thomas Jensen from Unsplash

Internet ngày càng phát triển và được sử dụng rộng rãi. Các ứng dụng web ngày càng phức tạp hơn, yêu cầu về một giao thức kết nối an toàn và hiện đại. HTTP/3 đã được phát triển nhằm đáp ứng nhu cầu đó. Bài viết này sẽ trình bày những điểm mới của giao thức này.

Lịch sử HTTP

HTTP (Hypertext Transfer Protocol – giao thức truyền tin siêu văn bản) là một trong những giao thức quan trọng nhất của Internet hiện nay. Gần như mọi dữ liệu trên web đều được truyền tải thông qua HTTP.

Được giới thiệu cách đây hơn 30 năm, phiên bản đầu tiên – HTTP/0.9 – còn khá đơn giản (được gọi là one-line protocol). Phiên bản này chỉ có phương thức GET và không có header. Năm 1996, HTTP/1.0 được giới thiệu, đã bổ sung HTTP status code, các phương thức POSTHEAD, header và cache.

HTTP/1.1 được công bố sau đó chỉ vài tháng, vào đầu năm 1997. HTTP/1.1 mang đến sự thay đổi lớn với đầy đủ các phương thức, keep-alive và đặc biệt là header Host. Chính header này đã thay đổi hoàn toàn cách các trang web hoạt động. Nhờ đó, nhiều host (domain) khác nhau có thể được triển khai trên cùng máy chủ với cùng địa chỉ IP.

Năm 2015, phiên bản mới của giao thức, HTTP/2 được công bố với sự thay đổi ở tầng ứng dụng. Bằng việc sử dụng giao SPDY (giao thức được phát triển bởi Google), HTTP/2 mang đến nhiều thay đổi lớn: truyền dữ liệu dạng nhị phân, HPACK nén header, ghép kênh, đánh số ưu tiên, server push, v.v… Những tính năng này cho phép gửi và nhận nhiều file trong một truy vấn.

Với sự xuất hiện của HTTP/2, người ta kỳ vọng vào sự thay đổi lớn về tốc độ tải của các trang web. Thế nhưng thực tế áp dụng HTTP/2 không mang lại hiệu quả như lý thuyết. Áp dụng server push cũng như việc đánh số ưu tiên cho các gói tin không hề đơn giản. Do đó, HTTP/2 khó có thể phát huy được hết khả năng của mình.

Trong nỗ lực cải thiện tốc độ tải trang, Google (lại là cái tên này 😂) đã nghiên cứu một giao thức mới, đặt tên là QUIC (Quick UDP Internet Connections).

Từ giao thức này, IETF đã xây dựng đặc tả kỹ thuật cho một giao thức QUIC khác vào năm 2021 (RFC 9000). QUIC (đọc giống “quick”) của IETF không phải là từ viết tắt, và dù tên rất giống nhau, hai giao thức này có nhiều điểm khác biệt. Có thể coi đây là một giao thức hoàn toàn mới (nhiều người gọi giao thức của Google là gQUIC để phân biệt).

Năm 2022, IETF công bố đặc tả kỹ thuật của HTTP/3 ở tầng ứng dụng dựa trên QUIC ở tầng dưới. Mặc dù QUIC luôn được nhắc đến cùng với HTTP/3, giao thức này được thiết kế để có thể dùng với mọi giao thức trên tầng ứng dụng.

Xem toàn bộ lịch sử của HTTP ở đây.

HTTP/3

Giao thức HTTP/3 rất phức tạp, và tôi cũng không định đi sâu vào nó trong bài viết này. Ở đây, tôi chỉ muốn nói đến những điểm mới mà HTTP/3 mang đến cho thế giới web. Toàn bộ đặc tả kỹ thuật của HTTP/3 ở RFC 9114.

Giao thức HTTP/2 được phát triển để cải thiện tốc độ tải trang. HTTP/3 vẫn tiếp tục mục tiêu này với việc sử dụng QUIC, giao thức được cho là có tốc độ tốt hơn.

Về mặt “tính năng”, khác với những phiên bản tiền nhiệm, HTTP/3 không mang đến tính năng nào mới. Về cơ bản, các tính năng HTTP/3 tương tự như HTTP/2. Sự khác biệt đến từ cơ chế hoạt động bên trong.

HTTP/3 lúc đầu được đặt tên là “HTTP-over-QUIC” bởi vì nó tiếp tục tối ưu những tính năng mà HTTP/2 đã có với giao thức QUIC. Hầu như mọi tính năng của HTTP/3 đều đến từ QUIC, bao gồm bảo mật, mã hóa dữ liệu, ghép kênh, v.v…

QUIC là một giao thức đem đến rất nhiều cải tiến về thiết kế để tăng tốc độ: giảm đáng kể thời gian thiết lập kết nối, cải thiện kiểm soát tắc nghẽn, ghép kênh mà không bị Head of Line (HOL) Blocking, v.v…

Sự khác biệt của HTTP/3 so với HTTP/1.1, HTTP/2

Hình ảnh dưới đây mô tả sự khác biệt giữa HTTP/3 và các phiên bản trước đó. Sự khác biệt lớn nhất ở tầng giao vận (transport layer): giao thức HTTP/1.1 và HTTP/2 sử dụng TCP, trong khi đó, HTTP/3 sử dụng giao thức QUIC với UDP.

Một sự khác biệt lớn khác là sự thay đổi cấu trúc và vai trò của các tầng mạng. Rất nhiều chức năng của tầng ứng dụng (HTTP, TLS) và tầng giao vận (TCP) được tích hợp vào QUIC.

HTTP
Nguồn: Robin Marx

Sự khác biệt giữa TCP và UDP

TCP yêu cầu xác nhận việc gửi và nhận các gói tin. Vì vậy, TCP yêu cầu thiết lập các kết nối trước khi gửi gói tin chính. Giao thức TCP có độ tin cậy cao, các gói tin được gửi bằng TCP sẽ được theo dõi do vậy dữ liệu sẽ không bị mất hoặc hỏng.

Giao thức TCP đạt được điều này theo hai cách. Đầu tiên, nó yêu cầu các gói tin bằng cách đánh số chúng. Thứ hai, nó kiểm tra lỗi bằng cách yêu cầu bên nhận gửi phản hồi đã nhận được cho bên gửi. Nếu bên gửi không nhận được phản hồi đúng, nó có thể gửi lại gói tin để đảm bảo bên nhận nhận chúng một cách chính xác.

Nhưng cách làm này khiến dữ liệu cần truyền tải tăng lên đáng kể (làm giảm tốc độ), đồng thời có thể dẫn đến HOL Blocking. Vì các gói tin phải được nhận theo đúng thứ tự, nếu một gói tin bị mất thì tất cả các gói tin khác sẽ bị block.

Ngược lại, giao thức UDP không yêu cầu việc xác nhận, cũng như không đánh số thứ tự cho các gói tin này. Nhờ vậy, UDP giảm thiểu được lượng thông tin trao đổi giữa, giúp giảm tải những dữ liệu dư thừa. Kết quả, UDP có tốc độ cao hơn hẳn TCP nên thích hợp với những ứng dụng yêu cầu tốc độ như streaming, RTP, v.v…

Nhưng đặc trưng này cũng mang lại một điểm yếu chí tử: kết nối UDP là không đảm bảo. Không thể chắc chắn rằng bên nhận đã nhận được gói tin, cũng như đọc các gói tin này theo một thứ tự chính xác hay không.

Giao thức QUIC được xây dựng ở tầng trên của UDP để đảm bảo việc gửi và nhận các gói tin. Khi một gói tin UDP bị mất, nó sẽ được xử lý ở tầng QUIC: gửi lại hoặc bỏ qua. HTTP/3 được xây dựng trên QUIC, do đó, mặc dù sử dụng UDP ở tầng dưới, nó vẫn là một kết nối đảm bảo, tương tự như HTTP/1.1 và HTTP/2 sử dụng TCP.

Ghép kênh (multiplex)

Phiên bản HTTP/1.1 chưa có ghép kênh. Do đó, mỗi một thành phần của trang web sẽ phải tải bằng một truy vấn riêng biệt. HTTP/2 đã bổ sung khả năng ghép kênh, cho phép tải xuống nhiều thành phần trong cùng một kết nối TCP.

HTTP/3 tiếp tục nâng cao tốc độ của việc ghép kênh khi sử dụng lợi thế của UDP. Kết nối UDP sẽ được chia thành nhiều luồng (stream), mỗi luồng là một chuỗi dữ liệu có thứ tự. Dữ liệu được kiểm soát trên từng luồng riêng lẻ và trên toàn bộ kết nối.

Từ phiên bản HTTP/2, header đã được nén bằng HPACK. Điều này sẽ giảm lượng dữ liệu cần truyền tải giúp tăng tốc độ tải trang.

Cụ thể, HPACK nén dữ liệu header bằng Huffman code. Đồng thời, cơ chế của nó dùng bảng chỉ mục (được đồng bộ giữa bên gửi và nhận) chứa các header đã được gửi (hoặc nhận) trong truy vấn trước đó. Điều đó cho phép các truy vấn tham chiếu các header cũ mà không truyền đi truyền lại.

HTTP/3 sử dụng QPACK để nén header (vì dùng UDP nên cũng không thể sử dụng HPACK). Cơ chế của QPACK tương tự như HPACK: nén bằng Huffman code và sử dụng bảng chỉ mục các header đã dùng trước đó. Tuy nhiên, QPACK có một số điểm cải tiến:

  • QPACK chỉ dùng 1 bảng chỉ mục cho tất cả mọi kết nối, trong khi HPACK có 2 bảng: 1 bảng tĩnh chứa các header chung cho mọi kết nối và 1 bảng động cho từng kết nối.
  • QPACK có thuật toán nén hiệu quả hơn, cho phép nén dữ liệu chỉ còn vài byte, việc nén và giải nén đơn giản, nhanh chóng hơn so với HPACK.
  • QPACK mềm dẻo hơn HPACK, cho phép tùy biến việc nén dữ liệu, cũng như dữ liệu có thể được dùng ở nhiều giao thức khác nhau ở tầng dưới (không nhất thiết phải là UDP).

Đổi lại, QPACK yêu cầu mở thêm hai luồng dữ liệu: encoder & decoder. Encoder chứa các lệnh để decoder thực hiện và ngược lại. Khác với các luồng dữ liệu khác của HTTP/3, hai luồng dữ liệu này chỉ hoạt động một chiều. Nghĩa là chúng chỉ cần gửi dữ liệu đi mà không cần chờ phản hồi.

Hai luồng dữ liệu này tương đối nhẹ, và có thể coi đây là một sự đánh đổi đáng giá.

Bảo mật

HTTP/3 tích hợp trực tiếp giao thức TLS v1.3 vào trong QUIC. Vì vậy, dữ liệu truyền qua truy vấn HTTP sẽ luôn được mã hóa, tức là HTTP/3 sẽ luôn là HTTPS.

Việc tích hợp trực tiếp TLS (lại là phiên bản mới nhất) vào QUIC cũng giúp tăng tốc HTTP. Với HTTPS ở các phiên bản trước, quá trình bắt tay phải diễn ra thành ít nhất 2 bước nối tiếp nhau – TCP và TLS – trước khi quá trình trao đổi dữ liệu thực sự diễn ra.

TLS v1.2 yêu cầu 2 bước bắt tay TLS, kết hợp với TCP sẽ thành 3 bước bắt tay nối tiếp nhau.

tls
Nguồn: The Cloudflare Blog

Bằng việc tích hợp TLS, QUIC kết hợp hai bước bắt tay khiến chúng diễn ra đồng thời. Máy khách và máy chủ xác nhận rằng kết nối và đồng thời cũng trao đổi khóa TLS.

http/3
Nguồn: The Cloudflare Blog

Ngoài ra, việc tích hợp TLS được thực hiện ở giao thức tầng dưới cũng giúp HTTP/3 bảo mật hơn. Với các phiên bản trước, TLS chạy trên tầng ứng dụng. Do đó, chỉ có các dữ liệu HTTP được mã hóa, còn header trong gói tin TCP thì không. HTTP/3 tích hợp TLS vào QUIC, nhờ vậy, không chỉ dữ liệu HTTP được mã hóa và hầu hết các header trong gói tin QUIC cũng được mã hóa.

Độ ưu tiên

Độ ưu tiên cũng là một trong các biện pháp tăng tốc độ tải trang. Mỗi luồng dữ liệu sẽ có độ ưu tiên của riêng nó. Bằng cách sắp xếp nội dung vào các luồng phù hợp, nội dung quan trọng sẽ được tải trước. Trong trường hợp trang web lớn, dữ liệu nhiều, người dùng sẽ sớm nhận được những nội dung cần thiết, thay vì phải chờ tải toàn bộ trang web.

Mất gói tin

Mất gói tin (packet loss) luôn là vấn đề của Internet từ trước đến giờ. Giờ đây, khi người dùng mạng di động ngày càng nhiều, vấn đề này càng cần phải quan tâm. Sóng LTE, 4G, 5G có thể bị chắn, phản xạ bởi môi trường khiến các gói tin bị thất lạc trên đường vận chuyển nhiều hơn.

Một vấn đề khác là độ trễ không đồng đều giữa các gói tin. Ngoài ra, không có gì đảm bảo rằng các gói tin được nhận theo đúng thứ tự chúng được gửi đi. Những vấn đề này sẽ dẫn đến vấn đề HOL Blocking.

Với kết nối TCP, khi một gói tin bị mất trên đường vận chuyển, bên nhận sẽ yêu cầu gửi lại một gói tin khác. Trước khi toàn bộ các gói tin đã được nhận đầy đủ và chính xác, phía bên nhận chưa thể truy cập được đến dữ liệu đang dang dở. Với TCP, việc mất một gói tin cũng sẽ block toàn bộ, khiến những dữ liệu đã nhận được cũng trở thành vô dụng vì dữ liệu không đầy đủ và chưa được xác nhận.

Vấn đề này sẽ được giải quyết trong giao thức QUIC. QUIC sử dụng nhiều thread khác nhau để truyền dữ liệu. Nếu một gói tin bị mất, thread chứa gói tin đó sẽ yêu cầu gửi lại. Những thread khác vẫn được sử dụng dữ liệu bình thường.

Hiệu suất

HTTP/3 được cho là nhanh hơn và sử dụng băng tầng mạng hiệu quả hơn. Sự hiệu quả thể hiện rõ ở những ứng dụng cần truyền tải một số lượng lớn những gói tin nhỏ như Twitch hay YouTube. Việc tải xuống các file cũng ổn định hơn. Nếu kết nối bị đứt giữa chừng, quá trình sẽ lại tiếp tục khi mạng được kết nối trở lại.

Những hạn chế của HTTP/3 và QUIC

Mặc dù có những cải tiến đáng kể, HTTP/3 và QUIC vẫn tồn tại những hạn chế nhất định.

Hiệu suất phụ thuộc vào từng cài đặt

Dù đặc tả kỹ thuật của QUIC rất rõ ràng và cho phép cài đặt thuật toán tương đối tự do, việc triển khai từng tính năng cụ thể lại rất khó khăn. Ví dụ như việc ghép kênh, nếu thuật toán không được tối ưu, vấn đề HOL Blocking vẫn có thể xảy ra.

Thực tế triển khai HTTP/3 hiện nay cũng cho thấy nhiều chênh lệch trong hiệu suất, tùy thuộc vào từng cài đặt cụ thể. Rất khó để nói rằng tại sao cách làm này lại tốt hơn cách làm kia. Ngoài ra, việc cài đặt giao thức QUIC không được thực hiện ở những tầng thấp mà ở user space, khiến cho nó dễ bị tổn thương trước các đợt tấn công DDoS.

IETF đã tổng hợp lại những cách cài đặt khác nhau của QUIC ở đây.

Kết nối HTTP/3 phải thông qua phiên bản cũ

Hiện tại, HTTP/3 không thể được sử dụng ngay từ truy vấn đầu tiên. Các trình duyệt đều được cài đặt với giả định rằng, server chưa hỗ trợ HTTP/3. Do đó, truy vấn đầu tiên sẽ được thực hiện bằng HTTP/2 hoặc HTTP/1.1 sử dụng TCP.

Nếu server hỗ trợ HTTP/3, kết quả phản hồi sẽ có thêm header Alt-Svc (Alternative Service) thông báo rằng HTTP/3 được hỗ trợ. Lúc này, trình duyệt có 2 lựa chọn: tạo một kết nối QUIC ngay lập tức hoặc chờ kết nối TCP kết thúc.

Dù triển khai theo phương án nào, kết nối HTTP/3 cũng chỉ được thiết lập sau khi những dữ liệu đầu tiên đã được tải xuống bằng HTTP/2 hoặc HTTP/1.1.

Quản trị mạng khó khăn

QUIC không chỉ mã hóa dữ liệu mà còn mã hóa cả header, do đó việc quản trị mạng sẽ trở nên khó khăn hơn rất nhiều. Việc tìm lỗi trong kết nối, thiết lập cấu hình mạng, tối ưu hóa băng thông sẽ không đơn giản.

Cũng vì mã hóa dữ liệu ở mức độ cao, tường lửa và các ứng dụng theo dõi mạng sẽ khó hoạt động hơn. Vì việc hỗ trợ QUIC đòi hỏi nhiều công sức, rất nhiều tường lửa đã bỏ qua giao thức này. Điều này có thể khiến việc bảo vệ mạng khó khăn và kém hiệu quả hơn.

UDP thường bị chặn

UDP được cho là thường bị lợi dụng để tấn công DoS. Do đó, nhiều mạng máy tính được thiết lập để chặn các kết nối UDP. Không thể kết nối bằng UDP thì không thể sử dụng HTTP/3.

Đã có thể sử dụng HTTP/3 chưa?

Hiện tại, dù đặc tả kỹ thuật của giao thức vẫn còn tiếp tục được phát triển (nhưng sẽ không có thay đổi lớn), HTTP/3 đã sẵn sàng.

Các web application như nginx, Apache, v.v… đều đã hỗ trợ HTTP/3. Giao thức cũng được cài đặt trên hầu hết các trình duyệt. Firefox, Chrome, Edge và các trình duyệt nhân Chromium khác đều đã hỗ trợ HTTP/3. Safari cũng đã cài đặt giao thức này nhưng vẫn đang ở tính năng thử nghiệm.

Việc triển khai HTTP/3 sẽ diễn ra từ từ, nhiều website đã triển khai HTTP/3. Người dùng sẽ dần dần được sử dụng HTTP/3 với những lợi thế về tốc độ.

Tôi xin lỗi nếu bài viết có bất kỳ typo nào. Nếu bạn nhận thấy điều gì bất thường, xin hãy cho tôi biết.

Nếu có bất điều gì muốn nói, bạn có thể liên hệ với tôi qua các mạng xã hội, tạo discussion hoặc report issue trên Github.