Điều gì xảy ra khi bạn duyệt web?
Internet đã trở thành một phần không thể thiếu trong cuộc sống hàng ngày. Mua sắm, ngân hàng, giao tiếp và giải trí đều phụ thuộc vào internet, và với sự phát triển của Internet vạn vật (IoT), ngày càng có nhiều thiết bị được kết nối trực tuyến, nơi chúng có thể được truy cập từ xa. Truy cập này được thực hiện nhờ một số công nghệ, bao gồm Giao thức Truyền Siêu văn bản (HTTP), đây là một phương pháp chính để yêu cầu truy cập vào các ứng dụng và tài nguyên web từ xa.
Mục đích sử dụng chính và đầu tiên của HTTP: để yêu cầu các trang web. Khi bạn mở một trang web trong trình duyệt của mình, dù trình duyệt đó trên pc/laptop, tablet, điện thoại di động hoặc bất kỳ thiết bị nào khác cho phép truy cập internet (tủ lạnh, tivi, …), rất nhiều thứ đang diễn ra.
Giả sử bạn khởi động trình duyệt và truy cập www.google.com. Trong vòng vài giây, những điều sau sẽ xảy ra
![[HTTP/2] Phần 1: Tìm hiểu hành trình đi lên HTTP/2 10 image - quochung.cyou PTIT](https://quochung.cyou/wp-content/uploads/2025/08/image.png)
Bước 1: DNS, IPv4, IPv5, IPv6, IPv1-3
Khi bạn gõ www.google.com vào trình duyệt, nó không tự biết Google ở đâu. Trình duyệt sẽ nhờ đến một “cuốn danh bạ” đặc biệt gọi là DNS (Domain Name System). Công việc của DNS rất đơn giản: biến cái tên thân thiện với con người (www.google.com) thành một dãy số mà máy tính hiểu được, gọi là địa chỉ IP.
- Tên miền giống như tên người trong danh bạ: “Google”.
- Địa chỉ IP giống như số điện thoại: máy tính chỉ biết gọi bằng số, chứ không hiểu tên.
Hiện nay có hai “kiểu số điện thoại” chính:
- IPv4: dạng cũ, ví dụ
216.58.192.4. Nhìn khá ngắn gọn, con người còn đọc được. - IPv6: dạng mới, ví dụ
2607:f8b0:4005:801:0:0:0:2004. Dài ngoằng, chỉ máy tính mới “thích” đọc. IPv6 sinh ra vì IPv4 gần như đã “hết số”, giống như khi một thành phố phải thêm mã vùng điện thoại mới vì dân cư quá đông.
Một fact: vì internet là toàn cầu, Google (và các công ty lớn khác) đặt máy chủ khắp nơi trên thế giới. DNS sẽ thông minh chọn cho bạn địa chỉ IP của máy chủ gần nhất, để tốc độ truy cập nhanh hơn. Thế nên một người ở Mỹ và một người ở châu Âu có thể nhận được IP hoàn toàn khác nhau khi cùng gõ www.google.com.
Điều gì đã xảy ra với IPv5?
Mỗi thiết bị kết nối Internet đều cần một địa chỉ IP duy nhất, giống như mỗi ngôi nhà cần một số nhà riêng.
- Với IPv4, ta có khoảng 4,3 tỷ “số nhà” (2³² địa chỉ). Khi Internet mới ra đời, con số đó nghe như vô tận.
- Nhưng rồi máy tính cá nhân, điện thoại thông minh, camera an ninh, đồng hồ thông minh, tủ lạnh IoT… tất cả đều cần một địa chỉ. Điều này khiến kho địa chỉ IPv4 gần như cạn kiệt.
Buộc phải mở ra một hệ thống đánh số mới rộng hơn. IPv6 chính là “hệ thống số nhà mở rộng” đó, với 128 bit, đủ để cấp địa chỉ cho hầu như mọi hạt cát trên trái đất. (2^128)
Bạn có thể thấy hơi lạ: chúng ta có IPv4, rồi nhảy thẳng sang IPv6. Thế IPv5 biến đi đâu? Và tại sao chẳng ai nhắc tới IPv1–IPv3?
Thực ra mọi gói tin Internet đều có một trường nhỏ ở đầu (4 bit) để ghi phiên bản. Về lý thuyết, chỉ có tối đa 15 phiên bản (0–15). (Có thể thấy ở ảnh dưới, phần Version đầu tiên)
![[HTTP/2] Phần 1: Tìm hiểu hành trình đi lên HTTP/2 11 image 1 - quochung.cyou PTIT](https://quochung.cyou/wp-content/uploads/2025/08/image-1.png)
- IPv6: giải quyết triệt để vấn đề “hết số nhà” trên Internet, đồng thời bổ sung nhiều tính năng mới. Đây mới là “người kế nhiệm” thực sự.
- IPv0–IPv3: chỉ là các phiên bản thử nghiệm ban đầu. Không cái nào trở thành chuẩn chính thức.
- IPv4: phiên bản đầu tiên thực sự phổ biến, đưa Internet bùng nổ như chúng ta thấy ngày nay.
- IPv5: từng tồn tại dưới cái tên Internet Stream Protocol. Nó được thiết kế cho âm thanh và video theo thời gian thực (kiểu như những gì sau này VoIP làm). Nhưng nó sớm bị bỏ xó, vì vẫn mắc đúng nhược điểm của IPv4: không đủ không gian địa chỉ.
Vậy nên, IPv5 không “mất tích” mà chỉ dừng lại ở mức thử nghiệm. Thế giới chọn đi thẳng từ IPv4 sang IPv6 để giải quyết triệt để vấn đề cạn kiệt địa chỉ.
Bước 2: Tạo kết nối TCP/IP
Sau khi có địa chỉ IP, trình duyệt sẽ tìm cách kết nối đến máy chủ web. Kết nối này thường chạy qua:
- Cổng 80 cho HTTP (truyền thống).
- Cổng 443 cho HTTPS (phiên bản an toàn, có mã hóa).
Ngày nay hầu hết các trang web (kể cả Google) đều bắt buộc HTTPS nhờ công nghệ HSTS. Nghĩa là, ngay cả khi bạn gõ http://..., trình duyệt cũng sẽ tự động nâng cấp sang HTTPS.
TCP và IP phối hợp thế nào?
- IP giống như địa chỉ nhà, đảm bảo gói tin tìm đúng nơi đến.
- TCP giống như dịch vụ giao hàng uy tín: luôn hỏi “Bạn có nhận đủ chưa?”, nếu thiếu thì gửi lại.
Khi kết hợp, ta có TCP/IP, hai thứ làm nên xương sống Internet.
Một địa chỉ IP, nhiều dịch vụ
Một máy chủ có thể phục vụ nhiều “dịch vụ” khác nhau (web, email, FTP…). Để phân biệt, nó dùng cổng/port , giống như từ 1 địa chỉ nhà, chúng ta có thể chỉ tới số phòng, tầng, …
- HTTP → cổng 80
- HTTPS → cổng 443
HTTP
Khi kết nối TCP/IP đã ổn định, trình duyệt mới bắt đầu dùng HTTP để gửi yêu cầu: “Hãy cho tôi trang chủ Google”. Lúc này mới đến phần giao tiếp cấp ứng dụng mà ta thường nghe đến nhiều nhất.
Bước 3-10: Yêu cầu máy chủ phản hồi và trình duyệt bắt đầu “vẽ” trang
Sau khi trình duyệt gửi yêu cầu, máy chủ Google phản hồi. Nội dung phản hồi thường là HTML – ngôn ngữ mô tả cấu trúc của trang web.
HTML giống như bộ khung của một ngôi nhà: nó chia trang thành các phần (thẻ <div>, <p>, <h1>…), và kèm theo đường dẫn tới những vật liệu khác để hoàn thiện ngôi nhà:
- CSS (màu sắc, kiểu dáng)
- JavaScript (hành vi, tương tác)
- Hình ảnh, font chữ, video…
Mã phản hồi và chuyển hướng
Không phải lúc nào máy chủ cũng trả về ngay một trang HTML:
- Nếu bạn truy cập
http://www.google.com, máy chủ sẽ gửi lại mã 301/302 để chuyển hướng bạn sanghttps://www.google.com. - Nếu bạn gõ nhầm, như
www.google.com/nonexistent, bạn sẽ gặp mã 404 Not Found – giống như hỏi thủ thư một cuốn sách không có trong thư viện.
Trình duyệt dựng DOM
Khi nhận được HTML, trình duyệt sẽ phân tích và xây dựng DOM (Document Object Model) – bản đồ nội bộ của trang. Trong quá trình đọc HTML, nó phát hiện thêm tài nguyên cần tải (CSS, JS, hình ảnh…).
- Google khá “nhẹ nhàng”: chỉ khoảng 16 tài nguyên bổ sung.
- Trang trung bình: khoảng 75 tài nguyên (theo HTTP Archive).
- Facebook? Có thể lên tới hàng trăm tài nguyên – mỗi ảnh, script, quảng cáo đều phải gọi thêm.
Mỗi tài nguyên lại đi qua vòng lặp yêu cầu–phản hồi như ban đầu, khiến duyệt web chậm dần. Đây cũng là lý do HTTP/2 ra đời: gom nhiều yêu cầu để tải nhanh hơn.
Khi nào thì “bắt đầu vẽ”
Trình duyệt không đợi tải hết tất cả mới hiển thị, mà sẽ render dần dần:
- Nếu chờ đủ, web sẽ chậm chạp, người dùng nản.
- Nếu render sớm quá, trang “nhảy loạn” khi CSS/ảnh/JS tải thêm – gây khó chịu.
Hãy tưởng tượng bạn xem họa sĩ vẽ tranh: ban đầu chỉ có khung, sau đó thêm màu, rồi chi tiết. Nếu vẽ dở dang mà đưa cho bạn xem, bức tranh cứ đổi hình dáng liên tục – đó chính là cảm giác khi trang web “nhảy”.
Tải nền
Ngay cả sau khi trang “trông như đã xong”, trình duyệt vẫn âm thầm tải thêm:
- Ảnh, script theo dõi, quảng cáo…
- Tính năng động: ví dụ Google gợi ý kết quả tìm kiếm ngay khi bạn gõ, hay Facebook tự động hiện bài mới.
Những thứ này chạy ngầm trong nền (AJAX, fetch API, WebSocket…), khiến web ngày nay giống ứng dụng thật sự chứ không chỉ là trang tĩnh.
HTTP là gì
Vào thập niên 1930, kỹ sư điện Vannevar Bush (MIT) đã lo ngại rằng khối lượng thông tin con người tạo ra vượt xa khả năng tiêu thụ. Trong bài tiểu luận As We May Think (1945), ông hình dung ra một thiết bị gọi là memex – nơi mọi tri thức được lưu trữ, có thể tra cứu nhanh chóng và liên kết với nhau giống như cách bộ não kết nối ý tưởng. Memex không bao giờ thành hiện thực, nhưng khái niệm “kết nối thông tin có ngữ cảnh” đã gieo mầm cho thế hệ sau.
![[HTTP/2] Phần 1: Tìm hiểu hành trình đi lên HTTP/2 12 image 3 - quochung.cyou PTIT](https://quochung.cyou/wp-content/uploads/2025/08/image-3.png)
Đến những năm 1960, Ted Nelson đưa ra thuật ngữ hypertext – tập hợp văn bản/hình ảnh liên kết phức tạp mà giấy in không thể thể hiện. Nelson mơ về một “docuverse”, nơi thông tin được liên kết, không bao giờ bị xóa, và mọi người đều có thể truy cập. Dù dự án Xanadu của ông không thành công, nhưng nó đã tạo cảm hứng mạnh mẽ.
![[HTTP/2] Phần 1: Tìm hiểu hành trình đi lên HTTP/2 13 image 2 - quochung.cyou PTIT](https://quochung.cyou/wp-content/uploads/2025/08/image-2.png)
Năm 1989, tại CERN, Tim Berners-Lee muốn một cách để quản lý thông tin từ các thí nghiệm khổng lồ. Ông kết hợp ý tưởng hypertext (liên kết tự do) và hypermedia (không giới hạn ở chữ viết) để đề xuất một hệ thống “phổ quát” , chính là nền móng của World Wide Web. Và từ đây, HTTP (Hypertext Transfer Protocol) ra đời.
HTTP (Hypertext Transfer Protocol) đúng như tên gọi, ban đầu được tạo ra chỉ để chuyển các tài liệu “siêu văn bản” – tức là những trang có thể chứa liên kết sang trang khác. Nhưng chẳng bao lâu, người ta nhận ra rằng nó cũng có thể dùng để gửi những thứ khác như hình ảnh, âm thanh, video…
Vì vậy, chữ Hypertext trong tên ngày nay không còn quá chính xác, nhưng cái tên HTTP đã ăn sâu nên không ai đổi nữa.
Điều quan trọng là HTTP hoạt động dựa trên kết nối mạng ổn định (thường qua TCP/IP). Nó không quan tâm đến cách bạn nối dây mạng, Wi-Fi hay Ethernet thế nào, tất cả việc đó do các tầng giao thức bên dưới lo. HTTP chỉ tập trung làm một việc: nhận yêu cầu từ trình duyệt và trả về phản hồi từ máy chủ.
Điểm mạnh của HTTP chính là sự đơn giản. Trình duyệt gửi yêu cầu, máy chủ trả lời – thế thôi. Chính sự giản đơn này giúp web phát triển thần tốc, dù sau này phải đánh đổi một chút để tối ưu hiệu năng (như trong HTTP/2, HTTP/3).
![[HTTP/2] Phần 1: Tìm hiểu hành trình đi lên HTTP/2 14 image 4 - quochung.cyou PTIT](https://quochung.cyou/wp-content/uploads/2025/08/image-4.png)
Cú pháp HTTP cơ bản
Một yêu cầu HTTP, ở mức đơn giản nhất, chỉ là một dòng văn bản. Ví dụ:
GET /page.html↵
Ở đây:
- GET là phương thức (cách bạn “xin” dữ liệu).
- /page.html là tài nguyên bạn muốn.
- Dấu xuống dòng (
↵) cho biết bạn đã gõ xong.
Thế là đủ. Khi đó, trình duyệt đã có kết nối TCP/IP với máy chủ rồi, nên nó chỉ cần nói: “Ê, cho tôi file này với!”
HTTP 0.9
Phiên bản đầu tiên, HTTP/0.9 (1991), chỉ biết làm đúng điều này: gửi GET, nhận file HTML, rồi đóng kết nối. Nhìn lại, bạn có thể thấy lạ: “Sao phải viết GET nữa? Chẳng phải mặc định nó chỉ có một lệnh duy nhất đó sao?” Nhưng chính nhờ tầm nhìn xa, sau này các nhà thiết kế bổ sung thêm nhiều phương thức khác (POST, HEAD…), nên cú pháp ban đầu vẫn giữ được tính mở rộng, chạy được với cả các phiên bản http cũ.
HTTP 1.0
HTTP/0.9 chỉ biết GET một file HTML rồi thôi, nhưng đến HTTP/1.0 (1996), web đã có thêm cơ bắp.
Ba phương thức mới quen mặt
- GET (nâng cấp): Giờ đây không chỉ tải trang HTML, mà còn có thể yêu cầu ảnh, nhạc, video… Ngoài ra, GET còn “thông minh” hơn: có thể hỏi “file này có thay đổi từ lần cuối tôi tải không?” Nếu không, máy chủ chỉ trả lời “yên tâm, bản cũ còn dùng được” (giúp tiết kiệm băng thông).
- HEAD: Giống như soi bìa sách thay vì đọc cả cuốn. Client chỉ lấy metadata (header HTTP) để kiểm tra thông tin: file còn tồn tại không, có đổi mới không…
- POST: Đây là bước đột phá. Client có thể gửi dữ liệu lên server, ví dụ form đăng nhập hay đơn hàng mua sắm. Khác với GET, giao thức POST mang dữ liệu trong body request, kín đáo hơn (dù vẫn phải gửi qua HTTPS mới thật sự an toàn).
Header: lời nhắn gửi kèm yêu cầu
HTTP/1.0 bổ sung header – những dòng thông tin thêm để client “dặn dò” server. Ví dụ:
GET /page.html HTTP/1.0
Accept: text/html,application/xhtml+xml
Accept-Encoding: gzip, deflate
User-Agent: MyAwesomeWebBrowser 1.1
Đọc ngắn gọn thì header nói:
- Tôi muốn nội dung HTML.
- Tôi có thể nhận file nén (gzip, deflate).
- Tôi đang dùng trình duyệt tên “MyAwesomeWebBrowser 1.1”
Đây chính là cơ chế giúp web mở rộng: chỉ cần thêm header mới là có thể dạy client/server hiểu thêm “ngôn ngữ” mà không phá vỡ giao thức.
Mã phản hồi: server biết cách trả lời
HTTP/0.9 không có khái niệm mã phản hồi. Nếu lỗi thì server chỉ nhét thông báo vào HTML. Sang HTTP/1.0, lần đầu tiên xuất hiện status code, ba chữ số huyền thoại:
Các mã 2xx, 3xx, 4xx, 5xx chia thành từng nhóm rõ ràng, biến HTTP thành một cuộc hội thoại có quy tắc: client hỏi, server đáp, không phải đoán mò nữa.
2xx – Thành công
- 200 OK: Mọi thứ ngon lành, dữ liệu đây.
- 201 Created: POST thành công, đã tạo tài nguyên mới.
- 202 Accepted: Server nhận rồi, đang xử lý, bạn đợi chút.
- 204 No Content: Yêu cầu thành công nhưng không có gì để gửi lại (ví dụ: xóa một record).
3xx – Chuyển hướng
- 300 Multiple Choices: Có nhiều đường, bạn chọn.
- 301 Moved Permanently: Tài nguyên đã dọn nhà vĩnh viễn (Location header chỉ đường).
- 302 Moved Temporarily: Tạm thời dọn nhà.
- 304 Not Modified: File chưa đổi từ lần cuối, cứ dùng bản cũ.
4xx – Lỗi từ phía client
- 400 Bad Request: Server không hiểu bạn nói gì, sửa cú pháp đi.
- 401 Unauthorized: Bạn chưa đăng nhập.
- 403 Forbidden: Đăng nhập rồi nhưng không có quyền.
- 404 Not Found: Nổi tiếng nhất – giống như bấm số điện thoại sai: “Thuê bao không tồn tại.”
5xx – Lỗi từ phía server
- 500 Internal Server Error: Lỗi chung chỉ về việc server lỗi
- 501 Not Implemented: Server không biết xử lý yêu cầu này.
- 502 Bad Gateway: Proxy/gateway hỏi downstream server nhưng nhận lỗi.
- 503 Service Unavailable: Server quá tải hoặc đang bảo trì, quay lại sau.
HTTP 1.1
Vì thế, HTTP/1.1 ra đời năm 1997, chỉ 9 tháng sau khi HTTP/1.0 được chuẩn hóa. Nó không thay đổi tận gốc như từ 0.9 → 1.0, nhưng đã tinh chỉnh, bổ sung và quan trọng nhất: đặt ra tiêu chuẩn chính thức cho toàn bộ thế giới web, vốn đang bùng nổ mạnh mẽ.
Đến nay, HTTP/1.1 đã trải qua nhiều lần sửa đổi:
- RFC 2068 (1997) – bản đầu tiên
- RFC 2616 (1999) – cập nhật và thay thế
- RFCs 7230–7235 (2014) – chỉnh sửa, chi tiết hóa hơn (305 trang, gần 100.000 từ!)
Điều này cho thấy: giao thức tưởng chừng “đơn giản” lại phức tạp đến mức cần một bộ luật khổng lồ để mọi trình duyệt, máy chủ, proxy trên thế giới cùng “nói chung một ngôn ngữ”.
Những thay đổi quan trọng trong HTTP/1.1
1. Host header bắt buộc
Trong HTTP/1.0, client gửi request kiểu:
GET /index.html HTTP/1.0
Server hiểu là: à, nó đang xin file index.html từ chính website mà nó đang kết nối đến. Nhưng khi web phát triển, một server có thể chạy hàng trăm website khác nhau trên cùng một địa chỉ IP (virtual hosting). Làm sao server biết client muốn example.com/index.html hay blog.example.com/index.html?
Giải pháp: thêm Host header.
GET / HTTP/1.1
Host: www.google.com
Từ HTTP/1.1 trở đi, mọi request bắt buộc phải có Host. Nhờ đó:
- Một server duy nhất có thể phục vụ nhiều website.
- Tiết kiệm tài nguyên IP (IPv4 vốn khan hiếm).
Nếu không có bước này, có thể web sẽ “ngốn” sạch IPv4 từ rất sớm. Ngược lại, nếu hồi đó người ta không chọn giải pháp Host header, mà bắt client phải gửi URL đầy đủ (absolute-form), thì web có thể đã ép buộc sang IPv6 sớm hơn 20 năm.
2. Kết nối bền vững (Persistent connections / Keep-Alive)
HTTP ban đầu hoạt động theo kiểu: một request → một response → đóng kết nối.
Nhưng khi web nhiều hình ảnh, CSS, JS, việc liên tục đóng/mở kết nối TCP cực kỳ lãng phí. Mỗi lần bắt tay TCP tốn thêm vài trăm mili-giây, nhân lên hàng chục file thì người dùng sẽ “chờ dài cổ”.
HTTP/1.1 thay đổi mặc định:
- Mọi kết nối được giữ mở trừ khi server nói rõ “Connection: close”.
- Client có thể gửi tiếp nhiều request trên cùng một kết nối.
GET /style.css HTTP/1.1
Host: www.example.com
GET /script.js HTTP/1.1
Host: www.example.com
Trình duyệt có thể “nạp đơn hàng” liên tục thay vì phải xếp hàng lại từ đầu.
Tuy nhiên, điều này đòi hỏi phải có thêm cách xác định “đâu là hết dữ liệu” (vì không còn dấu hiệu đóng kết nối nữa). Do đó, HTTP/1.1 dùng 1 header Content-Length hoặc chunked transfer encoding để báo độ dài nội dung. Khi đó, các bên có thể từ content length và dữ liệu đã nhận được để biết bao giờ là kết thúc.
![[HTTP/2] Phần 1: Tìm hiểu hành trình đi lên HTTP/2 15 image 5 - quochung.cyou PTIT](https://quochung.cyou/wp-content/uploads/2025/08/image-5.png)
3. Pipelining (nhưng thất bại)
HTTP/1.1 còn đưa ra ý tưởng pipelining: client gửi nhiều request “một lèo” mà không chờ phản hồi, server trả kết quả theo thứ tự.
Ví dụ:
- Gửi cùng lúc request cho CSS, JS, ảnh.
- Server trả về lần lượt CSS → JS → ảnh.
Nghe thì hay, nhưng thực tế bị head-of-line blocking: nếu request đầu tiên bị chậm (ví dụ truy vấn DB lâu), thì mọi request sau bị kẹt. Thêm nữa, hỗ trợ pipelining ở proxy và server thường kém (thậm chí lỗi). Vì vậy, pipelining gần như “chết yểu”, không được các trình duyệt phổ biến bật mặc định.
4. Bộ nhớ đệm (Caching) thông minh hơn
Trong HTTP/1.0, chỉ có header Expires: <date>. Nghĩa là:
- Nếu quá ngày đó → tài nguyên hết hạn, phải tải lại từ server.
- Nó cứng nhắc, ví dụ bạn muốn cho cache tồn tại 30 phút tính từ lúc tải thì không làm được (vì
Expirescần một mốc thời gian cố định).
HTTP/1.1 thì mềm dẻo hơn nhờ Cache-Control:
max-age=600→ cache trong vòng 600 giây (10 phút).no-cache→ client vẫn lưu cache nhưng luôn xác thực lại với server trước khi dùng.must-revalidate→ nếu cache hết hạn thì bắt buộc hỏi server, không được tự ý dùng lại.public/private→ phân biệt cache dùng chung (CDN, proxy) hay chỉ cho trình duyệt người dùng.
Ví dụ thực tế:
- File CSS/JS ít thay đổi →
Cache-Control: max-age=604800(1 tuần). - API JSON (luôn muốn dữ liệu mới) →
Cache-Control: no-cache, must-revalidate. - Ảnh profile user (có thể đổi nhưng không thường xuyên) →
Cache-Control: max-age=86400, must-revalidate.
Điểm mạnh: giúp tăng tốc độ web, giảm tải server, nhưng vẫn linh hoạt để dữ liệu quan trọng luôn mới.
5. Nhiều method và tính năng mới
HTTP/1.1 bổ sung khá nhiều method để phù hợp với web ngày càng phức tạp:
- Method mới
PUT: ghi đè hoặc tạo tài nguyên ở URL cụ thể.DELETE: xóa tài nguyên.OPTIONS: hỏi server xem URL đó hỗ trợ những method nào (cần cho CORS).TRACE: gửi request để server trả lại toàn bộ nội dung nó nhận → debug.CONNECT: dùng cho tunneling (thường thấy khi HTTPS đi qua proxy).
- Proxy support
Cho phép request/response đi qua nhiều server trung gian (caching proxy, load balancer, CDN). - Authentication
Có sẵn cơ chế như Basic và Digest Authentication để bảo vệ tài nguyên. - Cookies
HTTP vốn stateless (mỗi request độc lập, không nhớ “ai với ai”).
Cookie giúp “nhớ” trạng thái (user đã login, giỏ hàng, session…). - Charset & Content-Language
Giúp server khai báo tài liệu dùng encoding gì (UTF-8, ISO-8859-1…) và ngôn ngữ (en, vi…). - Status code mới
Bổ sung thêm nhiều mã:409 Conflict,410 Gone,100 Continue… để mô tả chính xác hơn tình huống. - Trailing headers & mở rộng headers vô hạn
Cho phép thêm metadata bổ sung sau phần body (dùng trong chunked transfer).
HTTP/1.1 cũng gỡ bỏ giới hạn số lượng header → dễ mở rộng (các API hiện nay tận dụng điều này rất nhiều, nhưAuthorization,X-Request-ID,Content-Security-Policy).
Các vấn đề của HTTP/1.1
Sau khi HTTP/1.1 được chuẩn hóa, nó trở thành nền móng của web suốt 20 năm. Nhưng chính sự bùng nổ website đã làm lộ rõ giới hạn của giao thức này.
![[HTTP/2] Phần 1: Tìm hiểu hành trình đi lên HTTP/2 16 image 8 - quochung.cyou PTIT](https://quochung.cyou/wp-content/uploads/2025/08/image-8.png)
Theo thống kê từ HTTP Archive:
- Năm 2010, trang web trung bình ~ 700 KB, khoảng 50 request.
- Đến 2018, tăng lên gần 1.8 MB, hơn 80–90 request.
- Một số website lớn:
- Wikipedia: chỉ 7 request, 0.06 MB (rất tối ưu).
- Facebook: 172 request, 2.2 MB.
- Amazon: 136 request, 4.46 MB.
- Yahoo: 240 request, 3.8 MB.
Nguyên nhân: website ngày càng giàu media (ảnh, video), nhiều framework và script, và dùng AJAX để cập nhật động liên tục.
Các vấn đề performance của HTTP/1.1 và cách giải quyết tạm thời vào thời điểm này
Hãy tưởng tượng bạn mở một trang web rất đơn giản: chỉ có một ít văn bản và hai tấm hình.
- Mỗi yêu cầu (request) từ trình duyệt đến server tốn 50ms để di chuyển qua mạng internet.
- Máy chủ lấy dữ liệu từ file server, xử lý trong 10ms rồi trả về.
- Trình duyệt khi nhận được ảnh, xử lý thêm 10ms trước khi gửi tiếp yêu cầu mới.
![[HTTP/2] Phần 1: Tìm hiểu hành trình đi lên HTTP/2 17 image 7 - quochung.cyou PTIT](https://quochung.cyou/wp-content/uploads/2025/08/image-7.png)
Tổng cộng, để hiển thị xong trang này cần 360ms. Trong đó chỉ 60ms là thời gian xử lý thực sự ở máy khách và máy chủ; còn lại 300ms (hơn 80%) chỉ để… chờ dữ liệu qua lại trên đường truyền. Trong lúc chờ, cả server lẫn trình duyệt đều “ngồi chơi xơi nước”
Điều bất hợp lý lộ rõ ở mốc 120ms: trình duyệt vừa gửi yêu cầu lấy ảnh số 1 và biết chắc là sẽ cần ảnh số 2, nhưng không thể gửi ngay. Nó buộc phải chờ ảnh 1 trả về xong, kết nối mới “rảnh” để gửi tiếp yêu cầu ảnh 2 vào lúc 240ms. Cách vận hành này làm mọi thứ chậm hẳn đi.
Trình duyệt hiện đại thường mở 6 kết nối / domain. Nếu website có nhiều file, chúng được tải trên 6 “đường ống” cùng lúc.
Dùng nhiều kết nối HTTP
Để tăng hơn nữa, nhiều trang web dùng domain sharding: chia file ra các subdomain như static.example.com, cdn.example.com… Như vậy mỗi domain được thêm 6 kết nối, tăng khả năng song song.
Ví dụ: StackOverflow tải:
- jQuery từ Google,
- Script/CSS từ
cdn.static.net, - Ảnh từ
i.stack.imgur.com.
![[HTTP/2] Phần 1: Tìm hiểu hành trình đi lên HTTP/2 18 image 9 - quochung.cyou PTIT](https://quochung.cyou/wp-content/uploads/2025/08/image-9.png)
Nhưng: giải pháp này lại tạo ra gánh nặng:
- TCP handshake: mỗi kết nối mới cần 3 bước SYN → SYN-ACK → ACK (tốn 1.5 round-trip).
- TCP slow start: kết nối mới ban đầu chỉ gửi ít gói, tăng dần khi chứng minh mạng chịu tải. Nghĩa là request/response đầu tiên thường bị “thắt cổ chai”.
- HTTPS handshake: thêm vài vòng trao đổi nữa để thiết lập mã hóa.
![[HTTP/2] Phần 1: Tìm hiểu hành trình đi lên HTTP/2 19 image 10 - quochung.cyou PTIT](https://quochung.cyou/wp-content/uploads/2025/08/image-10.png)
Mozilla từng thống kê: 74% kết nối HTTP/1 chỉ dùng cho 1 transaction duy nhất → tức nhiều kết nối mở ra xong gần như bỏ phí.
Kết luận: mở nhiều kết nối giúp đỡ phần nào, nhưng chỉ là giải pháp tình thế. Nó tự tạo thêm chi phí (handshake, slow start, bộ nhớ) trong khi bản chất vấn đề vẫn là độ trễ.
Giảm số lượng request
Cách khác: thay vì tăng kết nối, hãy giảm số lần gọi.
- Cache: dùng HTTP header
Cache-Control,Expiresđể client lưu lại file, không tải lại nữa. - Sprite images: gộp nhiều icon nhỏ thành một ảnh lớn rồi dùng CSS để “cắt” ra (TinyPNG hay dùng cách này).
![[HTTP/2] Phần 1: Tìm hiểu hành trình đi lên HTTP/2 20 image 11 - quochung.cyou PTIT](https://quochung.cyou/wp-content/uploads/2025/08/image-11.png)
- Concatenate & Minify: gộp nhiều file CSS/JS → một file duy nhất, đồng thời xóa khoảng trắng, comment.
- Inline: chèn CSS/JS/ảnh trực tiếp vào HTML (dùng
<style>,<svg>, hoặc base64).
Nhược điểm:
- Phức tạp: tạo sprite, gộp file cần phải triển khai từ trước.
- Lãng phí: tải cả sprite 100 icon trong khi chỉ cần 2.
- Cache khó quản lý: một thay đổi nhỏ buộc user tải lại cả file lớn (dù chỉ đổi một dòng CSS).
SPDY
Nguồn gốc: năm 2009, Google (Mike Belshe & Robert Peon) giới thiệu SPDY (đọc là “speedy”). Họ chạy thử nghiệm trên bản sao của 25 trang web lớn nhất và thấy cải thiện tốc độ tải trang rất rõ rệt, tới mức hai chữ số phần trăm trong nhiều trường hợp.
Ý tưởng chính của SPDY: không thay đổi “nghĩa” của HTTP (vẫn có GET/POST/headers/body), nhưng thay đổi cách đóng gói và gửi các yêu cầu/response sao cho nhanh hơn và hiệu quả hơn với mạng hiện có. SPDY làm 4 việc quan trọng:
- Multiplexing (đa luồng trên một kết nối):
- Trước HTTP/1.1: trình duyệt mở nhiều kết nối TCP (mỗi tên miền thường ~6 kết nối đồng thời). Mỗi kết nối chỉ xử lý lần lượt một yêu cầu → xuất hiện “waterfall” (đọan thác): các nhóm tài nguyên phải chờ lượt.
- SPDY: mọi request/response được chia thành các streams nhỏ, gửi xen kẽ qua một kết nối TCP duy nhất. Kết quả: tài nguyên có thể được gửi song song mà không cần mở thêm TCP connection.
- Request prioritization (ưu tiên yêu cầu):
- Không phải mọi tài nguyên đều quan trọng như nhau. SPDY cho phép trình duyệt nói với server tài nguyên nào quan trọng hơn (ví dụ: CSS quan trọng hơn ảnh nền). Server có thể ưu tiên gửi trước các stream quan trọng.
- Header compression:
- HTTP/1.1 gửi header dạng text cho từng yêu cầu, với nhiều request, header trùng lặp (cookie, user-agent, accept,…) gây lãng phí. SPDY nén header để giảm kích thước và số byte truyền.
- Nếu mỗi request gửi một header
Cookie: SESS=...dài 200 B, 360 request = 72 KB chỉ cho cookie. Header compression giảm con số này mạnh mẽ.
- Server push (đẩy từ server):
- Server có thể “đẩy” các tài nguyên mà nó dự đoán client sẽ cần (ví dụ: CSS, JS) ngay khi client yêu cầu HTML, tránh vòng lặp client → server hỏi “tôi cần CSS không?” → server mới trả.
Vì các tính năng như multiplexing và framing yêu cầu cấu trúc nhỏ gọn, chính xác và dễ phân mảnh, điều khó/không thể làm tốt khi gửi toàn bộ theo dạng text line-based (như HTTP/1.x). Binary framing cho phép định nghĩa các frame nhỏ (HEADERS, DATA, SETTINGS, WINDOW_UPDATE, v.v.) để truyền và ghép lại chính xác.
Kết quả thực tế: triển khai SPDY ở Chrome và trên các dịch vụ Google cho thấy tốc độ tải trang cải thiện rõ rệt; nhiều browser/server khác cũng nhanh chóng bổ sung hỗ trợ. Tuy nhiên SPDY chỉ là bước trung gian: nó chứng minh các ý tưởng thực tế và trở thành nền tảng để chuẩn hóa HTTP/2.
![[HTTP/2] Phần 1: Tìm hiểu hành trình đi lên HTTP/2 21 image 6 - quochung.cyou PTIT](https://quochung.cyou/wp-content/uploads/2025/08/image-6.png)
Ảnh: Sau khi HTTP/2 ra đời, SPDY bắt đầu giảm xuống
HTTP/2
SPDY chứng minh rằng các cải tiến có thể làm được, IETF (HTTP Working Group) dựa trên SPDY khi soạn HTTP/2 (bản draft đầu vào cuối 2012). HTTP/2 giữ hầu hết ý tưởng tốt của SPDY nhưng chuẩn hoá chúng, bổ sung một số cải tiến (ví dụ HPACK cho header compression) và xử lý các chi tiết tương thích/ bảo mật.
Tại sao dùng HTTP/2 thay vì HTTP/1.2?
HTTP/2 được tạo ra để giải quyết các vấn đề hiệu suất của HTTP/1, và phiên bản mới này thêm vào các khái niệm sau:
- Giao thức nhị phân thay vì văn bản.
- Ghép kênh (multiplexed) thay vì đồng bộ (synchronous).
- Kiểm soát dòng chảy (flow control).
- Ưu tiên luồng (stream prioritization).
- Nén tiêu đề (header compression).
- Đẩy từ máy chủ (server push).
Những khái niệm này (sẽ được mô tả chi tiết hơn trong chương) là những thay đổi cơ bản, phá vỡ tính tương thích ngược; nghĩa là, máy chủ web HTTP/1.0 có thể hiểu tin nhắn HTTP/1.1 và bỏ qua các chức năng thừa, nhưng điều này không đúng với tin nhắn HTTP/2, vì chúng có cấu trúc và định dạng khác. Vì lý do đó, HTTP/2 được coi là bản nâng cấp lớn..
Nhị phân thay vì văn bản
Một khác biệt chính giữa HTTP/1 và HTTP/2 là HTTP/2 là giao thức nhị phân dựa gói, trong khi HTTP/1 hoàn toàn dựa văn bản. Giao thức dựa văn bản dễ hiểu cho con người nhưng khó phân tích cho máy tính. Điều này chấp nhận được cho giao thức yêu cầu-phản hồi đơn giản mà HTTP bắt đầu, nhưng ngày càng hạn chế cho internet hiện đại.
Với giao thức văn bản, yêu cầu phải gửi và phản hồi nhận đầy đủ trước khi xử lý yêu cầu khác. HTTP hoạt động thế này 20 năm qua, dù có cải tiến nhỏ. HTTP/1.0 giới thiệu thân HTTP nhị phân, ví dụ, nơi hình ảnh và media khác có thể gửi trong phản hồi, và HTTP/1.1 giới thiệu pipelining và mã hóa chunked. Mã hóa chunked cho phép gửi phần thân tin nhắn trước, phần còn lại theo sau khi sẵn sàng. Thân HTTP chia thành chunk, và client nhận chunked response (hoặc server nhận chunked request) có thể bắt đầu xử lý trước khi nhận đầy đủ. Kỹ thuật này thường dùng khi độ dài dữ liệu tạo động không biết trước. Cả chunked encoding và pipelining có vấn đề chặn đầu hàng (HOL blocking), nơi tin nhắn đầu hàng ngăn phản hồi sau gửi, chưa kể pipelining không được hỗ trợ tốt trong thế giới thực.
HTTP/1.1
- Định dạng: toàn bộ request/response là văn bản (ASCII/UTF-8).
- Request line:
GET /index.html HTTP/1.1 - Headers:
Host: example.com\r\n... - Body: theo sau, độ dài được báo bằng
Content-Lengthhoặc chunked encoding.
- Request line:
- Kết quả:
- Parser phải đọc dấu hiệu kết thúc dòng (
\r\n) để tách header. - Nếu header/body to, trình duyệt phải chờ nhiều (buffering).
- Chỉ một request/response được xử lý trên một TCP connection tại một thời điểm → dễ nghẽn (head-of-line blocking).
- Không có khái niệm “frame type”, tất cả đều là text nối tiếp nhau.
- Parser phải đọc dấu hiệu kết thúc dòng (
HTTP/2 – mọi thứ là frame
- Cấu trúc rõ ràng, nhị phân: mỗi frame có header 9 byte cố định + payload.
- Length (3 byte): kích thước payload.
- Type (1 byte): phân loại (DATA, HEADERS, SETTINGS, PING, …).
- Flags (1 byte): đánh dấu (END_STREAM, END_HEADERS, …).
- Stream ID (4 byte, thực tế 31 bit): thuộc về stream nào.
- Payload: dữ liệu thực (body, header block, …).
- Ưu điểm:
- Parser biết ngay độ dài frame → không cần scan ký tự xuống dòng.
- Có thể ghép nhiều request/response song song trên một TCP connection (multiplexing, sẽ giải thích thêm ở dưới), nhờ phân biệt bằng stream ID.
- Cho phép mở rộng: frame mới có thể được định nghĩa thêm mà không phá chuẩn.
- Có nhiều loại frame khác nhau cho mục đích cụ thể:
HEADERS,DATA,PRIORITY,WINDOW_UPDATE,PUSH_PROMISE… → kiểm soát chi tiết mà h1.1 không làm được.
![[HTTP/2] Phần 1: Tìm hiểu hành trình đi lên HTTP/2 22 image 16 - quochung.cyou PTIT](https://quochung.cyou/wp-content/uploads/2025/08/image-16.png)
Cấu trúc frame header (9 bytes đầu):
- Length (3 bytes): độ dài payload.
- Type (1 byte): loại frame (HEADERS, DATA, SETTINGS, …).
- Flags (1 byte): cờ tùy theo frame type.
- R (1 bit): reserved, không dùng.
- Stream Identifier (31 bits): xác định stream mà frame thuộc về.
- Payload: dữ liệu thực, độ dài như
Length.
Frame types (10 chuẩn + mở rộng):
DATA (0x0): payload chính.HEADERS (0x1): HTTP headers + priority.PRIORITY (0x2): thay đổi độ ưu tiên, dependency.RST_STREAM (0x3): kết thúc stream (thường khi lỗi).SETTINGS (0x4): config connection.PUSH_PROMISE (0x5): server thông báo sẽ push object.PING (0x6): test RTT.GOAWAY (0x7): đóng connection, không nhận stream mới.WINDOW_UPDATE (0x8): điều khiển flow (bytes còn có thể nhận).CONTINUATION (0x9): nối thêm headers khi HEADERS quá dài.- Extension frames: cho phép mở rộng mà không phá protocol.
![[HTTP/2] Phần 1: Tìm hiểu hành trình đi lên HTTP/2 23 image 17 - quochung.cyou PTIT](https://quochung.cyou/wp-content/uploads/2025/08/image-17.png)
t= 1646 [st= 1] HTTP2_SESSION_RECV_SETTINGS
t= 1647 [st= 2] HTTP2_SESSION_RECV_SETTING
--> id = "1 (SETTINGS_HEADER_TABLE_SIZE)"
--> value = 4096
t= 1647 [st= 2] HTTP2_SESSION_RECV_SETTING
--> id = "5 (SETTINGS_MAX_FRAME_SIZE)"
--> value = 16384
t= 1647 [st= 2] HTTP2_SESSION_RECV_SETTING
--> id = "6 (SETTINGS_MAX_HEADER_LIST_SIZE)"
--> value = 131072
t= 1647 [st= 2] HTTP2_SESSION_RECV_SETTING
--> id = "3 (SETTINGS_MAX_CONCURRENT_STREAMS)"
--> value = 100
t= 1647 [st= 2] HTTP2_SESSION_RECV_SETTING
--> id = "4 (SETTINGS_INITIAL_WINDOW_SIZE)"
--> value = 65536
Ghép kênh (multiplexing) trên một kết nối
Ý tưởng chính:
HTTP/2 biến mỗi yêu cầu thành một luồng (stream) riêng, và tất cả luồng đi chung một “đường ống TCP duy nhất”.
- Yêu cầu được cắt thành các khung (frame) nhỏ.
- Mỗi khung có ID luồng để biết nó thuộc yêu cầu nào.
- Server và client chỉ việc ghép các khung lại → tái tạo thành thông điệp HTTP hoàn chỉnh.
Lợi ích:
- Không bị nghẽn đầu hàng (head-of-line blocking ở mức HTTP): Nếu một yêu cầu chậm (ví dụ tải ảnh lớn), nó không làm tắc nghẽn các yêu cầu khác. Server có thể trả xen kẽ: một khung ảnh, rồi một khung CSS, rồi tiếp tục ảnh…
- Chỉ cần một kết nối TCP duy nhất cho mọi tài nguyên → giảm overhead handshake, giảm tiêu tốn tài nguyên.
- Server có thể quyết định ưu tiên: gửi CSS/JS quan trọng trước, hình ảnh phụ sau → tăng tốc độ hiển thị trang.
Ví dụ:
Cần tải 3 tài nguyên: styles.css, main.js, logo.png.
- Với HTTP/1.1 pipelining:
- Client gửi cả 3 yêu cầu nối tiếp.
- Server phải trả đúng thứ tự: CSS → JS → PNG. Nếu file CSS to hoặc bị trễ, hai file sau cũng kẹt lại.
![[HTTP/2] Phần 1: Tìm hiểu hành trình đi lên HTTP/2 24 image 12 - quochung.cyou PTIT](https://quochung.cyou/wp-content/uploads/2025/08/image-12.png)
- Với HTTP/2 multiplexing:
- Client gửi cả 3 yêu cầu trên cùng một kết nối.
- Server có thể trả: một phần CSS → một phần JS → một phần PNG → tiếp tục CSS…
- Trình duyệt nhận được khung CSS đầu tiên thì đã có thể render ngay, không cần chờ toàn bộ CSS tải xong.
![[HTTP/2] Phần 1: Tìm hiểu hành trình đi lên HTTP/2 25 image 13 - quochung.cyou PTIT](https://quochung.cyou/wp-content/uploads/2025/08/image-13.png)
- Bên trái (Client): trình duyệt gửi nhiều request (GET /styles.css, GET /script.js, GET /image.jpg…).
- Giữa (HTTP/2 layer): tất cả request/response đều đi qua một kết nối TCP duy nhất nhưng được đóng gói thành nhiều stream. Mỗi stream lại chia nhỏ thành nhiều frame.
- Bên phải (Server): server nhận request từ nhiều stream cùng lúc, xử lý rồi trả response xen kẽ trở lại trên cùng kết nối TCP.
Bước 1: Client gửi request
- Client tạo 3 request:
- Request 2 → GET /styles.css → Stream 5
- Request 3 → GET /script.js → Stream 7
- Request 4 → GET /image.jpg → Stream 9
Mỗi request sẽ được đánh số ID luồng (stream ID). Ở đây: 5, 7, 9 (client luôn tạo ID lẻ).
![[HTTP/2] Phần 1: Tìm hiểu hành trình đi lên HTTP/2 26 image 15 - quochung.cyou PTIT](https://quochung.cyou/wp-content/uploads/2025/08/image-15-1024x618.png)
Bước 2: HTTP/2 framing layer đóng gói
- Request không gửi nguyên khối, mà bị chia nhỏ thành frames:
- Frame chứa headers (ví dụ GET, URL, cookie, header HTTP).
- Frame chứa body (nếu có).
- Các frame từ nhiều stream có thể xếp nối tiếp nhau trên cùng kết nối TCP.
Ví dụ: thay vì phải gửi toàn bộ styles.css rồi mới đến script.js, rồi mới đến image.jpg, HTTP/2 sẽ gửi xen kẽ: một frame của Stream 5 (styles.css), sau đó một frame của Stream 7 (script.js), rồi một frame của Stream 9 (image.jpg)…
Bước 3: Server nhận và xử lý
- Server đọc các frame, ghép lại theo stream ID để tái tạo thành request đầy đủ.
- Sau đó server xử lý và tạo response.
Bước 4: Server trả response xen kẽ
- Response cũng được cắt thành frames, rồi trả về client.
- Các stream response không cần giữ đúng thứ tự yêu cầu ban đầu.
- Server có thể ưu tiên gửi nhanh CSS (quan trọng để render trang) trước khi trả ảnh JPG.
- Trong hình: Stream 5 và Stream 7 response đi xen kẽ nhau, trong khi Stream 9 (ảnh JPG) response nối tiếp.
Bạn có thể hình dung:
- HTTP/1.1 giống như có 6 cái ống nước riêng, mỗi ống chỉ chảy được một loại nước. Nếu một ống nghẹt thì nước loại đó tắc hết.
- HTTP/2 giống như một ống nước lớn duy nhất, trong đó dòng chảy có nhiều màu khác nhau (đỏ = ảnh, vàng = CSS, xanh = JS). Các giọt nước khác màu có thể luân phiên chạy trong cùng một ống, và khi đến đích thì được lọc ra đúng “xô” tương ứng.
![[HTTP/2] Phần 1: Tìm hiểu hành trình đi lên HTTP/2 27 image 14 - quochung.cyou PTIT](https://quochung.cyou/wp-content/uploads/2025/08/image-14.png)
Stream prioritization (Ưu tiên dòng)
HTTP/1.x:
- Trình duyệt phải “xếp hàng” tài nguyên vì giới hạn 6 kết nối/host.
- Muốn ưu tiên CSS/JS quan trọng thì chỉ đơn giản gửi sớm hơn. Nhưng nếu kết nối đã đầy, thì phải đợi → cơ chế ưu tiên thô sơ, bị giới hạn bởi số kết nối.
HTTP/2:
- Có thể gửi hàng trăm stream một lúc trên cùng một kết nối.
- Nếu không có ưu tiên, dễ lãng phí băng thông: ví dụ hình ảnh (không critical) lại chiếm chỗ trước CSS (critical).
- Cơ chế ưu tiên: Client gửi “hints” về độ ưu tiên (priority) → server chọn phân bổ tài nguyên.
- Ví dụ: nếu cả CSS và ảnh đang chờ, server sẽ gửi nhiều frame CSS hơn để trình duyệt render trang sớm.
- Ưu tiên mềm: không phải “gửi cái này trước, cái kia sau”, mà là chia băng thông nhiều–ít giữa các stream.
Flow control
Ta đã thấy ở Multiplexing nghĩa là nhiều stream chia sẻ cùng một TCP. Nhưng nếu client đọc chậm (ví dụ đang pause video), mà server vẫn dồn dữ liệu video về → nghẽn buffer, mất gói, phải retransmit → phí công.
TCP vốn đã có cơ chế window size để tránh sender “dội” dữ liệu quá nhiều so với khả năng nhận của receiver.
Nhưng: TCP coi cả kết nối như một dòng duy nhất. Nếu một luồng dữ liệu (ví dụ video) bị nghẽn, thì nó kéo theo tất cả dữ liệu khác trên cùng connection → “head-of-line blocking”.
- HTTP/2 chia nhỏ kết nối thành nhiều stream (mỗi request/response).
- Mỗi stream có cửa sổ riêng (window size), mặc định 65,535 byte.
- Cơ chế:
- Server chỉ được gửi tối đa số byte trong cửa sổ.
- Khi client xử lý xong một phần dữ liệu, nó báo lại bằng
WINDOW_UPDATEframe → tăng cửa sổ, cho phép server gửi tiếp.
- Kết quả: stream nào “chậm” (ví dụ video đang pause) thì chỉ bị tạm ngừng riêng, không ảnh hưởng các stream khác (CSS, JS vẫn chạy bình thường).
Giả sử stream #11 là video, stream #13 là CSS:
- Ban đầu: cả hai có window = 65,535.
- Server gửi:
- Video 10 KB → cửa sổ video còn 55,535.
- CSS 20 KB → cửa sổ CSS còn 45,535.
- Client pause video → không gửi
WINDOW_UPDATEcho stream #11 → video tạm “đóng băng”. - Nhưng client vẫn gửi
WINDOW_UPDATEcho stream #13 → CSS tiếp tục tải bình thường.
Lợi ích
- Tinh chỉnh: quản lý luồng nào cần, luồng nào tạm dừng.
- Hiệu quả: tránh lãng phí băng thông/memory vào dữ liệu không tiêu thụ.
- Khả năng phối hợp: đặc biệt quan trọng khi đi qua proxy/CDN với tốc độ khác nhau.
Header compression
Vấn đề trong HTTP/1:
- Mỗi request lặp lại hàng đống header giống nhau:
Cookie(to, nặng).User-Agent,Host,Accept,Accept-Encoding…
- Với hàng trăm request nhỏ, phần header đôi khi to hơn cả body!
- HTTP/1 chỉ nén body (gzip, deflate), không nén header.
Vấn đề: headers lớn, lặp nhiều (cookie, user-agent, accept, …). Một trang ~140 request, mỗi request ~460 bytes → ~63 KB headers, phần lớn lặp.
Cách làm:
- Giữ bảng tĩnh (61 header phổ biến, ví dụ
:method: GET). - Giữ bảng động (lưu các header đã thấy trong connection).
- Ví dụ:
:method: GETcó thể là entry số 2 trong bảng. Thay vì gửi"GET"cả chữ, client chỉ gửi số 2. - Tương tự,
host: example.comcó thể được lưu ở entry #62 → request sau chỉ cần gửi 62 thay vì nguyên chuỗi. - Với các header mới/chưa có trong bảng, vẫn phải gửi chuỗi.
- Nhưng để tiết kiệm, HTTP/2 dùng Huffman coding (biểu diễn ký tự bằng bit ngắn hơn cho ký tự thường gặp, dài hơn cho ký tự hiếm gặp).
- Nhờ đó, chuỗi literal cũng nhỏ gọn hơn nhiều so với ASCII/UTF-8 thẳng.
Ví dụ:
- Request 1: gửi
:authority: www.akamai.com, :method: GET, ...→ thêm vào bảng. - Request 2: gần giống, chỉ khác
:path→ chỉ cần gửi index + giá trị mới. - Tiết kiệm ~85% dung lượng.
Đẩy từ máy chủ
Cơ chế: server gửi PUSH_PROMISE frame gắn vào một stream hiện có.
Stream IDtrong PUSH_PROMISE = stream gốc (ví dụ:/index.html).- Headers trong PUSH_PROMISE mô phỏng như client sẽ request file đó.
- Sau đó server gửi DATA của object.
Mục tiêu: đặt tài nguyên vào cache trước khi client yêu cầu.
Rủi ro: push sai (tài nguyên đã cache rồi, hoặc client không cần) → lãng phí băng thông.
![[HTTP/2] Phần 2: Tìm hiểu thêm Server Push 29 image 18 - quochung.cyou PTIT](https://quochung.cyou/wp-content/uploads/2025/08/image-18.png)
![[HTTP/2] Phần 2: Tìm hiểu thêm Server Push 30 image 19 - quochung.cyou PTIT](https://quochung.cyou/wp-content/uploads/2025/08/image-19.png)
![[HTTP/2] Phần 2: Tìm hiểu thêm Server Push 31 image 20 - quochung.cyou PTIT](https://quochung.cyou/wp-content/uploads/2025/08/image-20.png)
![[HTTP/2] Phần 2: Tìm hiểu thêm Server Push 32 image 21 - quochung.cyou PTIT](https://quochung.cyou/wp-content/uploads/2025/08/image-21.png)
![[HTTP/2] Phần 2: Tìm hiểu thêm Server Push 33 image 22 - quochung.cyou PTIT](https://quochung.cyou/wp-content/uploads/2025/08/image-22.png)
![[HTTP/2] Phần 2: Tìm hiểu thêm Server Push 34 image 23 - quochung.cyou PTIT](https://quochung.cyou/wp-content/uploads/2025/08/image-23.png)
![[HTTP/2] Phần 2: Tìm hiểu thêm Server Push 36 image 25 - quochung.cyou PTIT](https://quochung.cyou/wp-content/uploads/2025/08/image-25.png)