Welcome to HTTP/2
This post hasn't been updated for 3 years
Introduction
HTTP/2.0 is not future, it's present
Đã 1 khoảng thời gian rất dài từ khi bộ giao thức HTTP được ra đời, các ứng dụng web đã tiến hóa hoàn toàn khác biệt. Giờ đây chúng ta tạo ra các ứng dụng Web và ngày càng có nhiều xử lý logic ở trình duyệt cũng như việc tải nhiều assets hơn về client. Ngoài ra nhu cầu tối ưu hóa tốc độ cho Mobile, Smartphone,... cũng được quan tâm rất nhiều. Các LTV front-end đã và đang cố gắng nén thật nhiều, ghép thật nhiều các asset vào 1 bundle khổng lồ bởi vì
Tải 1 file lớn thì nhanh hơn tải nhiều file nhỏ
Giờ đây với HTTP/2.0 thì điều đó đã không còn đúng nữa. HTTP/2.0 ra đời đã thay đổi phương thức trao đổi dữ liệu của client - server dựa vào response - request truyền thống hay còn gọi là Stateless Paradigm. HTTP/2.0 là một Stateful Protocol, nó đem lại tốc độ tải trang nhanh hơn đáng kể. Bên cạnh đó HTTP/2.0 cũng mang tới thêm những tính năng về bảo mật ( TLS 2.0 ), Server Preload ,...
Điều tuyệt vời hơn nữa là cho tới thời điểm này, HTTP/2.0 đã được hỗ trợ bởi hầu hết các trình duyệt thông dụng, bạn có thể dễ dàng tìm được hướng dẫn nâng cấp trên google. Còn trong bài viết này chúng ta sẽ cùng đi sâu hơn 1 chút về bản chất cái gì đã tạo nên sức mạnh của HTTP/2.0 nhé.
HTTP/2.0 Goal
Mục tiêu hàng đầu của HTTP/2 là giảm thiểu độ trễ của giao tiếp giữa client với server thông qua:
- Full request and response multiplexing, không còn phân chia request và response thành các đường truyền riêng biệt (singleplexing) như HTTP/1.x.
- Tối giản dư thừa dữ liệu bằng việc nén các trường HTTP Header
- Thêm vào tính năng Server Push (Server Preload)
Để có thể đạt được những mục tiêu đó, đã có nhiều thay đổi về cơ chế flow control, xử lý lỗi,... bên trong lõi hệ thống tuy nhiên HTTP/2.0 không thay đổi về API tầng ứng dụng của mình. Tất cả những khái niệm như HTTP methods, Status code, URL,... đều được giữ nguyên giúp cho các nhà phát triển vaf các ứng dụng cũ hoàn toàn tương thích với HTTP/2.0 mà không gặp bất cứ xung đột nào.
Brief History
HTTP là 1 trong những protocol phổ biến và nổi tiếng nhất trong thế giới Web, HTTP được kiến tạo bởi Tim Berners-Lee (CERN) vào năm 1989. Tiêu chuẩn của HTTP được định nghĩa bởi 2 tổ chức IETF và W3C, và được công bố thông qua RFCs. Trước HTTP/2.0 thì HTTP cũng đã trải qua những lần thay đổi, nổi bật là sự ra đời của HTTP/1.1 vào năm 1997. Bản thân HTTP/1.1 cũng đã liên tục được cải tiến và lần gần nhất vào năm 2014 trong RFC 7230, đây cũng đang là phiên bản được sử dụng nhiều nhất hiện tại. Năm 2009, Google đi đầu trong việt tạo ra 1 bộ giao thức mới được gọi là SPDY dựa trên HTTP. Năm 2015, HTTP/2 (hay HTTP/2.0) chính thức ra đời kế thừa SPDY, đánh dấu sự thay đổi lớn nhất từ trước tới nay của giao thức HTTP. Theo W3Techs, cho đến tháng 11 năm 2017, đã có 20,5% trong số top 10 triệu trang web đã hỗ trợ bộ giao thức mới này.
Why not HTTP/1.2
HTTP/2.0 giới thiệu cơ chế Binary Framing Layer hoàn toàn mới và không tương thích ngược với bộ tiêu chuẩn HTTP/1.x. Tuy vậy như đã nói ở trên những thay đổi kỹ thuật của HTTP/2.0 nằm ở Transport Layer chứ không phải Application Layer - nên trừ khi bạn đang phát triển 1 webserver làm việc trực tiếp với TCP socket, thì sẽ không có sự khác biệt nào giữa HTTP/1.x và HTTP/2.0
HTTP/2.0 Core
Binary framing layer
Cốt lõi của việc cải thiện hiệu năng trong HTTP/2.0 nằm ở Binary framing layer, đây là lớp điều phối các gói tin sẽ được đóng gói và vận chuyển như thế nào giữa client và server. Tất cả các API (headers, statuscode, verbs,... ) từ HTTP/1.x đều được giữ nguyên nhưng cách chúng được mã hóa khi được vận chuyển đã thay đổi. Nếu HTTP/1.x sử dụng dấu "xuống dòng - newline" để phân cách câu lệnh thì HTTP/2.0 phân tách các gói tin trở thành các gói tin nhỏ hơn và các frames, tất cả đều được mã hóa kiểu nhị phân. Kết quả là cả client và server đều phải sử dụng chung 1 cơ chế mã hóa để có thể hiểu nhau. Thật may, đây không phải việc chúng ta cần quan tâm, các ứng dụng sẽ không nhận ra sự thay đổi trong cơ chế làm việc của HTTP/2.0 bởi chúng đã được xử lý bởi các ứng dụng low-level (như Apache, Chrome ,...)
Termilogies
Để hiểu được về Binary framing layer, hãy làm quen với các thuật ngữ mới của HTTP/2.0:
- Stream: Đây là 1 kết nối 2 chiều, nơi các gói tin (messages) được vận chuyển.
- Message: Do 1 chuỗi các frames sẽ tạo thành 1 gói tin request hoặc response
- Frame: Đơn vị thông tin nhỏ nhất trong HTTP/2.0, mỗi frame chứa 1 frame header, header tối thiểu chứa thông tin về stream nó thuộc về.
Sự liên kết giữa các thuật ngữ này được mô tả như sau:
- Tất cả giao tiếp đều được thực hiện qua duy nhất 1 kết nối TCP, nơi chứa các stream 2 chiều.
- Mỗi stream có 1 định danh duy nhất, có thể có thêm thông tin về độ ưu tiên, được sử dụng để vận chuyển các gói tin
- Mỗi gói tin có thể là 1 request hay 1 response và được hợp thành bởi nhiều frames
- Frame là đơn vị nhỏ nhất, frame từ các streams khác nhau có thể được gửi đan xen nhau và sau đó được sắp xếp lại đúng với stream nó thuộc về dựa vào thông tin ở header.
Request and response multiplexing
HTTP1/x sử dụng nhiều kết nối TCP (xem Using Multiple TCP Connections), mỗi connection chỉ phục vụ cho 1 request hoặc 1 response, điều này gây ra head-of-line blocking và không tận dung được toàn bộ TCP connection. Binary Framing Layer phá bỏ giới hạn này, bằng cách cho phép Client & Server tách các gói tin HTTP trở thành các frames, đan xen chúng và kết thúc bằng việc ghép chúng lại, tận dụng tối đa kết nối.
Có thể thấy trong hình minh họa cùng 1 lúc 3 gói tin được vận chuyển thông qua chỉ 1 kết nối TCP
Bình thường HTTP/1.x gửi các request riêng biệt trên mỗi kết nối
HTTP/2.0 gửi nhiều request trên 1 kết nối
Stream prioritization
Mỗi HTTP message được cắt thành nhiều frames riêng biệt, và những frame này khi ở các stream riêng biệt cũng có thể được ghép lại vận chuyển cùng nhau. Để cụ thể hóa chức năng này, HTTP/2.0 cho phép:
- Mỗi stream được gán 1 số nguyên từ 1 đến 256 gọi là weight
- Mỗi stream có thể được gán với 1 dependency ở stream khác.
Sự kết hợp này hình thành nên "prioritization tree" (cây ưu tiên). Cây ưu tiên mang thông tin về thứ tự ưu tiên của response. Nhờ vào mức độ ưu tiên server tối ưu hóa được nguồn lực để xử lý những stream mang thứ tự ưu tiên cao hơn trước.
Hình thứ 2 sẽ được thông dịch và có thể được diễn tả bằng human-language như sau:
Hãy vận chuyển và xử lý response D trước response C (do C lúc này đang phụ thuộc vào D)
Các stream có chung stream mẹ, sẽ được phân bổ thứ tự ưu tiên dựa vào weight Ví dụ: Stream A có weight là 12, B có weight là 4. Vậy thì tổng weight của 2 stream là 16, stream A nhận được A = 12/16 (3/4) tài nguyên, stream B nhận được B = 4/16 (1/4) tài nguyên.
HTTP/2.0 cũng cho phép Client thay đổi các giá trị cũng như dependency on-line cho phù hợp với yêu cầu.
One connection per origin
Bởi vì chỉ sử dụng 1 connection, HTTP/2.0 giảm thiểu bộ nhớ cần thiết, các tiến trình xử lý cho việc khởi tạo và kết nối TCP cũng được tối ưu. Như vậy không chỉ tăng tốc độ, HTTP/2.0 còn giảm được chi phí vận hành, dung lượng bộ nhất và đảm bảo chất lượng đường truyền.
Flow Control
Flow Control là 1 cơ chế giúp ngăn chặn dư thừa dữ liệu được gửi đi. Lấy ví dụ: Khi người dùng đang stream video và click vào nút pause, lúc này client không mong muốn nhận thêm data từ phía Server. TCP flow control là có sẵn nhưng bị giới hạn bởi 1 số vấn đề Xem Flow Control HTTP/2.0 cung cấp stream- and connection-level flow control hoàn toàn mới để giải quyết những vấn đề đó:
- Flow Control mang tính 2 chiều, mỗi chủ thể đều có thể thiết lập giới hạn về stream mình muốn nhận được
- Flow Control dựa trên độ tin tưởng của kết nối. Điều đó có nghĩa chủ thể nhận sẽ gửi đi các thông tin yêu cầu tăng hay giảm lương data muốn nhận.
- Flow Control không thể bị vô hiệu hóa.
- Flow Control có thể được 1 chủ thể trung gian đã qua xác thực thay đổi.
Server Push
Đây là tính năng rất mạnh mẽ cho phép Server gửi nhiều response về Client khi nhận được chỉ 1 request.
Ngay khi Client request index.html
ngay lập tức, Server sẽ trả về index.html
và cả style.css
nữa, điều này có thể thực hiện do cơ chế single connection, single origin được nhắc tới ở trên. Và trình duyệt có thể render trang web ngay lập tức thay vì chờ đợi request thứ 2 cho style.css
dược phản hồi.
PUSH_PROMISE 101
Tất cả server stream đều được khởi tạo thông qua PUSH_PROMISE 101
frame, thứ sẽ báo hiệu cho server push các tài nguyên cần thiết tới cho client và cần được vận chuyển trước khi server nhận được request tài nguyên đó. Thứ tự này là rất quan trọng bởi vì Client cần biết Server sẽ phản hồi những gì cho mình để tránh những request dư thừa. Thông thường các frame chứa thông tin về tài nguyên sẽ được phản hồi được gửi đi trước khi gói tin chính được gửi. Khi đã nhận được các frames này, Client dễ dang quyết định và điều chỉnh lượng tài nguyên mình muốn nhận thông qua frame SETTING
.
Header Compression
Mỗi gói tin HTTP chứa 1 tập hợp các headers mô tả tài nguyên và thuộc tính của gói tin, ở HTTP/1.x các siêu dữ liệu này được gửi dưới dạng plain text và thường chiếm 500-800 bytes, đôi lúc lên tới kylobytes nếu có chứa cookies. Để tối giản nó, HTTP/2 đã nén chúng lại sử dụng HPACK format.
- HTTP/2.0 sử dụng Huffman code để mãn hóa
- Yêu cầu cả client và server lưu giữ 1 danh sách chỉ mục những trường headers đã được khởi tạo và sử dụng như 1 bảng tham chiếu tới những giá trị đã được mã hóa.
HPACK chứa cả static và dynamic table:
- Static table là nơi chứa các HTTP header fields có khả năng cao được sử dụng.
- Dynamic table được khởi tạo rỗng và được lấp đầy giá trị bằng các giá trị chiết xuất từ mỗi connection.
Security and performance of HPACK
Trước đây HTTP/2 và SPDY sử dụng zlib để mã hóa HTTP headers, zlib có khả năng nén đến 88% data của header và nâng cấp đáng kể độ trễ khi tải trang. Vào năm 2012, Cuộc tấn công mang tên "CRIME" xảy ra dựa trên thuật toán bảo mật của TLS và SPDY thông qua kỹ thuật session hijacking - Đây là kiểu tấn công mà attacker mạo danh được request dựa trên 1 người dùng đã được xác thực. Xem hình minh hoạ để hiểu rõ hơn
Sau đó thì HTTP/2.0 đã được chuyển sang sử dụng HPACK, đến lúc này thì HPACK vẫn đang chứng tỏ khả năng bảo mật tốt hơn so người zlib IETF HPACK
The end
Có thể thấy HTTP/2 đem lại sức mạnh mới cho nền tảng web hiện tại, không có lý do gì trì hoãn việc nâng cấp lên HTTP/2.0 cả. Qua bài viết tôi cũng đã phân tích khái quát về lớp low-level mà HTTP/2.0 đã triển khai, điều này sẽ giúp các bạn hiểu rõ cách HTTP/2.0 vận hành qua đó vận dụng và tự mình đưa ra những phương án mới cải tiến cho nền tảng ứng dụng web/server của mình. Hiện nay chưa có bất cứ thông tin gì về HTTP/3 cũng như 1 bản nâng cấp mới nào của HTTP/2, nhưng tương lai và công nghệ là 2 thứ song hành, chúng ta không nên chờ đợi thêm phút nào để upgrade hệ thống lên HTTP/2.0 cả.
References
HTTP/2 is here, let's optimize! - Velocity SC 2015 High Performance Browser Networking -* Ilya Grigorik* https://en.wikipedia.org/wiki/HTTP/2 https://medium.com/eleven-labs/http-2-is-not-future-its-present-b4e4fdd99cbe https://developers.google.com/web/fundamentals/performance/http2/
All Rights Reserved