Thứ tư, 30/01/2019 | 00:00 GMT+7

HTTP / 1.1 so với HTTP / 2: Sự khác biệt là gì?

Giao thức truyền siêu văn bản, hoặc HTTP, là một giao thức ứng dụng đã trở thành tiêu chuẩn thực tế cho giao tiếp trên World Wide Web kể từ khi được phát minh vào năm 1989. Từ khi phát hành HTTP / 1.1 vào năm 1997 cho đến gần đây, đã có một số bản sửa đổi đối với giao thức. Nhưng vào năm 2015, một version được mô phỏng lại có tên là HTTP / 2 đã được đưa vào sử dụng, cung cấp một số phương pháp để giảm độ trễ, đặc biệt khi xử lý các nền tảng di động, đồ họa và video sử dụng nhiều server . HTTP / 2 kể từ đó ngày càng trở nên phổ biến, với một số ước tính cho thấy rằng khoảng một phần ba số trang web trên thế giới hỗ trợ nó. Trong bối cảnh thay đổi này, các nhà phát triển web có thể hưởng lợi từ việc hiểu được sự khác biệt về kỹ thuật giữa HTTP / 1.1 và HTTP / 2, cho phép họ đưa ra quyết định sáng suốt và hiệu quả về việc phát triển các phương pháp hay nhất.

Sau khi đọc bài viết này, bạn sẽ hiểu sự khác biệt chính giữa HTTP / 1.1 và HTTP / 2, tập trung vào những thay đổi kỹ thuật mà HTTP / 2 đã áp dụng để đạt được một giao thức Web hiệu quả hơn.

Lý lịch

Để ngữ cảnh hóa những thay đổi cụ thể mà HTTP / 2 đã thực hiện đối với HTTP / 1.1, trước tiên ta hãy xem xét sự phát triển lịch sử và hoạt động cơ bản của từng loại.

HTTP / 1.1

Được phát triển bởi Timothy Berners-Lee vào năm 1989 như một tiêu chuẩn giao tiếp cho World Wide Web, HTTP là một giao thức ứng dụng cấp cao nhất trao đổi thông tin giữa một client và một web server local hoặc từ xa. Trong quá trình này, một client gửi một yêu cầu dựa trên văn bản đến server bằng cách gọi một phương thức như GET hoặc POST . Đáp lại, server sẽ gửi lại một tài nguyên như trang HTML cho client .

Ví dụ: giả sử bạn đang truy cập một trang web tại domain www.example.com . Khi bạn chuyển đến URL này, trình duyệt web trên máy tính của bạn sẽ gửi một yêu cầu HTTP dưới dạng một thông báo dựa trên văn bản, tương tự như một thông báo hiển thị ở đây:

GET /index.html HTTP/1.1 Host: www.example.com 

Yêu cầu này sử dụng phương thức GET , phương thức này yêu cầu dữ liệu từ server lưu trữ được liệt kê sau Host: Để đáp ứng yêu cầu này, web server example.com trả về một trang HTML cho ứng dụng client yêu cầu, ngoài bất kỳ hình ảnh, bảng định kiểu nào hoặc các tài nguyên khác được gọi trong HTML. Lưu ý không phải tất cả các tài nguyên đều được trả lại cho client trong lần gọi dữ liệu đầu tiên. Các yêu cầu và phản hồi sẽ qua lại giữa server và client cho đến khi trình duyệt web nhận được tất cả các tài nguyên cần thiết để hiển thị nội dung của trang HTML trên màn hình của bạn.

Bạn có thể coi việc trao đổi yêu cầu và phản hồi này như một lớp ứng dụng duy nhất của ngăn xếp giao thức internet, nằm trên đầu lớp truyền (thường sử dụng Giao thức điều khiển truyền hoặc TCP) và các lớp mạng (sử dụng Giao thức Internet hoặc IP ):

Ngăn xếp giao thức Internet

Có nhiều điều để thảo luận về các cấp thấp hơn của ngăn xếp này, nhưng để có được hiểu biết cấp cao về HTTP / 2, bạn chỉ cần biết mô hình lớp trừu tượng này và vị trí HTTP đưa vào.

Với tổng quan cơ bản về HTTP / 1.1 này, bây giờ ta có thể chuyển sang kể lại sự phát triển ban đầu của HTTP / 2.

HTTP / 2

