Pengantar HTTP/2

HTTP/2 akan membuat aplikasi kami lebih cepat, lebih sederhana, dan lebih tangguh, kombinasi yang langka, dengan memungkinkan kami mengurungkan banyak solusi HTTP/1.1 yang sebelumnya dilakukan dalam aplikasi dan mengatasi masalah ini dalam lapisan transport itu sendiri. Yang lebih bagus lagi, API ini juga membuka sejumlah peluang yang sama sekali baru untuk mengoptimalkan aplikasi kita dan meningkatkan performa.

Tujuan utama untuk HTTP/2 adalah mengurangi latensi dengan mengaktifkan multiplexing permintaan dan respons lengkap, meminimalkan overhead protokol melalui kompresi kolom header HTTP yang efisien, serta menambahkan dukungan untuk penentuan prioritas permintaan dan push server. Untuk menerapkan persyaratan ini, ada sejumlah besar dukungan untuk peningkatan protokol lain, seperti kontrol alur baru, penanganan error, dan mekanisme upgrade, tetapi ini adalah fitur paling penting yang harus dipahami dan dimanfaatkan oleh setiap developer web dalam aplikasinya.

HTTP/2 tidak mengubah semantik aplikasi HTTP dengan cara apa pun. Semua konsep inti, seperti metode HTTP, kode status, URI, dan kolom header, tetap berlaku. Sebagai gantinya, HTTP/2 mengubah cara data diformat (dibingkai) dan ditransportasi antara klien dan server, yang keduanya mengelola seluruh proses, dan menyembunyikan semua kompleksitas dari aplikasi kita dalam lapisan framing baru. Akibatnya, semua aplikasi yang ada dapat dikirimkan tanpa modifikasi.

Mengapa tidak HTTP/1.2?

Untuk mencapai sasaran performa yang ditetapkan oleh HTTP Working Group, HTTP/2 memperkenalkan lapisan framing biner baru yang tidak kompatibel dengan server dan klien HTTP/1.x sebelumnya. Oleh karena itu, penambahan versi protokol utama ke HTTP/2.

Dengan demikian, kecuali Anda mengimplementasikan server web (atau klien kustom) dengan menggunakan soket TCP mentah, Anda tidak akan melihat perbedaan apa pun: semua penyesuaian frame tingkat rendah yang baru dilakukan oleh klien dan server atas nama Anda. Satu-satunya perbedaan yang dapat diamati adalah peningkatan performa dan ketersediaan kemampuan baru seperti penentuan prioritas permintaan, kontrol alur, dan push server.

Sejarah singkat SPDY dan HTTP/2

SPDY adalah protokol eksperimental yang dikembangkan di Google dan diumumkan pada pertengahan tahun 2009. Tujuan utamanya adalah mencoba mengurangi latensi pemuatan halaman web dengan mengatasi beberapa batasan performa HTTP/1.1 yang terkenal. Secara khusus, tujuan proyek yang diuraikan ditetapkan sebagai berikut:

  • Menargetkan pengurangan 50% dalam waktu muat halaman (PLT).
  • Hindari kebutuhan atas perubahan apa pun terhadap konten oleh penulis situs.
  • Meminimalkan kompleksitas deployment, dan menghindari perubahan infrastruktur jaringan.
  • Kembangkan protokol baru ini melalui kemitraan dengan komunitas open source.
  • Kumpulkan data performa nyata untuk (membatalkan) protokol eksperimental.

Tidak lama setelah pengumuman awal, Mike Belshe dan Roberto Peon, keduanya {i>software engineer<i} di Google, membagikan hasil, dokumentasi, dan kode sumber pertama mereka untuk implementasi eksperimental protokol SPDY yang baru:

Sejauh ini, kami hanya menguji SPDY dalam kondisi lab. Hasil awalnya sangat menggembirakan: saat kami mendownload 25 situs teratas dari simulasi koneksi jaringan rumah, kami melihat peningkatan performa yang signifikan—halaman dimuat hingga 55% lebih cepat. (Blog Chromium)

Hingga tahun 2012, protokol eksperimental baru ini didukung di Chrome, Firefox, dan Opera, dan sejumlah situs yang berkembang pesat, baik besar (misalnya, Google, Twitter, Facebook) maupun kecil, men-deploy SPDY di dalam infrastruktur mereka. Hasilnya, SPDY berjalan sesuai rencana untuk menjadi standar de facto melalui adopsi industri yang terus berkembang.

