Lược sử từ HTTP/1 tới HTTP/2 và tương lai của HTTP
http
1
http2
1
quic
1
SPDY
1
White

dungcoi viết ngày 30/09/2015

HTTP/1

Năm 1989, Tim Berners-Lee phát minh ra HTTP. Năm 1996, HTTP 1.0 được tổ chức RFC thông qua trở thành một chuẩn, HTTP 1.1 cũng hình thành cùng năm đó, đây là một trong những cột mốc quan trọng bật nhất khiến thế giới công nghệ phát triển như vũ bão và định hình như ngày hôm nay. Sau 26 năm kể từ ngày phát minh, và gần 20 năm kể từ ngày phiên bản 1.0 xuất hiện, tháng 5 năm 2015, tổ chức RFC đã thông qua đặc tả HTTP 2, đánh dấu thay đổi lớn nhất kể từ ngày hình thành tới nay của giao thức HTTP.
Trong cái thời buổi mà version của Chrome hay Firefox tăng vùn vụt tính theo tháng thì chuyện nâng version đó không mang nhiều lưu tâm, nhưng từ con số 1.1 lên 2 tốn mất 20 năm, ở một giao thức chiếm tầm quan trọng như HTTP thì nó lại là một chuyện khác, đó là một vấn đề to tát.

Bài viết sẽ không đi sâu chi tiết của HTTP 2, thay vào đó là việc cố gắng nhìn nhận vấn đề cốt lõi của việc lên đời này đó là vấn đề kết nối và truyền dữ liệu.
Đầu tiên, chúng ta quan sát lại cách làm của HTTP/1

1. Mỗi connection một tài nguyên

alt text
Hình: HTTP/1 mỗi connection một tài nguyên

Trong dạng xử lý này, mỗi connection sẽ request một tài nguyên độc lập. Kết nối sẽ được mở mới khi cần request một tài nguyên và close khi nhận response hoàn tất. Đây là dạng làm việc đơn giản và cũng là thông dụng nhất, tuy nhiên rất không tối ưu vì thời gian thiết lập kết nối mới tốn rất nhiều thời gian do phải thực hiện bắt tay 3 bước, chưa kể nếu có các lớp xử lý bảo mật như TLS sẽ càng làm tăng độ trễ của việc thiết lập kết nối này.

2. Keep-alive connection

alt text
Hình: Connection keep-alive

Với keep-alive connection, có thể thực hiện nhiều lượt request tài nguyên khác nhau với cùng một connection.

Tuy nhiên, chúng ta dễ dàng nhận thấy một khoảng thời gian chờ sau khi thực hiện một request, trong lúc đợi response về hoàn tất, sẽ không có một request nào khác được phép thực hiện. Điều này gây lãng phí tài nguyên, do băng thông vẫn còn đó trong khi request tài nguyên khác sẽ không thể request ở cùng connection, và nếu tạo connection mới thì lại trở lại vấn đề với mỗi request một connection.

3. HTTP/1 pipelining

alt text
Hình: HTTP pipelining

Giải pháp cho phép nhiều lượt request được gọi mà không cần response phải hoàn thành, sau đó sẽ nhận các response. Một giải pháp khá mượt, nhưng nhìn sâu hơn vấn đề một chút, đầu tiên ta quan sát lại HTTP request và response.

Một cú pháp request điển hình như sau:
GET /index.html HTTP/1.1
Host: www.example.com

Cú pháp response dạng:

HTTP/1.1 200 OK
Date: Mon, 23 May 2005 22:38:34 GMT
Server: Apache/1.3.3.7 (Unix) (Red-Hat/Linux)
Last-Modified: Wed, 08 Jan 2003 23:11:55 GMT
ETag: "3f80f-1b6-3e1cb03b"
Content-Type: text/html; charset=UTF-8Content-Length: 138
Accept-Ranges: bytes
Connection: close
<html>
<head>
<title>An Example Page</title>
</head>
<body>
Hello World, this is a very simple HTML document.
</body>
</html>

Nếu dữ liệu response về không có thứ tự mà đi lộn xộn, thì do cùng sử dụng 1 connection chung, đầu nhận response sẽ không thể phân biệt được phần dữ liệu là thuộc request nào.
Điều này khiến HTTP pipelining phải tuân thủ một điều là phía client chỉ sau khi nhận trọn vẹn một response của request này mới được nhận tiếp response từ request khác, việc này gây ra nguy cơ về hiệu năng khi có một response bị mất hay bị xử lý chậm.

alt text
Hình: Head-of-line blocking trong HTTP pipelining