HTTP / 2 bắt đầu là giao thức SPDY, được phát triển chủ yếu tại Google với mục đích giảm độ trễ tải trang web bằng cách sử dụng các kỹ thuật như nén, ghép kênh và ưu tiên. Giao thức này phục vụ như một khuôn mẫu cho HTTP / 2 khi group làm việc Giao thức truyền siêu văn bản httpbis của IETF (Lực lượng đặc nhiệm kỹ thuật Internet) đưa tiêu chuẩn lại với nhau, đỉnh điểm là việc xuất bản HTTP / 2 vào tháng 5 năm 2015. Ngay từ đầu, nhiều trình duyệt đã hỗ trợ nỗ lực tiêu chuẩn hóa này, bao gồm Chrome, Opera, Internet Explorer và Safari. Một phần do hỗ trợ trình duyệt này, đã có một tỷ lệ chấp nhận giao thức đáng kể kể từ năm 2015, với tỷ lệ đặc biệt cao trong số các trang web mới.

Từ quan điểm kỹ thuật, một trong những tính năng quan trọng nhất phân biệt HTTP / 1.1 và HTTP / 2 là lớp khung binary , có thể được coi như một phần của lớp ứng dụng trong ngăn xếp giao thức internet. Trái ngược với HTTP / 1.1, giữ tất cả các yêu cầu và phản hồi ở định dạng văn bản thuần túy, HTTP / 2 sử dụng lớp khung binary để đóng gói tất cả các thông báo ở định dạng binary , trong khi vẫn duy trì ngữ nghĩa HTTP, chẳng hạn như động từ, phương thức và tiêu đề. Một API cấp ứng dụng sẽ vẫn tạo thông báo ở các định dạng HTTP thông thường, nhưng lớp bên dưới sau đó sẽ chuyển đổi các thông báo này thành binary . Điều này đảm bảo các ứng dụng web được tạo trước HTTP / 2 có thể tiếp tục hoạt động bình thường khi tương tác với giao thức mới.

Việc chuyển đổi thông điệp thành binary cho phép HTTP / 2 thử các cách tiếp cận mới để phân phối dữ liệu không có trong HTTP / 1.1, một sự tương phản là root rễ của sự khác biệt thực tế giữa hai giao thức. Phần tiếp theo sẽ xem xét mô hình phân phối của HTTP / 1.1, tiếp theo là mô hình mới nào được HTTP / 2 tạo ra.

Mô hình giao hàng

Như đã đề cập trong phần trước, HTTP / 1.1 và HTTP / 2 phần ngữ nghĩa, đảm bảo các yêu cầu và phản ứng đi lại giữa server và khách hàng trong cả hai giao thức đạt được điểm đến của họ là truyền thống được định dạng tin nhắn với tiêu đề và các cơ quan, sử dụng các phương pháp quen thuộc như GETPOST .Nhưng trong khi HTTP / 1.1 chuyển những thứ này dưới dạng tin nhắn văn bản thuần túy, HTTP / 2 lại mã hóa những thứ này thành binary , cho phép các khả năng mô hình phân phối khác nhau đáng kể. Trong phần này, trước tiên, ta sẽ xem xét ngắn gọn cách HTTP / 1.1 cố gắng tối ưu hóa hiệu quả với mô hình phân phối của nó và các vấn đề nảy sinh từ điều này, tiếp theo là các ưu điểm của lớp khung binary của HTTP / 2 và mô tả cách nó ưu tiên các yêu cầu.

HTTP / 1.1 - Pipelining và Head-of-Line Block

Phản hồi đầu tiên mà khách hàng nhận được trên một yêu cầu HTTP GET thường không phải là trang được hiển thị đầy đủ. Thay vào đó, nó chứa các liên kết đến các tài nguyên bổ sung cần thiết cho trang được yêu cầu. Máy khách phát hiện ra rằng việc hiển thị đầy đủ trang yêu cầu các tài nguyên bổ sung này từ server chỉ sau khi server tải trang xuống. Do đó, khách hàng sẽ phải thực hiện các yêu cầu bổ sung để lấy các tài nguyên này. Trong HTTP / 1.0, client phải ngắt và tạo lại kết nối TCP với mỗi yêu cầu mới, một việc tốn kém cả về thời gian và tài nguyên.

HTTP / 1.1 giải quyết vấn đề này bằng cách giới thiệu các kết nối liên tục và pipelining. Với các kết nối liên tục, HTTP / 1.1 giả định kết nối TCP nên được giữ ở trạng thái mở trừ khi được yêu cầu trực tiếp đóng. Điều này cho phép client gửi nhiều yêu cầu dọc theo cùng một kết nối mà không cần đợi phản hồi cho từng yêu cầu, cải thiện đáng kể hiệu suất của HTTP / 1.1 so với HTTP / 1.0.