Dengan mengamati tren ini, HTTP Working Group (HTTP-WG) memulai upaya baru untuk mengambil pelajaran dari SPDY, membangun dan meningkatkannya, serta mewujudkan standar "HTTP/2" resmi. Piagam baru telah disusun, panggilan terbuka untuk proposal HTTP/2 dilakukan, dan setelah banyak diskusi dalam kelompok kerja, spesifikasi SPDY diadopsi sebagai titik awal untuk protokol HTTP/2 yang baru.

Selama beberapa tahun berikutnya, SPDY dan HTTP/2 terus berevolusi secara paralel, dengan SPDY bertindak sebagai cabang eksperimental yang digunakan untuk menguji fitur dan proposal baru untuk standar HTTP/2. Cara yang terlihat bagus di atas kertas mungkin tidak berfungsi dalam praktiknya, begitu juga sebaliknya. SPDY menawarkan cara untuk menguji dan mengevaluasi setiap proposal sebelum disertakan dalam standar HTTP/2. Pada akhirnya, proses ini berlangsung selama tiga tahun dan menghasilkan banyak draf menengah:

  • Maret 2012: Panggilan untuk proposal untuk HTTP/2
  • November 2012: Draf pertama HTTP/2 (berdasarkan SPDY)
  • Agustus 2014: Draf-17 HTTP/2 dan draf-12 HPACK dipublikasikan
  • Agustus 2014: Panggilan terakhir Working Group untuk HTTP/2
  • Februari 2015: IESG menyetujui draf HTTP/2 dan HPACK
  • Mei 2015: RFC 7540 (HTTP/2) dan RFC 7541 (HPACK) dipublikasikan

Pada awal 2015, IESG meninjau dan menyetujui standar HTTP/2 baru untuk dipublikasikan. Tak lama setelah itu, tim Google Chrome mengumumkan jadwal penghentian penggunaan ekstensi SPDY dan NPN untuk TLS:

Perubahan utama HTTP/2 dari HTTP/1.1 berfokus pada peningkatan performa. Beberapa fitur utama seperti multiplexing, kompresi header, penentuan prioritas, dan negosiasi protokol berevolusi dari pekerjaan yang dilakukan lebih awal, tetapi protokol non-standar bernama SPDY. Chrome telah mendukung SPDY sejak Chrome 6, tetapi karena sebagian besar manfaatnya ada di HTTP/2, kini saatnya untuk menghentikan penggunaan. Kami berencana menghapus dukungan untuk SPDY pada awal tahun 2016, dan juga menghapus dukungan untuk ekstensi TLS bernama NPN dan mendukung ALPN di Chrome pada saat yang sama. Developer server sangat disarankan untuk beralih ke HTTP/2 dan ALPN.

Kami senang telah berkontribusi pada proses standar terbuka yang mengarah ke HTTP/2, dan berharap dapat melihat adopsi yang luas mengingat interaksi industri yang luas terkait standardisasi dan implementasi. (Blog Chromium)

Evolusi bersama SPDY dan HTTP/2 memungkinkan developer server, browser, dan situs untuk mendapatkan pengalaman dunia nyata dengan protokol baru saat sedang dikembangkan. Oleh karena itu, standar HTTP/2 adalah salah satu standar terbaik dan paling banyak diuji secara menyeluruh. Setelah HTTP/2 disetujui oleh IESG, ada puluhan penerapan klien dan server yang telah diuji secara menyeluruh dan siap produksi. Bahkan, hanya beberapa minggu setelah protokol akhir disetujui, banyak pengguna mulai menikmati manfaatnya karena beberapa browser populer (dan banyak situs) men-deploy dukungan HTTP/2 penuh.

Tujuan desain dan teknis

Versi protokol HTTP sebelumnya sengaja didesain untuk kemudahan implementasi: HTTP/0.9 adalah protokol satu baris untuk mem-bootstrap World Wide Web; HTTP/1.0 mendokumentasikan ekstensi populer ke HTTP/0.9 dalam standar informasi; HTTP/1.1 memperkenalkan standar IETF resmi; baca Histori Singkat HTTP. Dengan demikian, HTTP/0.9-1.x memberikan hasil sesuai dengan yang direncanakan: HTTP adalah salah satu protokol aplikasi yang paling banyak diadopsi di Internet.