Vấn đề này được gọi là head-of-line blocking. Nếu vì một lý do nào đó request tới trước được phía server xử lý chậm hơn request sau thì các request sau nó cũng không được response về ngay mà buộc phải đợi.
Vì vấn đề này mà hầu hết các trình duyệt dù đều có hỗ trợ sẵn HTTP pipelining nhưng đều mặc định disabled. Ở góc nhìn web server cũng không khá hơn mấy, một số web server có vấn đề khi xử lý HTTP pipelining.
Những vấn đề với HTTP pipelining khiến tiến trình cải tiến tốc độ ở góc nhìn kết nối và truyền tải bị dừng lại. HTTP/1 cứ vậy vận hành với phiên bản 1.1, cho tới khi giao thức SPDY xuất hiện, đây là nền tảng cho việc xây dựng HTTP/2.

HTTP/2

Năm 2009, Google giới thiệu giao thức SPDY, về cơ bản đây là một giao thức ở tầng TCP sử dụng binary thay vì trên text như HTTP/1. Giao thức cũng hỗ trợ sẵn cơ chế về nén dữ liệu, lớp bảo mật, chế độ ưu tiên ... để tăng tốc độ truyền tải dữ liệu web.
Năm 2015, trên nền tảng của SPDY, HTTP/2 được tổ chức RFC công nhận như một chuẩn. Tiến trình phổ cập HTTP/2 thay thế HTTP/1 đang diễn ra trên toàn cầu.

1. Tổng quát

alt text
Hình: Kiến trúc HTTP/2

HTTP/2 xây dựng trên tư tưởng mỗi TCP connection sẽ có nhiều stream, mỗi packet truyền tải trong stream sẽ là một frame, các frame này sẽ có đầy đủ các thông tin định danh stream.

alt text
Hình: HTTP/2 nhiều stream dùng chung một connection

Khi sử dụng, mỗi request tài nguyên sẽ sử dụng một stream độc lập, mỗi frame đều có thông tin định danh cho stream riêng, nên việc thứ tự truyền/nhận của request/response không còn là vấn đề, dữ liệu của frame nào sẽ được đưa vào stream của nó, tương ứng với đó là request/response tương ứng. Như vậy vấn đề head-of-line blocking được giải quyết.

alt text
Hình: Vấn đề Head-of-line blocking được giải quyết trong HTTP/2

2. Vấn đề

a. Head-of-line blocking gây ra bởi TCP

HTTP/2 là một kiến trúc đẹp, nhưng tư tưởng xây dựng nó nhiều stream dùng chung một TCP connection, tức là sử dụng chung một đường truyền tải. Khi gói tin từ stream được đóng gói để đưa xuống tầng TCP, gói tin sẽ lại được đóng gói (trong nhiều trường hợp có thể bị chia nhỏ hơn để đóng gói) bởi giao thức TCP, bằng cách đánh thêm chỉ số tuần tự và các thông tin khác ... để đưa xuống tầng IP và truyền đi. Tầng IP sẽ không đảm bảo gói tin sẽ không mất mát và đúng thứ tự, vì vậy tầng TCP sẽ làm việc đó, nếu có gói tin nào bị mất mát do truyền tải ở tầng IP thì tầng TCP sẽ gửi lại gói tin tương ứng.

Trong trường hợp những gói tin này thuộc các stream khác nhau, thì khi mất mát gói tin của một stream thì các stream còn lại sẽ bị ảnh hưởng. Vấn đề head-of-line blocking lại xuất hiện, nhưng lần này là do cơ chế của TCP gây nên.

alt text
Hình: Head-of-line blocking do cơ chế bảo vệ flow của TCP

b. Stream dùng chung thuật toán chống nghẽn

Thuật toán chống nghẽn được thiết kế nhằm giúp TCP sử dụng băng thông tối đa mà nó có thể, tùy vào lượng mất mát gói tin mà thuật toán sẽ tự điều chỉnh lượng băng thông truyền đi.
Trong HTTP/2, nhiều stream sẽ dùng chung trên một connection, nên sẽ phải sử dụng chung một trạng thái chống nghẽn. Việc này sẽ gây ra vấn đề nếu một gói tin thuộc connection tương ứng bị mất gói tin, thì thuật toán chống nghẽn sẽ điều chỉnh làm chậm băng thông của connection lại, kéo theo việc các stream còn lại của connection này cũng sẽ bị chậm theo.

QUIC - Quick UDP Internet Connections

1. Tổng quát

Để khắc phục vấn đề head-of-line blocking gây ra bởi TCP, cách duy nhất là thiết kế HTTP/2 trên nền một giao thức khác. QUIC lựa chọn xây dựng lại trên nền UDP, một giao thức thông dụng và có thể dễ dàng tương tác ở userland.