Thật không may, có một nút thắt tự nhiên đối với chiến lược tối ưu hóa này. Vì nhiều gói dữ liệu không thể vượt qua nhau khi đi đến cùng một đích, nên có những tình huống trong đó một yêu cầu ở đầu hàng đợi không thể truy xuất tài nguyên cần thiết của nó sẽ chặn tất cả các yêu cầu phía sau nó. Đây được gọi là chặn head-of-line (HOL) và là một vấn đề nghiêm trọng với việc tối ưu hóa hiệu quả kết nối trong HTTP / 1.1. Việc thêm các kết nối TCP song song, riêng biệt có thể giảm bớt vấn đề này, nhưng có giới hạn về số lượng kết nối TCP đồng thời có thể có giữa client và server và mỗi kết nối mới yêu cầu tài nguyên đáng kể.

Những vấn đề này luôn nằm trong tâm trí của các nhà phát triển HTTP / 2, những người đã đề xuất sử dụng lớp khung binary nói trên để khắc phục những vấn đề này, một chủ đề bạn sẽ tìm hiểu thêm trong phần tiếp theo.

HTTP / 2 - Ưu điểm của Lớp khung binary

Trong HTTP / 2, lớp khung binary mã hóa các yêu cầu / phản hồi và cắt chúng thành các gói thông tin nhỏ hơn, làm tăng đáng kể tính linh hoạt của việc truyền dữ liệu.

Ta hãy xem xét kỹ hơn cách thức hoạt động của nó. Trái ngược với HTTP / 1.1, phải sử dụng nhiều kết nối TCP để giảm bớt ảnh hưởng của việc chặn HOL, HTTP / 2 cài đặt một đối tượng kết nối duy nhất giữa hai máy. Trong kết nối này có nhiều luồng dữ liệu. Mỗi stream bao gồm nhiều thông báo ở định dạng yêu cầu / phản hồi quen thuộc. Cuối cùng, mỗi thông báo này được chia thành các đơn vị nhỏ hơn được gọi là khung :

Luồng, Tin nhắn và Khung

Ở cấp độ chi tiết nhất, kênh giao tiếp bao gồm một loạt các khung được mã hóa binary , mỗi khung được gắn thẻ cho một stream cụ thể. Các thẻ nhận dạng cho phép kết nối xen kẽ các khung này trong quá trình truyền và lắp ráp lại chúng ở đầu kia.Các yêu cầu và phản hồi xen kẽ có thể chạy song song mà không chặn các thông báo đằng sau chúng, một quá trình được gọi là ghép kênh . Ghép kênh giải quyết vấn đề chặn đầu dòng trong HTTP / 1.1 bằng cách đảm bảo không có thông báo nào phải chờ thông báo khác kết thúc. Điều này cũng nghĩa là server và client có thể gửi yêu cầu và phản hồi đồng thời, cho phép kiểm soát tốt hơn và quản lý kết nối hiệu quả hơn.

Vì ghép kênh cho phép client xây dựng nhiều stream song song, các stream này chỉ cần sử dụng một kết nối TCP duy nhất. Việc có một kết nối liên tục duy nhất cho mỗi điểm root sẽ cải thiện dựa trên HTTP / 1.1 bằng cách giảm bộ nhớ và xử lý dấu vết trên toàn mạng. Điều này dẫn đến việc sử dụng mạng và băng thông tốt hơn và do đó giảm chi phí vận hành tổng thể.

Một kết nối TCP duy nhất cũng cải thiện hiệu suất của giao thức HTTPS, vì client và server có thể sử dụng lại cùng một phiên bảo mật cho nhiều yêu cầu / phản hồi. Trong HTTPS, trong quá trình bắt tay TLS hoặc SSL, cả hai bên đồng ý về việc sử dụng một khóa duy nhất trong suốt phiên. Nếu kết nối bị ngắt, một phiên mới sẽ bắt đầu, yêu cầu một khóa mới được tạo để liên lạc thêm. Do đó, việc duy trì một kết nối duy nhất có thể làm giảm đáng kể tài nguyên cần thiết cho hiệu suất HTTPS. Lưu ý , mặc dù thông số kỹ thuật HTTP / 2 không bắt buộc phải sử dụng lớp TLS, nhiều trình duyệt chính chỉ hỗ trợ HTTP / 2 với HTTPS.