Sayangnya, kesederhanaan implementasi juga mengorbankan performa aplikasi: klien HTTP/1.x harus menggunakan beberapa koneksi untuk mencapai konkurensi dan mengurangi latensi; HTTP/1.x tidak mengompresi header permintaan dan respons, menyebabkan traffic jaringan yang tidak perlu; HTTP/1.x tidak memungkinkan penentuan prioritas resource yang efektif, sehingga menyebabkan penggunaan koneksi TCP dasar yang buruk; dan sebagainya.

Batasan ini tidak fatal, tetapi karena aplikasi web terus berkembang dalam cakupan, kompleksitas, dan kepentingannya dalam kehidupan sehari-hari, batasan ini menimbulkan beban yang semakin besar pada developer dan pengguna web, yang merupakan celah yang tepat untuk diatasi oleh HTTP/2:

Dengan HTTP/2, penggunaan resource jaringan menjadi lebih efisien dan persepsi latensi berkurang dengan menggunakan kompresi kolom header dan memungkinkan beberapa pertukaran serentak pada koneksi yang sama... Secara khusus, HTTP/2 memungkinkan interleaving pesan permintaan dan respons pada koneksi yang sama dan menggunakan coding yang efisien untuk kolom header HTTP. Hal ini juga memungkinkan penentuan prioritas permintaan, sehingga permintaan yang lebih penting dapat diselesaikan lebih cepat, sehingga meningkatkan performa.

Protokol yang dihasilkan lebih ramah terhadap jaringan karena lebih sedikit koneksi TCP yang dapat digunakan dibandingkan dengan HTTP/1.x. Ini berarti lebih sedikit persaingan dengan alur lain, dan koneksi berdurasi lebih lama, yang pada gilirannya menghasilkan pemanfaatan kapasitas jaringan yang tersedia dengan lebih baik. Terakhir, HTTP/2 juga memungkinkan pemrosesan pesan lebih efisien melalui penggunaan framing pesan biner. (Hypertext Transfer Protocol versi 2, Draf 17)

Penting untuk diperhatikan bahwa HTTP/2 bersifat memperluas, bukan menggantikan standar HTTP sebelumnya. Semantik aplikasi HTTP sama, dan tidak ada perubahan yang dilakukan pada fungsi yang ditawarkan atau konsep inti seperti metode HTTP, kode status, URI, dan kolom header. Perubahan ini secara eksplisit berada di luar cakupan upaya HTTP/2. Meskipun demikian, meskipun API level tinggi tetap sama, penting untuk memahami bagaimana perubahan tingkat rendah mengatasi keterbatasan performa protokol sebelumnya. Mari kita ikuti tur singkat tentang lapisan framing biner dan fitur-fiturnya.

Lapisan framing biner

Inti dari semua peningkatan performa HTTP/2 adalah lapisan framing biner baru, yang menentukan cara pesan HTTP dienkapsulasi dan ditransfer antara klien dan server.

Lapisan frame biner HTTP/2

"Lapisan" mengacu pada pilihan desain untuk memperkenalkan mekanisme encoding baru yang dioptimalkan antara antarmuka soket dan HTTP API yang lebih tinggi yang diekspos ke aplikasi kita: semantik HTTP, seperti kata kerja, metode, dan header, tidak terpengaruh, tetapi cara encoding saat dalam pengiriman berbeda. Tidak seperti protokol HTTP/1.x teks biasa yang dibatasi baris baru, semua komunikasi HTTP/2 dibagi menjadi pesan dan frame yang lebih kecil, yang masing-masing dienkode dalam format biner.

Akibatnya, baik klien maupun server harus menggunakan mekanisme encoding biner yang baru untuk memahami satu sama lain: klien HTTP/1.x tidak akan memahami server khusus HTTP/2, dan sebaliknya. Untungnya, aplikasi kami tetap tidak mengetahui semua perubahan ini, karena klien dan server melakukan semua pekerjaan penyesuaian frame yang diperlukan atas nama kami.

Streaming, pesan, dan bingkai

Pengenalan mekanisme framing biner baru mengubah cara data dipertukarkan antara klien dan server. Untuk menggambarkan proses ini, mari kita familier dengan terminologi HTTP/2:

  • Stream: Alur dua arah byte dalam koneksi yang dibuat, yang dapat membawa satu atau beberapa pesan.
  • Pesan: Urutan lengkap frame yang dipetakan ke pesan respons atau permintaan logis.
  • Frame: Unit komunikasi terkecil di HTTP/2, masing-masing berisi header frame, yang minimal mengidentifikasi streaming yang mencakup frame.