Tư tưởng thiết kế giao thức QUIC là sự kết hợp giữa TCP và tinh thần của HTTP/2

  • Đảm bảo không mất mát, đúng thứ tự gói tin: Tương tự TCP
  • Cải thiện thuật toán chống nghẽn: Sử dụng thuật toán CUBIC
  • Tự sửa lỗi gói tin
  • Hỗ trợ lớp bảo mật TLS

alt text
Hình: QUIC = TLS + TCP + SPDY

Mặc dù trong UDP, khái niệm connection không tồn tại, nhưng dựa trên tinh thần của TCP, QUIC xây dựng lại connection cho mình, tuy nhiên nhiên tầng truyền tải dữ liệu sẽ độc lập giữa các stream. Điều này giúp loại bỏ head-of-line blocking gây ra khi các stream truyền tải dùng chung connection. Một điều thú vị là connection của QUIC sẽ tốt hơn TCP trong một số trường hợp, ví dụ khi kết nối mạng của bạn đang sử dụng đột ngột bị ngắt và connect lại, lúc này connection của TCP sẽ bị mất và buộc phải khởi tạo kết nối mới, do xây dựng trên nền tảng UDP - một giao thức phi kết nối (connectionless) nên về lý thuyết thì connection sẽ vẫn tiếp tục truyền nhận dữ liệu bình thường dù sẽ chậm đi một chút.
QUIC cũng sử dụng thuật toán chống nghẽn cho từng stream riêng biệt, loại bỏ vấn đề thuật toán chống nghẽn gây ra cho HTTP/2.

alt text
Hình: Giao thức QUIC

2. Lời kết

QUIC hiện tại là một phần của dự án Chromium, chưa có một đóng gói độc lập nào để sử dụng giao thức này. Điều này khiến việc sử dụng QUIC rất khó khăn. Mặc dù rất nhiều các service của Google hiện tại đã dùng QUIC, nhưng việc sử dụng rộng rãi giao thức này còn rất hạn chế. Hiện chỉ 2 trình duyệt hỗ trợ giao thức này là Chromium, Chrome và Opera.
Việc cố gắng xây dựng lại một giao thức lõi của internet của Google là một diễn biến lạ lẫm, họ thử nghiệm QUIC trên những sản phẩm nội bộ của mình (các dịch vụ web và trình duyệt), nhưng Google đủ lớn để biến những cuộc thử nghiệm về công nghệ khiến cả thế giới công nghệ phải ồn ào và học hỏi, thậm chí trở thành chuẩn. Trường hợp đó đã đúng với Ajax, BigTable, SPDY ... và biết đâu đó là QUIC trong tương lai.

So sánh tốc độ HTTP/1 và HTTP/2

Thank em @HuyTran nhiều nhiều về gợi ý bổ sung minh họa cho phần này.
Để dễ dàng hình dung sự khác biệt về tốc độ của HTTP/1.1 với HTTP/2 chúng ta quan sát một thực nghiệm cụ thể. Để thực nghiệm lợi thế của việc sử dụng nhiều stream trong cùng một kết nối TCP, ở đây người ta xây dựng 1 trang web nhỏ gồm nhiều bức hình nhỏ ghép lại thành 1 bức hình lớn.

Với HTTP/1.1, một kết nối TCP sẽ tiến hành load tuần tự từng bức ảnh nhỏ, sau khi hoàn thành 1 ảnh sẽ tiếp tục load ảnh tiếp theo. Đây là vấn đề head-of-line blocking đề cập trong bài viết.
Với HTTP/2, một kết nối TCP chia thành nhiều stream, mỗi stream truyền một bức ảnh nhỏ, các gói tin của các stream có thể đi xen lẫn nhau không nhất thiết phải đợi nhau hoàn thành, vì vậy gần như được stream đồng thời cùng lúc nhiều ảnh.

alt text
Hình: So sánh tốc độ của HTTP/1.1 với HTTP/2

Nếu muốn bạn có thể trải nghiệm thực tế thì có thể truy cập ví dụ tương tự tại đây.

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

dungcoi

4 bài viết.
90 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
26 3
simplehttp à một source viết bởi bitly : https://github.com/bitly/simplehttp Như các bạn thấy các từ simple, bit : đơn giản và nhỏ bé thôi, đừng t...
dungcoi viết hơn 2 năm trước
26 3
White
16 4
Trong note này bạn sẽ thấy sự xuất hiện các node.js , socket.io, redis ... hay đủ thứ khác, nhưng nội dung của note chỉ luẩn quẩn quanh khái niệm s...
dungcoi viết 2 năm trước
16 4
White
14 2
(Link) là một phần mềm load balancing thông dụng được phát triển trên ngôn ngữ C, có tốc độ xử lý và độ ổn định rất cao, các lý do thì hầu hết đã đ...
dungcoi viết hơn 2 năm trước
14 2
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
4 bài viết.
90 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!