Mặc dù ghép kênh vốn có trong lớp khung binary giải quyết một số vấn đề nhất định của HTTP / 1.1, nhưng nhiều stream đang chờ cùng một tài nguyên vẫn có thể gây ra các vấn đề về hiệu suất. Tuy nhiên, thiết kế của HTTP / 2 có tính đến điều này bằng cách sử dụng ưu tiên stream , một chủ đề ta sẽ thảo luận trong phần tiếp theo.

HTTP / 2 - Ưu tiên stream

Ưu tiên stream không chỉ giải quyết vấn đề có thể xảy ra của các yêu cầu cạnh tranh cho cùng một tài nguyên mà còn cho phép các nhà phát triển tùy chỉnh trọng lượng tương đối của các yêu cầu để tối ưu hóa hiệu suất ứng dụng tốt hơn. Trong phần này, ta sẽ chia nhỏ quá trình ưu tiên này để cung cấp thông tin chi tiết hơn về cách bạn có thể tận dụng tính năng này của HTTP / 2.

Như bạn đã biết bây giờ, lớp khung binary tổ chức các thông điệp thành các stream dữ liệu song song. Khi một client gửi các yêu cầu đồng thời đến một server , nó có thể ưu tiên các phản hồi mà nó đang yêu cầu bằng cách gán trọng số từ 1 đến 256 cho mỗi stream . Số cao hơn cho thấy mức độ ưu tiên cao hơn. Ngoài ra, client cũng chỉ ra dependencies của mỗi stream vào một stream khác bằng cách chỉ định ID của stream mà nó phụ thuộc vào đó. Nếu định danh cha bị bỏ qua, stream được coi là phụ thuộc vào stream root . Điều này được minh họa trong hình sau:

Ưu tiên  stream

Trong hình minh họa, kênh chứa sáu stream , mỗi stream có một ID duy nhất và được liên kết với trọng số cụ thể. Luồng 1 không có ID cha được liên kết với nó và được liên kết với nút root theo mặc định. Tất cả các stream khác có một số ID root được đánh dấu. Việc phân bổ tài nguyên cho mỗi stream sẽ dựa trên trọng lượng mà chúng nắm giữ và các yếu tố phụ thuộc mà chúng yêu cầu. Ví dụ, các stream 5 và 6, trong hình đã được gán cùng một trọng số và cùng một stream mẹ, sẽ có cùng mức độ ưu tiên cho việc phân bổ tài nguyên.

Server sử dụng thông tin này để tạo cây phụ thuộc, cho phép server xác định thứ tự mà các yêu cầu sẽ lấy dữ liệu của chúng. Dựa trên các stream trong hình trước, cây phụ thuộc sẽ như sau:

Cây phụ thuộc

Trong cây phụ thuộc này, stream 1 phụ thuộc vào stream root và không có stream nào khác xuất phát từ root , vì vậy tất cả các tài nguyên có sẵn sẽ phân bổ cho stream 1 trước các stream khác. Vì cây cho biết stream 2 phụ thuộc vào việc hoàn thành stream 1, nên stream 2 sẽ không tiếp tục cho đến khi hoàn thành nhiệm vụ của stream 1. Bây giờ, ta hãy xem xét các stream 3 và 4. Cả hai stream này đều phụ thuộc vào stream 2. Như trong trường hợp của stream 1, stream 2 sẽ lấy tất cả các tài nguyên có sẵn trước stream 3 và 4. Sau khi stream 2 hoàn thành nhiệm vụ, các stream 3 và 4 sẽ nhận được các tài nguyên; chúng được chia theo tỷ lệ 2: 4 như được chỉ ra bởi trọng số của chúng, dẫn đến phần tài nguyên cao hơn cho stream 4. Cuối cùng, khi stream 3 kết thúc, stream 5 và 6 sẽ nhận được tài nguyên có sẵn thành các phần bằng nhau. Điều này có thể xảy ra trước khi stream 4 hoàn thành nhiệm vụ của nó, mặc dù stream 4 nhận được lượng tài nguyên cao hơn; các stream ở cấp thấp hơn được phép bắt đầu ngay sau khi các stream phụ thuộc ở cấp trên kết thúc.