Hubungan istilah-istilah ini dapat diringkas sebagai berikut:

  • Semua komunikasi dilakukan melalui satu koneksi TCP yang dapat membawa sejumlah aliran dua arah.
  • Tiap aliran data memiliki ID unik dan informasi prioritas opsional yang digunakan untuk membawa pesan dua arah.
  • Setiap pesan adalah pesan HTTP logis, seperti permintaan atau respons, yang terdiri dari satu atau beberapa frame.
  • {i>Frame<i} adalah unit komunikasi terkecil yang membawa jenis data tertentu—misalnya, Header HTTP, payload pesan, dan lain-lain. Frame dari stream yang berbeda dapat di-intersheet, lalu disusun ulang melalui ID streaming yang disematkan di header setiap frame.

Streaming, pesan, dan frame HTTP/2

Singkatnya, HTTP/2 memecah komunikasi protokol HTTP menjadi pertukaran frame yang berenkode biner, yang kemudian dipetakan ke pesan yang termasuk dalam aliran data tertentu, yang semuanya di-multiplex dalam satu koneksi TCP. Ini adalah dasar yang memungkinkan semua fitur lain dan pengoptimalan performa yang disediakan oleh protokol HTTP/2.

Multiplexing permintaan dan respons

Dengan HTTP/1.x, jika klien ingin membuat beberapa permintaan paralel untuk meningkatkan performa, beberapa koneksi TCP harus digunakan (lihat Menggunakan Beberapa Koneksi TCP). Perilaku ini merupakan konsekuensi langsung dari model pengiriman HTTP/1.x, yang memastikan bahwa hanya satu respons yang dapat dikirim pada satu waktu (antrean respons) per koneksi. Lebih buruk lagi, hal ini juga menyebabkan pemblokiran head-of-line dan penggunaan koneksi TCP yang mendasarinya yang tidak efisien.

Lapisan framing biner baru di HTTP/2 menghapus batasan ini, dan memungkinkan multiplexing permintaan dan respons penuh, dengan memungkinkan klien dan server memecah pesan HTTP ke dalam frame independen, menyisipkannya, lalu menyusun ulang pesan di ujung yang lain.

Multiplexing permintaan dan respons HTTP/2 dalam koneksi bersama

Snapshot merekam beberapa streaming yang berlangsung dalam koneksi yang sama. Klien mengirimkan frame DATA (aliran 5) ke server, sedangkan server mentransmisikan urutan interleaf frame ke klien untuk aliran 1 dan 3. Akibatnya, ada tiga aliran paralel yang sedang berjalan.

Kemampuan untuk memecah pesan HTTP menjadi beberapa frame independen, menyisipkannya ke dalam pesan, lalu menyusunnya ulang di sisi lain adalah satu-satunya peningkatan terpenting dari HTTP/2. Bahkan, versi ini menghadirkan efek riak dari berbagai manfaat performa di seluruh stack semua teknologi web, yang memungkinkan kami untuk:

  • Melakukan interleft beberapa permintaan secara paralel tanpa memblokir salah satunya.
  • Melakukan interleft beberapa respons secara paralel tanpa memblokir salah satunya.
  • Menggunakan satu koneksi untuk mengirim beberapa permintaan dan respons secara paralel.
  • Hapus solusi HTTP/1.x yang tidak perlu (lihat Mengoptimalkan untuk HTTP/1.x, seperti file gabungan, sprite gambar, dan sharding domain).
  • Berikan waktu muat halaman yang lebih rendah dengan menghilangkan latensi yang tidak perlu dan meningkatkan pemanfaatan kapasitas jaringan yang tersedia.
  • Dan masih banyak lagi...

Lapisan framing biner baru di HTTP/2 menyelesaikan masalah pemblokiran head-of-line yang ditemukan di HTTP/1.x dan menghilangkan kebutuhan akan beberapa koneksi untuk memungkinkan pemrosesan paralel serta pengiriman permintaan dan respons. Hasilnya, hal ini membuat aplikasi kami menjadi lebih cepat, lebih sederhana, dan lebih murah untuk di-deploy.

Penentuan prioritas streaming