Là một nhà phát triển ứng dụng, bạn có thể đặt trọng số trong yêu cầu của bạn dựa trên nhu cầu của bạn. Ví dụ: bạn có thể chỉ định mức độ ưu tiên thấp hơn để tải hình ảnh có độ phân giải cao sau khi cung cấp hình ảnh thu nhỏ trên trang web. Bằng cách cung cấp phương tiện phân công trọng lượng này, HTTP / 2 cho phép các nhà phát triển kiểm soát tốt hơn việc hiển thị trang web. Giao thức cũng cho phép khách hàng thay đổi các phụ thuộc và phân bổ lại trọng số trong thời gian chạy để đáp ứng với tương tác của user . Tuy nhiên, điều quan trọng cần lưu ý là server có thể tự thay đổi các ưu tiên được chỉ định nếu một stream nhất định bị chặn truy cập vào một tài nguyên cụ thể.

Tràn bộ nhớ

Trong bất kỳ kết nối TCP nào giữa hai máy, cả client và server đều có sẵn một lượng không gian đệm nhất định để chứa các yêu cầu đến chưa được xử lý. Các cache này cung cấp tính linh hoạt để giải quyết nhiều yêu cầu hoặc đặc biệt lớn, ngoài tốc độ không đồng đều của các kết nối xuôi và ngược dòng.

Tuy nhiên, có những tình huống trong đó cache là không đủ. Ví dụ: server có thể đang đẩy một lượng lớn dữ liệu với tốc độ mà ứng dụng client không thể đối phó do kích thước cache hạn chế hoặc băng thông thấp hơn. Tương tự như vậy, khi client tải một hình ảnh lớn hoặc video lên server , cache server có thể bị tràn, gây mất một số gói bổ sung.

Để tránh tràn cache , cơ chế kiểm soát stream phải ngăn người gửi lấn át dữ liệu của người nhận. Phần này sẽ cung cấp tổng quan về cách HTTP / 1.1 và HTTP / 2 sử dụng các version khác nhau của cơ chế này để đối phó với việc kiểm soát stream theo các mô hình phân phối khác nhau của chúng.

HTTP / 1.1

Trong HTTP / 1.1, điều khiển stream dựa vào kết nối TCP bên dưới. Khi kết nối này bắt đầu, cả client và server đều cài đặt kích thước cache của chúng bằng cách sử dụng cài đặt mặc định của hệ thống. Nếu cache của người nhận được lấp đầy một phần dữ liệu, nó sẽ thông báo cho người gửi biết cửa sổ nhận của nó, tức là lượng không gian khả dụng vẫn còn trong cache của nó. Cửa sổ nhận này được quảng cáo trong một tín hiệu được gọi là gói ACK , là gói dữ liệu mà người nhận gửi để xác nhận nó đã nhận được tín hiệu mở. Nếu kích thước cửa sổ nhận được quảng cáo này bằng 0, người gửi sẽ không gửi thêm dữ liệu nào cho đến khi client xóa cache nội bộ và sau đó yêu cầu tiếp tục truyền dữ liệu. Điều quan trọng cần lưu ý ở đây là việc sử dụng các cửa sổ nhận dựa trên kết nối TCP bên dưới chỉ có thể triển khai điều khiển stream ở một trong hai đầu của kết nối.

Vì HTTP / 1.1 dựa vào lớp truyền tải để tránh tràn cache , mỗi kết nối TCP mới yêu cầu một cơ chế điều khiển stream riêng biệt. HTTP / 2, tuy nhiên, ghép kênh trong một kết nối TCP duy nhất và sẽ phải thực hiện kiểm soát stream theo một cách khác.

HTTP / 2

HTTP / 2 ghép các stream dữ liệu trong một kết nối TCP. Do đó, các cửa sổ nhận ở cấp độ kết nối TCP không đủ để điều chỉnh việc phân phối các stream riêng lẻ. HTTP / 2 giải quyết vấn đề này bằng cách cho phép client và server triển khai các điều khiển stream của riêng họ, thay vì dựa vào lớp truyền tải. Lớp ứng dụng giao tiếp không gian đệm có sẵn, cho phép client và server đặt cửa sổ nhận ở mức của các stream được ghép kênh. Điều khiển stream quy mô nhỏ này có thể được sửa đổi hoặc duy trì sau kết nối ban đầu qua khung WINDOW_UPDATE .

Vì phương pháp này kiểm soát stream dữ liệu ở mức của lớp ứng dụng, nên cơ chế điều khiển stream không phải đợi tín hiệu đến đích cuối cùng trước khi điều chỉnh cửa sổ nhận. Các node trung gian có thể sử dụng thông tin cài đặt kiểm soát stream để xác định việc phân bổ tài nguyên của riêng chúng và sửa đổi cho phù hợp. Bằng cách này, mỗi server trung gian có thể thực hiện chiến lược tài nguyên tùy chỉnh của riêng mình, cho phép hiệu quả kết nối cao hơn.

Tính linh hoạt trong kiểm soát dòng chảy này có thể có lợi khi tạo ra các chiến lược nguồn lực thích hợp. Ví dụ: client có thể tìm nạp bản quét đầu tiên của một hình ảnh, hiển thị nó cho user và cho phép user xem trước nó trong khi tìm nạp các tài nguyên quan trọng hơn. Sau khi khách hàng tìm nạp các tài nguyên quan trọng này, trình duyệt sẽ tiếp tục truy xuất phần còn lại của hình ảnh. Do đó, trì hoãn việc triển khai kiểm soát stream cho client và server có thể cải thiện hiệu suất nhận thức của các ứng dụng web.

Về điều khiển stream và mức độ ưu tiên stream được đề cập trong phần trước, HTTP / 2 cung cấp mức kiểm soát chi tiết hơn, mở ra khả năng tối ưu hóa cao hơn. Phần tiếp theo sẽ giải thích một phương pháp khác duy nhất cho giao thức có thể tăng cường kết nối theo cách tương tự: dự đoán các yêu cầu tài nguyên với sự thúc đẩy của server .

Dự đoán yêu cầu tài nguyên

Trong một ứng dụng web điển hình, client sẽ gửi một yêu cầu GET và nhận một trang bằng HTML, thường là trang index của trang đó.Trong khi kiểm tra nội dung trang index , khách hàng có thể phát hiện ra rằng nó cần tìm nạp các tài nguyên bổ sung, chẳng hạn như file CSS và JavaScript, để hiển thị đầy đủ trang. Máy khách xác định rằng nó chỉ cần các tài nguyên bổ sung này sau khi nhận được phản hồi từ yêu cầu GET ban đầu và do đó phải thực hiện các yêu cầu bổ sung để tìm nạp các tài nguyên này và hoàn thành việc ghép trang lại với nhau. Những yêu cầu bổ sung này cuối cùng làm tăng thời gian tải kết nối.

Tuy nhiên, có các giải pháp cho vấn đề này: vì server biết trước rằng client sẽ yêu cầu file bổ sung, server có thể tiết kiệm thời gian của client bằng cách gửi các tài nguyên này cho client trước khi nó yêu cầu chúng. HTTP / 1.1 và HTTP / 2 có các chiến lược khác nhau để thực hiện điều này, mỗi chiến lược sẽ được mô tả trong phần tiếp theo.

HTTP / 1.1 - Nội tuyến tài nguyên

Trong HTTP / 1.1, nếu nhà phát triển biết trước tài nguyên bổ sung nào mà client cần để hiển thị trang, họ có thể sử dụng một kỹ thuật gọi là nội tuyến tài nguyên để bao gồm tài nguyên cần thiết trực tiếp trong trang HTML mà server gửi để phản hồi yêu cầu GET ban đầu. Ví dụ: nếu khách hàng cần một file CSS cụ thể để hiển thị một trang, thì nội tuyến file CSS đó sẽ cung cấp cho khách hàng tài nguyên cần thiết trước khi nó yêu cầu, giảm tổng số yêu cầu mà khách hàng phải gửi.

Nhưng có một vài vấn đề với nội tuyến tài nguyên. Bao gồm tài nguyên trong trang HTML là một giải pháp khả thi cho các tài nguyên nhỏ hơn, dựa trên văn bản, nhưng các file lớn hơn ở định dạng không phải văn bản có thể làm tăng đáng kể kích thước của trang HTML , điều này cuối cùng có thể làm giảm tốc độ kết nối và vô hiệu hóa lợi thế ban đầu đã đạt được từ việc sử dụng kỹ thuật này. Ngoài ra, vì các tài nguyên nội tuyến không còn tách biệt với trang HTML , nên không có cơ chế nào để client từ chối tài nguyên mà nó đã có hoặc đặt một tài nguyên vào bộ nhớ cache của nó. Nếu nhiều trang yêu cầu tài nguyên, mỗi trang HTML mới sẽ có cùng một tài nguyên được nội tuyến trong mã của nó, dẫn đến các trang HTML lớn hơn và thời gian tải lâu hơn so với khi tài nguyên chỉ được lưu vào bộ nhớ cache lúc đầu.