Setelah pesan HTTP dapat dibagi menjadi banyak frame individual, dan kami mengizinkan frame dari beberapa aliran data untuk di-multiplex, urutan frame di-inter permainankan dan dikirim oleh klien dan server akan menjadi pertimbangan performa yang penting. Untuk memfasilitasi hal ini, standar HTTP/2 memungkinkan setiap aliran data memiliki bobot dan dependensi terkait:

  • Setiap aliran data dapat diberi bobot bilangan bulat antara 1 sampai 256.
  • Setiap aliran data dapat diberi dependensi eksplisit pada aliran data lainnya.

Kombinasi dependensi dan bobot streaming memungkinkan klien membuat dan mengomunikasikan "hierarki prioritas" yang menyatakan cara yang lebih disukai dalam menerima respons. Oleh karena itu, server dapat menggunakan informasi ini untuk memprioritaskan stream processing dengan mengontrol alokasi CPU, memori, dan resource lainnya, dan setelah data respons tersedia, alokasi bandwidth untuk memastikan pengiriman respons prioritas tinggi yang optimal kepada klien.

Dependensi dan bobot streaming HTTP/2

Dependensi stream dalam HTTP/2 dideklarasikan dengan mereferensikan ID unik stream lain sebagai induknya; jika ID dihilangkan, stream dianggap bergantung pada "root stream". Mendeklarasikan dependensi aliran data menunjukkan bahwa, jika memungkinkan, aliran data induk harus dialokasikan resource sebelum dependensinya. Dengan kata lain, "Harap proses dan kirimkan respons D sebelum respons C".

Streaming yang memiliki induk yang sama (dengan kata lain, stream yang seinduk) harus dialokasikan resource secara proporsional dengan bobotnya. Misalnya, jika stream A memiliki bobot 12 dan satu saudaranya B memiliki bobot 4, maka untuk menentukan proporsi resource yang harus diterima oleh setiap stream tersebut:

  1. Jumlahkan semua bobot: 4 + 12 = 16
  2. Bagi setiap bobot aliran dengan bobot total: A = 12/16, B = 4/16

Dengan demikian, aliran data A akan menerima satu per tiga dan aliran data B harus menerima seperempat dari resource yang tersedia; aliran B harus menerima sepertiga dari resource yang dialokasikan ke aliran A. Mari kita lihat beberapa contoh langsung pada gambar di atas. Dari kiri ke kanan:

  1. Baik stream A maupun B tidak menentukan dependensi induk dan disebut bergantung pada "stream root" implisit; A memiliki bobot 12, dan B memiliki bobot 4. Dengan demikian, berdasarkan bobot proporsional: aliran B akan menerima sepertiga dari resource yang dialokasikan ke aliran A.
  2. Stream D bergantung pada root stream; C bergantung pada D. Dengan demikian, D harus menerima alokasi resource penuh sebelum C. Bobotnya tidak penting karena dependensi C mengkomunikasikan preferensi yang lebih kuat.
  3. Stream D harus menerima alokasi resource penuh sebelum C; C harus menerima alokasi penuh resource sebelum A dan B; stream B harus menerima sepertiga resource yang dialokasikan ke stream A.
  4. Stream D harus menerima alokasi resource penuh sebelum E dan C; E dan C harus menerima alokasi yang sama sebelum A dan B; A dan B harus menerima alokasi proporsional berdasarkan bobotnya.

Seperti yang diilustrasikan oleh contoh di atas, kombinasi bobot dan dependensi streaming memberikan bahasa ekspresif untuk penentuan prioritas resource, yang merupakan fitur penting untuk meningkatkan performa penjelajahan karena kami memiliki banyak jenis resource dengan dependensi dan bobot yang berbeda. Yang lebih bagus lagi, protokol HTTP/2 juga memungkinkan klien memperbarui preferensi ini kapan saja, yang memungkinkan pengoptimalan lebih lanjut di browser. Dengan kata lain, kita dapat mengubah dependensi dan mengalokasikan ulang bobot sebagai respons terhadap interaksi pengguna dan sinyal lainnya.

Satu koneksi per origin

Dengan menerapkan mekanisme framing biner yang baru, HTTP/2 tidak lagi memerlukan beberapa koneksi TCP ke streaming multipleks secara paralel; setiap streaming dibagi menjadi banyak frame, yang dapat di-interleaf dan diprioritaskan. Akibatnya, semua koneksi HTTP/2 bersifat persisten, dan hanya satu koneksi per origin yang diperlukan, yang menawarkan berbagai manfaat performa.