Do đó, một nhược điểm lớn của nội tuyến tài nguyên là client không thể tách biệt tài nguyên và tài liệu. Cần có mức độ kiểm soát tốt hơn để tối ưu hóa kết nối, một nhu cầu mà HTTP / 2 tìm cách đáp ứng với việc đẩy server .

HTTP / 2 - Server đẩy

Vì HTTP / 2 cho phép nhiều phản hồi đồng thời đối với yêu cầu GET ban đầu của khách hàng, nên server có thể gửi tài nguyên đến client cùng với trang HTML được yêu cầu, cung cấp tài nguyên trước khi khách hàng yêu cầu. Quá trình này được gọi là đẩy server . Bằng cách này, kết nối HTTP / 2 có thể thực hiện cùng một mục tiêu là nội tuyến tài nguyên trong khi vẫn duy trì sự tách biệt giữa tài nguyên được đẩy và tài liệu. Điều này nghĩa là client có thể quyết định lưu vào bộ nhớ cache hoặc từ chối tài nguyên được đẩy tách biệt khỏi trang HTML chính, khắc phục nhược điểm chính của nội tuyến tài nguyên.

Trong HTTP / 2, quá trình này bắt đầu khi server gửi một khung PUSH_PROMISE để thông báo cho client rằng nó sẽ đẩy một tài nguyên.Khung này chỉ bao gồm tiêu đề của thư và cho phép client biết trước tài nguyên mà server sẽ đẩy. Nếu nó đã có tài nguyên được lưu trong bộ nhớ cache, client có thể từ chối việc đẩy bằng cách gửi một khung RST_STREAM để phản hồi. Khung PUSH_PROMISE cũng giúp client không gửi một yêu cầu trùng lặp đến server , vì nó biết server sẽ đẩy tài nguyên nào.

Điều quan trọng cần lưu ý ở đây là sự nhấn mạnh của đẩy server là kiểm soát client . Nếu một ứng dụng client cần điều chỉnh mức độ ưu tiên của việc đẩy server hoặc thậm chí vô hiệu hóa nó, nó có thể gửi khung SETTINGS bất kỳ lúc nào để sửa đổi tính năng HTTP / 2 này.

Mặc dù tính năng này có rất nhiều tiềm năng, nhưng không phải lúc nào đẩy server cũng là câu trả lời để tối ưu hóa ứng dụng web của bạn. Ví dụ: một số trình duyệt web không thể luôn hủy các yêu cầu đã đẩy, ngay cả khi client đã có tài nguyên được lưu trong bộ nhớ cache. Nếu client nhầm lẫn cho phép server gửi tài nguyên trùng lặp, server đẩy có thể sử dụng hết kết nối một cách không cần thiết. Cuối cùng, việc đẩy server nên được sử dụng theo quyết định của nhà phát triển. Để biết thêm về cách sử dụng chiến lược đẩy server và tối ưu hóa các ứng dụng web, hãy xem mẫu PRPL do Google phát triển. Để tìm hiểu thêm về các vấn đề có thể xảy ra với quá trình đẩy server , hãy xem bài đăng trên blog của Jake Archibald Quá trình đẩy HTTP / 2 khó khăn hơn tôi nghĩ .

Nén

Một phương pháp phổ biến để tối ưu hóa các ứng dụng web là sử dụng các thuật toán nén để giảm kích thước của các thông điệp HTTP truyền giữa client và server . HTTP / 1.1 và HTTP / 2 đều sử dụng chiến lược này, nhưng có một số vấn đề triển khai trong chiến lược trước đó là cấm nén toàn bộ thông báo. Phần sau đây sẽ thảo luận về lý do tại sao lại như vậy và cách HTTP / 2 có thể đưa ra giải pháp.

HTTP / 1.1

Các chương trình như gzip từ lâu đã được sử dụng để nén dữ liệu được gửi trong các thông điệp HTTP, đặc biệt là để giảm kích thước của các file CSS và JavaScript. Tuy nhiên, thành phần tiêu đề của thư luôn được gửi dưới dạng văn bản thuần túy. Mặc dù mỗi tiêu đề khá nhỏ, gánh nặng của dữ liệu không nén này ngày càng đè nặng lên kết nối khi có nhiều yêu cầu hơn được thực hiện, đặc biệt phạt các ứng dụng web phức tạp, nặng về API, đòi hỏi nhiều tài nguyên khác nhau và do đó có nhiều yêu cầu tài nguyên khác nhau. Ngoài ra, việc sử dụng cookie đôi khi có thể làm cho tiêu đề lớn hơn nhiều, làm tăng nhu cầu về một số loại nén.