Untuk SPDY dan HTTP/2, fitur utamanya adalah multiplexing arbitrer pada satu saluran yang dikontrol kemacetan. Menakjubkan betapa pentingnya hal ini dan seberapa baik cara kerjanya. Salah satu metrik hebat yang saya nikmati adalah fraksi koneksi yang dibuat yang hanya membawa satu transaksi HTTP (sehingga transaksi tersebut menanggung semua overhead). Untuk HTTP/1, 74% koneksi aktif kita hanya membawa satu transaksi—koneksi persisten tidak membantu seperti yang kita semua inginkan. Namun di HTTP/2 angka itu turun menjadi 25%. Itu adalah kemenangan besar untuk pengurangan {i>overhead<i}. (HTTP/2 adalah Live di Firefox, Patrick McManus)

Sebagian besar transfer HTTP singkat dan padat, sedangkan TCP dioptimalkan untuk transfer data massal berdurasi panjang. Dengan menggunakan kembali koneksi yang sama, HTTP/2 dapat mengefisienkan penggunaan setiap koneksi TCP, dan juga secara signifikan mengurangi keseluruhan overhead protokol. Selain itu, penggunaan koneksi yang lebih sedikit akan mengurangi jejak memori dan pemrosesan di sepanjang jalur koneksi lengkap (dengan kata lain, klien, perantara, dan server asal). Hal ini mengurangi biaya operasional secara keseluruhan serta meningkatkan pemanfaatan dan kapasitas jaringan. Hasilnya, peralihan ke HTTP/2 tidak hanya mengurangi latensi jaringan, tetapi juga membantu meningkatkan throughput dan mengurangi biaya operasional.

Kontrol alur

Kontrol alur adalah mekanisme untuk mencegah pengirim membebani penerima dengan data yang mungkin tidak diinginkan atau tidak dapat diproses: penerima mungkin sibuk, memiliki beban berat, atau mungkin hanya bersedia mengalokasikan resource dalam jumlah tetap untuk streaming tertentu. Misalnya, klien mungkin telah meminta streaming video berukuran besar dengan prioritas tinggi, tetapi pengguna telah menjeda video dan sekarang klien ingin menjeda atau membatasi pengirimannya dari server untuk menghindari pengambilan dan buffering data yang tidak perlu. Selain itu, server proxy mungkin memiliki koneksi downstream yang cepat dan koneksi upstream yang lambat. Selain itu, server proxy juga ingin mengatur seberapa cepat downstream mengirimkan data agar sesuai dengan kecepatan upstream untuk mengontrol penggunaan resourcenya; dan seterusnya.

Apakah persyaratan di atas mengingatkan Anda tentang kontrol alur TCP? Seharusnya, karena masalahnya identik (lihat Kontrol Alur). Namun, karena streaming HTTP/2 di-multiplex dalam satu koneksi TCP, kontrol alur TCP tidak cukup terperinci, dan tidak menyediakan API tingkat aplikasi yang diperlukan untuk mengatur pengiriman streaming individual. Untuk mengatasi hal ini, HTTP/2 menyediakan sekumpulan elemen penyusun sederhana yang memungkinkan klien dan server menerapkan kontrol alur tingkat streaming dan tingkat koneksinya sendiri:

  • Kontrol alur bersifat terarah. Setiap penerima dapat memilih untuk menyetel ukuran jendela yang diinginkan untuk setiap streaming dan seluruh koneksi.
  • Kontrol alur berbasis kredit. Setiap penerima mengiklankan koneksi awal dan jendela kontrol alur aliran data (dalam byte), yang dikurangi setiap kali pengirim memunculkan frame DATA dan bertambah melalui frame WINDOW_UPDATE yang dikirim oleh penerima.
  • Kontrol alur tidak dapat dinonaktifkan. Saat koneksi HTTP/2 dibuat, klien dan server bertukar frame SETTINGS, yang menetapkan ukuran jendela kontrol alur di kedua arah. Nilai default jendela kontrol alur ditetapkan ke 65.535 byte, tetapi penerima dapat menetapkan ukuran jendela maksimum yang besar (2^31-1 byte) dan mempertahankannya dengan mengirimkan frame WINDOW_UPDATE setiap kali data diterima.
  • Kontrol alur bersifat hop demi hop, bukan end-to-end. Artinya, perantara dapat menggunakannya untuk mengontrol penggunaan resource dan menerapkan mekanisme alokasi resource berdasarkan kriteria dan heuristiknya sendiri.

HTTP/2 tidak menentukan algoritma tertentu untuk menerapkan kontrol alur. Sebaliknya, LLM menyediakan elemen penyusun sederhana dan menunda implementasi ke klien dan server, yang dapat menggunakannya untuk mengimplementasikan strategi kustom untuk mengatur penggunaan dan alokasi resource, serta mengimplementasikan kemampuan pengiriman baru yang dapat membantu meningkatkan performa nyata dan yang dirasakan (lihat Kecepatan, Performa, dan Persepsi Manusia) dari aplikasi web kami.

Misalnya, kontrol alur lapisan aplikasi memungkinkan browser mengambil sebagian resource tertentu, menangguhkan pengambilan dengan mengurangi jendela kontrol alur aliran data menjadi nol, lalu melanjutkannya nanti. Dengan kata lain, hal ini memungkinkan browser mengambil pratinjau atau pemindaian pertama gambar, menampilkannya, dan memungkinkan pengambilan prioritas tinggi lainnya dapat dilanjutkan, serta melanjutkan pengambilan setelah resource yang lebih penting selesai dimuat.

Push server

Fitur baru yang canggih dari HTTP/2 adalah kemampuan server untuk mengirim beberapa respons untuk satu permintaan klien. Artinya, selain respons terhadap permintaan asli, server dapat mengirim resource tambahan ke klien (Gambar 12-5), tanpa klien harus meminta setiap resource secara eksplisit.

Server memulai streaming baru (promise) untuk resource push

Mengapa kita membutuhkan mekanisme seperti itu dalam browser? Aplikasi web umumnya terdiri dari lusinan resource, yang semuanya ditemukan oleh klien dengan memeriksa dokumen yang disediakan oleh server. Dengan demikian, mengapa tidak menghilangkan latensi tambahan dan membiarkan server mengirim resource terkait terlebih dahulu? Server sudah mengetahui resource yang akan diperlukan klien; yaitu push server.

Bahkan, jika Anda pernah membuat CSS, JavaScript, atau aset lain secara inline melalui URI data (lihat Resource Inlining), berarti Anda sudah memiliki pengalaman langsung dengan server push. Dengan menyisipkan resource ke dalam dokumen secara manual, kita sebenarnya mendorong resource tersebut ke klien, tanpa menunggu klien memintanya. Dengan HTTP/2, kita dapat mencapai hasil yang sama, tetapi dengan manfaat performa tambahan. Resource push dapat berupa:

  • Di-cache oleh klien
  • Digunakan kembali di halaman yang berbeda
  • Di-multiplex bersama resource lainnya
  • Diprioritaskan oleh server
  • Ditolak oleh klien

101 PROMISE_PUSH

Semua aliran data push server dimulai melalui frame PUSH_PROMISE, yang menandakan intent server untuk mendorong resource yang dijelaskan ke klien dan harus dikirimkan sebelum data respons yang meminta resource yang didorong. Urutan pengiriman ini sangat penting: klien perlu mengetahui resource mana yang ingin didorong oleh server guna menghindari pembuatan permintaan duplikat untuk resource ini. Strategi yang paling sederhana untuk memenuhi persyaratan ini adalah mengirim semua frame PUSH_PROMISE, yang hanya berisi header HTTP resource yang dijanjikan, sebelum respons induk (dengan kata lain, frame DATA).

Setelah menerima frame PUSH_PROMISE, klien memiliki opsi untuk menolak aliran data (melalui frame RST_STREAM) jika diinginkan. (Hal ini dapat terjadi misalnya karena resource sudah ada di cache.) Ini merupakan peningkatan penting pada HTTP/1.x. Sebaliknya, penggunaan inline resource, yang merupakan "pengoptimalan" populer untuk HTTP/1.x, setara dengan "forced push": klien tidak dapat memilih untuk tidak ikut, membatalkannya, atau memproses resource inline satu per satu.