Để giải quyết nút cổ chai này, HTTP / 2 sử dụng tính năng nén HPACK để thu nhỏ kích thước của tiêu đề, một chủ đề sẽ được thảo luận kỹ hơn trong phần tiếp theo.

HTTP / 2

Một trong những chủ đề đã xuất hiện nhiều lần trong HTTP / 2 là khả năng sử dụng lớp khung binary để thể hiện khả năng kiểm soát tốt hơn đối với chi tiết tốt hơn. Điều này cũng đúng khi nói đến nén tiêu đề. HTTP / 2 có thể tách tiêu đề khỏi dữ liệu của chúng, dẫn đến một khung tiêu đề và một khung dữ liệu. Sau đó, chương trình nén HTTP / 2 cụ thể HPACK có thể nén khung tiêu đề này. Thuật toán này có thể mã hóa metadata tiêu đề bằng mã hóa Huffman, do đó làm giảm đáng kể kích thước của nó.Ngoài ra, HPACK có thể theo dõi các trường metadata đã truyền tải trước đó và nén thêm chúng theo index được thay đổi động được chia sẻ giữa client và server . Ví dụ: lấy hai yêu cầu sau:

Yêu cầu số 1
method:     GET scheme:     https host:       example.com path:       /academy accept:     /image/jpeg user-agent: Mozilla/5.0 ... 
Yêu cầu số 2
method:     GET scheme:     https host:       example.com path:       /academy/images accept:     /image/jpeg user-agent: Mozilla/5.0 ... 

Các trường khác nhau trong các yêu cầu này, chẳng hạn như method , scheme , host , acceptuser-agent , có cùng giá trị; chỉ có trường path sử dụng một giá trị khác. Do đó, khi gửi Request #2 , client có thể sử dụng HPACK để chỉ gửi các giá trị được lập index cần thiết để cấu trúc lại các trường chung này và mới mã hóa trường path . Khung tiêu đề kết quả sẽ như sau:

Khung tiêu đề cho yêu cầu số 1
method:     GET scheme:     https host:       example.com path:       /academy accept:     /image/jpeg user-agent: Mozilla/5.0 ... 
Khung tiêu đề cho yêu cầu số 2
path:       /academy/images 

Sử dụng HPACK và các phương pháp nén khác, HTTP / 2 cung cấp thêm một tính năng có thể giảm độ trễ client - server .

Kết luận

Như bạn thấy từ phân tích từng điểm này, HTTP / 2 khác với HTTP / 1.1 theo nhiều cách, với một số tính năng cung cấp mức độ kiểm soát cao hơn được dùng để tối ưu hóa hiệu suất ứng dụng web tốt hơn và các tính năng khác chỉ đơn giản là cải thiện giao thức trước đó. Đến đây bạn đã có được quan điểm cấp cao về các biến thể giữa hai giao thức, bạn có thể xem xét các yếu tố như ghép kênh, ưu tiên stream , kiểm soát stream , đẩy server và nén trong HTTP / 2 sẽ ảnh hưởng như thế nào đến bối cảnh thay đổi của phát triển web .

Nếu bạn muốn xem so sánh hiệu suất giữa HTTP / 1.1 và HTTP / 2, hãy xem bản trình diễn này của Google để so sánh các giao thức cho các độ trễ khác nhau. Lưu ý khi bạn chạy thử nghiệm trên máy tính của bạn , thời gian tải trang có thể thay đổi tùy thuộc vào một số yếu tố như băng thông, tài nguyên client và server có sẵn tại thời điểm thử nghiệm, v.v. Nếu bạn muốn nghiên cứu kết quả của thử nghiệm toàn diện hơn, hãy xem bài viết HTTP / 2 - Kiểm tra và phân tích hiệu suất trong thế giới thực . Cuối cùng, nếu bạn muốn khám phá cách xây dựng ứng dụng web hiện đại, bạn có thể làm theo Hướng dẫn cách xây dựng ứng dụng web hiện đại để quản lý thông tin khách hàng với Django và React trên Ubuntu 18.04 hoặc cài đặt server HTTP / 2 của bạn với Hướng dẫn Cách cài đặt Nginx với Hỗ trợ HTTP / 2 trên Ubuntu 16.04 của ta .


Tags:

Các tin liên quan