Dengan HTTP/2, klien tetap memegang kendali penuh atas penggunaan server push. Klien dapat membatasi jumlah stream yang didorong secara serentak; menyesuaikan jendela kontrol alur awal untuk mengontrol jumlah data yang dikirim saat streaming pertama kali dibuka; atau menonaktifkan push server sepenuhnya. Preferensi ini dikomunikasikan melalui frame SETTINGS pada awal koneksi HTTP/2 dan dapat diperbarui kapan saja.

Tidak seperti resource inline, setiap resource yang didorong adalah stream yang memungkinkannya untuk di-multiplex, diprioritaskan, dan diproses satu per satu oleh klien. Satu-satunya pembatasan keamanan, sebagaimana diterapkan oleh browser, adalah bahwa resource yang dikirim harus mematuhi kebijakan origin yang sama: server harus bersifat otoritatif untuk konten yang disediakan.

Kompresi header

Setiap transfer HTTP membawa sekumpulan header yang mendeskripsikan resource yang ditransfer dan propertinya. Di HTTP/1.x, metadata ini selalu dikirim sebagai teks biasa dan menambahkan overhead 500–800 byte per transfer, dan terkadang lebih banyak kilobyte jika cookie HTTP digunakan. (Lihat Measurement and Controlling Protocol Overhead .) Untuk mengurangi overhead ini dan meningkatkan performa, HTTP/2 mengompresi metadata header permintaan dan respons menggunakan format kompresi HPACK yang menggunakan dua teknik yang sederhana tetapi efektif:

  1. API ini memungkinkan kolom header yang ditransmisikan dienkode melalui kode Huffman statis, sehingga mengurangi ukuran transfer masing-masing.
  2. Klien dan server harus mempertahankan dan memperbarui daftar terindeks dari kolom header yang sebelumnya terlihat (dengan kata lain, membuat konteks kompresi bersama), yang kemudian digunakan sebagai referensi untuk mengenkode nilai yang dikirim sebelumnya secara efisien.

Dengan coding Huffman, setiap nilai dapat dikompresi saat ditransfer, dan daftar terindeks dari nilai yang ditransfer sebelumnya memungkinkan kita mengenkode nilai duplikat dengan mentransfer nilai indeks yang dapat digunakan untuk secara efisien mencari dan merekonstruksi kunci dan nilai header yang lengkap.

HPACK: Kompresi Header untuk HTTP/2

Sebagai salah satu pengoptimalan lebih lanjut, konteks kompresi HPACK terdiri dari tabel statis dan dinamis: tabel statis ditentukan dalam spesifikasi dan menyediakan daftar kolom header HTTP umum yang kemungkinan akan digunakan oleh semua koneksi (misalnya, nama header yang valid); tabel dinamis awalnya kosong dan diperbarui berdasarkan nilai yang dipertukarkan dalam koneksi tertentu. Hasilnya, ukuran setiap permintaan dikurangi dengan menggunakan coding Huffman statis untuk nilai yang belum pernah dilihat sebelumnya, dan substitusi indeks untuk nilai yang sudah ada dalam tabel statis atau dinamis di setiap sisi.

Keamanan dan performa HPACK

Versi awal HTTP/2 dan SPDY menggunakan zlib, dengan kamus khusus, untuk mengompresi semua header HTTP. Versi ini menghasilkan pengurangan ukuran data header yang ditransfer sebesar 85% hingga 88%, dan peningkatan yang signifikan pada latensi waktu muat halaman:

Pada link DSL bandwidth lebih rendah, dengan link upload hanya 375 Kbps, kompresi header permintaan khususnya, menyebabkan peningkatan waktu muat halaman yang signifikan untuk situs tertentu (dengan kata lain, situs yang mengeluarkan permintaan resource dalam jumlah besar). Kami menemukan pengurangan waktu muat halaman sebesar 45–1142 md hanya karena kompresi header. (Laporan SPDY, chromium.org)

Namun, pada musim panas tahun 2012, serangan keamanan "CRIME" dipublikasikan terhadap algoritma kompresi TLS dan SPDY, yang dapat mengakibatkan pembajakan sesi. Hasilnya, algoritma kompresi zlib diganti dengan HPACK yang dirancang khusus untuk: mengatasi masalah keamanan yang ditemukan, efisien dan mudah diterapkan dengan benar, dan tentu saja, memungkinkan kompresi metadata header HTTP yang baik.

Untuk mengetahui detail selengkapnya tentang algoritme kompresi HPACK, lihat IETF HPACK - Kompresi Header untuk HTTP/2.

Bacaan lebih lanjut