TCP BBR: Cara cepat dan mudah untuk mempercepat pemuatan halaman. Laporan Yandex

Protokol tingkat aplikasi modern menggunakan multiplexing untuk mempercepat transmisi data, yang meningkatkan persyaratan untuk keandalan saluran. Pada konferensi YaTalks Alexander Gryanko phasmamemberi tahu bagaimana kami mempercepat pemuatan halaman pada saluran dengan packet loss tinggi menggunakan protokol HTTP / 2 dan TCP BBR sebagai contoh.



- Hai. Saya Sasha, saya bekerja di Yandex, selama tiga tahun terakhir saya telah mengembangkan penyeimbang beban L7. Saya akan memberi tahu Anda tentang cara cepat dan mudah untuk mempercepat jaringan Anda. Kita akan mulai dari tingkat ketujuh, HTTP, dan turun ke tingkat keempat, TCP. Hari ini kita hanya akan berbicara tentang dua tingkat ini dan membahasnya secara mendetail.



Dalam delapan tahun terakhir saya telah melakukan lebih banyak pengembangan backend, dan kemungkinan besar pengetahuan saya tetap pada level AngularJS di versi pertama. Anda mungkin lebih tahu dari saya bagaimana semuanya bekerja. Anda telah mengoptimalkan semuanya, mengompresi semuanya, dan di sini saya tidak dapat memberi tahu Anda apa pun.



Tetapi saya dapat menyarankan Anda tentang cara mempercepat jaringan Anda dengan mengoptimalkan server itu sendiri, sistem operasi itu sendiri.







Untuk mempercepat sesuatu, Anda membutuhkan metrik. Dalam hal ini, kami menggunakan yang berikut ini: waktu rata-rata hingga byte pertama menunjukkan seberapa cepat lapisan TCP, dan metrik kedua adalah waktu untuk menerima HTML dari byte pertama. Kami bereksperimen, mengukur metrik kami, dan setelah menyalakan BBR, percepatan kami sekitar sepuluh persen.







Untuk memahami apa itu sepuluh persen, kita beralih ke nilai absolut, yaitu 66 milidetik. Jika Anda membuka game multiplayer online favorit Anda, Ping ke server Eropa Barat akan berdurasi sekitar 60-70 milidetik.



Bagaimana melakukannya dengan cepat



Semua server kami dikelola menggunakan protokol kendali jarak jauh, dalam hal ini SSH. Jika Anda belum menemukan SSH, Anda dapat meminta administrator sistem untuk mengonfigurasi server Anda. Saya akan memberitahu Anda bagaimana meyakinkan dia untuk melakukan ini.







Apa itu BBR? Ini adalah salah satu algoritme yang memungkinkan kita mengontrol bagaimana paket masuk ke jaringan. Dan itu dikonfigurasi dengan dua parameter berikut. Yang pertama adalah mengatur penjadwal paket ke FQ, lalu saya akan memberi tahu Anda mengapa Anda harus menggunakan FQ. Yang kedua adalah dimasukkannya pengendalian kemacetan itu sendiri, yaitu BBR itu sendiri.



Sepertinya di sinilah kita bisa mengakhiri. Namun kenyataannya, ada banyak jebakan, dan kemungkinan besar, sysadmin Anda tidak akan hanya mengaktifkan BBR di server. Oleh karena itu, kami akan melangkah lebih jauh.



HTTP / 2 dan multiplexing



Kami akan mulai dari level 7, yang merupakan HTTP, dan perlahan-lahan mulai meninjau protokol kami.







Kami akan mulai dengan browser yang kami gunakan setiap hari. Kami melihat konsol pengembang web. Konsol memiliki bidang yang menarik bagi kami - protokol.



Dalam kasus kami, protokolnya adalah HTTP / 1 dan HTTP / 2. Ada juga protokol HTTP / 3, yang didasarkan pada protokol QUIC dari Google. Tetapi hari ini kami tidak akan kembali ke sana, karena masih dalam pengembangan, belum sepenuhnya disetujui. Mari kembali ke HTTP / 1.







Di slide, kami melihat utilitas Wireshark, yang memungkinkan kami menganalisis paket kami, cara kami berinteraksi dengan jaringan. Kami melihat bahwa satu bidang disorot dengan warna hijau. Ini adalah permintaan HTTP kami. Di bawah ini kita dapat melihat byte, bagaimana mereka akan disajikan di jaringan.







Seperti apa HTTP / 1 di kehidupan nyata? Ini adalah protokol yang cukup sederhana. Ini sepenuhnya berbasis teks, yaitu, kami hanya menulis teks dan mengirimkannya ke jaringan. Karakter kami dikodekan dengan nilai heksadesimal khusus. Di sebelah kanan adalah tabel ASCII, bagian kecil sehingga Anda dapat menavigasi.



Kami memiliki bagian pertama berupa header, yang dipisahkan oleh karakter ā€œ\ r \ n \ r \ nā€ dari tubuh kami. Kami hanya meminta sumber daya biasa di sini dengan metode GET, jadi permintaan ini tidak akan memiliki badan. Dan kita melihat bahwa byte kira-kira mirip dengan yang ada di tabel ASCII. Kami meminta beberapa jenis JS, beberapa jenis sumber daya. Ada juga tajuk Host yang menunjukkan domain tempat kami bekerja saat ini. Dan - beberapa set header tambahan. Mereka bisa custom, Anda bisa menggunakan apapun.







HTTP / 2 adalah protokol yang lebih kompleks. Ini adalah biner, dan unit terkecil dari pertukaran informasi adalah bingkai. Ada banyak kasus khusus, jenis khusus dari bingkai ini. Anda dapat melihat di slide bahwa mereka disorot.







Kita juga bisa mengamati di baris pertama bahwa dua frame bisa muat dalam satu paket sekaligus. Kami tidak akan memikirkan frame apa yang ada, ada beberapa di antaranya. Dalam hal ini, kita akan tertarik dengan bingkai header, karena itu hanya memungkinkan kita untuk meminta sumber daya. Saya sedikit terlibat dalam pengembangan Wireshark, membantu meningkatkannya di bidang ini.



Kami melihat bahwa ada permintaan get. Kami melihat bahwa di tengah ada representasi tekstual dari permintaan get ini. Tetapi di kolom kanan kita hanya melihat satu byte yang dialokasikan, dan itu akan menjadi metode get ini. Selanjutnya, saya akan menjelaskan mengapa ini terjadi.



Selanjutnya, kami memiliki header jalur, yang menunjukkan jalur ke sumber daya, ke JS kami, yang akan kami minta. Dan ada satu set beberapa tajuk tambahan yang juga akan hadir dalam permintaan kami.



Jadi mengapa byte kita di jaringan tidak sama dengan bagaimana semua ini digambar dalam gambar kita? Faktanya adalah bahwa Wireshark menunjukkan kepada kita hasil akhirnya, bagaimana dia menerjemahkan semuanya. Dan di jaringan, byte ini, header ini, akan dikompresi dengan format HPACK khusus. Lebih detail lebih baik untuk berkenalan di Internet. Carilah informasi, itu didokumentasikan dengan baik.



Mari kembali ke gigitan kita. Ada bidang khusus - pengenal konten. Ini menunjukkan sumber daya mana yang saat ini bekerja dengan bingkai ini. Dalam hal ini, kami mengirim bingkai pertama, menerima data. Ketika server memberi kita byte konten itu sendiri, bingkai data sudah akan digunakan.







Protokol HTTP / 1 dan HTTP / 2 kami sangat berbeda. Kami telah berbicara tentang fakta bahwa HTTP / 1 adalah protokol teks, dan HTTP / 2 adalah protokol biner, yang berfungsi menggunakan bingkai.



HTTP / 1 dalam kasus permintaan dalam bentuk koneksi tunggal akan mengembalikan hasil yang tidak diketahui, tergantung pada implementasi cara pengembang server web menulisnya. Artinya, jika kita membuat dua permintaan dalam satu koneksi, kemungkinan besar, respons untuk permintaan pertama atau kedua akan dikembalikan. Untuk melakukannya, untuk memuat sumber daya secara paralel, browser membuat beberapa koneksi, biasanya sekitar enam koneksi, dan memuat sumber daya secara paralel.



HTTP / 2, pada gilirannya, menggunakan satu koneksi. Artinya, ini mengatur koneksi, dan di dalamnya memuat semua data yang diperlukan melalui bingkai. Teknik mengemas banyak sumber daya ke dalam satu koneksi disebut multiplexing.



Jelas dari cara kerja koneksi kami: jika terjadi kehilangan paket di salah satu koneksi, HTTP / 1 akan bekerja lebih baik. Kemungkinan besar, kami tidak akan menyentuh koneksi lain, mereka akan terus memuat dengan kecepatan yang sama. Dan dalam kasus HTTP / 2, jika paket kami hilang, pemuatan semua sumber daya mulai melambat.







Tampaknya HTTP / 2 lebih buruk, juga sensitif terhadap kehilangan paket. Faktanya, saat kami membuat masing-masing dari enam koneksi ini, kami melakukan operasi berikut.



Jenis klien dan server membangun koneksi yang andal, koneksi TCP. Kami mengirim dua paket dari klien ke server, dan satu paket dikirim dari sisi server ke klien. Jadi, kami sepertinya mengatakan bahwa kami siap mentransfer data. Ini, tentu saja, menciptakan sumber daya overhead, kita dapat melakukannya untuk waktu yang lama.







Ada juga enkripsi. Jika Anda melihat browser Anda sekarang, kemungkinan besar Anda akan melihat ikon gembok. Banyak orang menyebutnya SSL, tetapi sebenarnya bukan SSL. Ini TLS. SSL sudah lama kedaluwarsa, praktis tidak didukung, dan harus ditinggalkan.



TLS juga memiliki pertukaran paket. Artinya, kami, seperti dalam kasus jabat tangan TCP, menetapkan status tertentu, setelah itu kami dapat terus bekerja. Pada titik ini kita juga bisa melakukan optimasi, tapi browser belum mendukung hal-hal yang sudah kita aktifkan dari sisi server. Kami akan menunggu semua orang untuk menyalakannya.







Suatu ketika, HTTP / 1 mencoba memecahkan masalah pemuatan sumber daya secara bersamaan. RFC memilikinya. Dan pada suatu waktu, mereka menerapkan pipelining. Karena kompleksitas implementasi, Internet Explorer tidak mendukungnya, sedangkan Firefox dan Chrome mendukungnya, tetapi dukungan telah menurun seiring waktu.







Masing-masing dari enam koneksi yang telah kita buat, pada kenyataannya, tidak akan ditutup. Artinya, mereka akan terus bekerja dengan cara yang sama seperti sebelumnya. Untuk ini, teknik seperti Keep-Alive digunakan. Artinya, kami membuat koneksi yang andal ke server tertentu dan terus bekerja.



Pada level HTTP, ini dikontrol oleh header. Dalam hal ini, ini adalah koneksi. Dan pada tingkat TCP, kita sudah akan menggunakan sistem operasi itu sendiri, yang akan memutuskan apa yang harus kita lakukan.







Ada masalah lain dengan HTTP / 2 juga. Di HTTP / 2, kita dapat memprioritaskan paket dan mengirim lebih banyak data yang dibutuhkan dengan lebih cepat. Dalam hal ini, saat kami mencoba mengirim banyak data sekaligus, buffer di server mungkin meluap. Kemudian paket dengan prioritas yang lebih tinggi akan melambat dan ditempatkan di akhir antrian.



Kehilangan paket diamati. Mereka memperlambat pemuatan kami, dan pemblokiran ini disebut pemblokiran Head-of-line.



Bagaimana TCP Memecahkan Masalah Kehilangan Paket



Sekarang kita akan berbicara tentang TCP, yaitu lapisan keempat kita. Dalam sepuluh menit berikutnya, saya akan membahas cara kerja TCP.







Saat kami berkunjung, kami meminta seseorang untuk membagikan garam. Ketika seseorang memberi kita garam, kita memastikan bahwa garam itu telah mencapai kita. Dalam hal ini, kami juga mengambil segmen, mengirimkannya, dan menunggu konfirmasi. Kami mengirimkan lagi. Dan jika ada yang rugi, maka segmen ini kami teruskan dan alhasil diserahkan kepada kami. Teknik pengiriman satu segmen ini disebut Berhenti dan tunggu.



Namun jaringan kami telah meningkat pesat selama 30 tahun terakhir. Mungkin sebagian dari Anda ingat dialup, Internet dalam megabyte. Sekarang, Anda mungkin sudah dapat menghubungkan internet gigabit di rumah.



Juga, dalam hal ini, kita dapat mulai mengirim beberapa paket sekaligus. Dalam contoh kami, ada tiga di antaranya. Kami mengirimkan window dalam bentuk tiga paket dan menunggu semuanya untuk dikonfirmasi.



Jika terjadi kehilangan paket, kami dapat mulai meneruskan kembali semua paket, mulai dari kerugian pertama kami. Teknik ini disebut Go-Back N. Jika tidak, kita dapat mulai melacak semua paket dan hanya meneruskan yang hilang. Teknik ini disebut Pengulangan Selektif. Lebih mahal di sisi server. Saat kami menyiapkan slide, butuh waktu lama untuk memikirkan bagaimana cara menyajikannya. Saya sendiri bingung di dalamnya, dan karena itu muncul dengan analogi seperti itu.







Ada pipa yang diketahui oleh kita semua yang menjadi tempat air mengalir. Pipa-pipa tersebut memiliki diameter yang berbeda-beda, di suatu tempat dapat lebih tipis, dan dalam hal ini titik tersempit hanya dengan hasil maksimum kami. Kami tidak akan dapat menuangkan lebih banyak air daripada yang dimungkinkan oleh kemacetan ini.



Kami akan mencoba menembak bola dari kiri ke kanan. Di sisi kanan, kami akan memastikan bahwa bola telah terbang. Kami mulai mengirim aliran bola. Mari kita lihat potongannya. Sekarang bola terbang ke satu arah, mereka dikonfirmasi, dan jumlah bola kita bertambah secara eksponensial. Di beberapa titik, volume bola menjadi sangat besar sehingga melambat dan kerugian dimulai. Setelah kehilangan, kami memperlambat sedikit, mengurangi jendela kami hingga setengahnya. Kemudian kami mencoba memahami apa yang terjadi pada kami. Tahap pertama disebut TCP Slow Start.







Ketika kami menutup jendela dua kali, kami dapat memulihkan koneksi dan meminta orang-orang untuk mengirimkan bola kami lagi. Mereka berteriak kepada kami bahwa kami perlu mengirim bola, kami menjawabnya - ini bola Anda. Fase ini disebut Fast Recovery dan Fast Retransmit.







Ketika kami menyadari bahwa semuanya baik-baik saja dengan kami, kami mulai secara bertahap meningkatkan jumlah bola yang dikirim, mulai dari jendela yang runtuh itu. Fase ini disebut Penghindaran Kemacetan. Artinya, kami mencoba menghindari kehilangan paket kami.



Fase ketika jendela kita runtuh dua kali disebut Penurunan perkalian. Dan fase lambat peningkatan jumlah bola disebut Peningkatan Aditif.



Ketika Penghindaran Kemacetan kami kehilangan paket lagi, kami dapat melakukan langkah berikutnya. Tetapi saat ini kami lebih tertarik pada gambar grafik ini. Kami melihat gergaji seperti itu, dan gergaji ini akan berguna bagi kami beberapa kali. Ingat seperti apa bentuknya.







Kami akan kembali ke masalah protokol TCP konvensional. Dengan analogi dengan pipa, kami menuangkan tas. Karena ada pengguna lain di Internet selain kita, mereka juga mulai menuangkan paket ke dalam pipa. Di beberapa titik, buffer dari router kami dapat meluap dan menimbulkan masalah bagi kami dalam mengirim paket.



Ada juga masalah dengan kehilangan paket pada jaringan nirkabel. Kemungkinan besar, laptop Anda tidak memiliki port Ethernet dan Anda sedang menonton pembicaraan melalui Wi-Fi. Kehilangan paket di jaringan Wi-Fi dan seluler tidak disebabkan oleh router itu sendiri, tetapi oleh gangguan radio. Metrik seperti itu tidak akan berguna bagi kami.



Perbedaan TCP BBR dari algoritma lain







Di sini kita datang ke BBR. Ini adalah singkatan dari Bottleneck Bandwidth dan Round Trip Time, ini adalah metrik bandwidth ketika kami tidak sepenuhnya menyumbat saluran kami, dan waktu perjalanan paket dari kami ke server dan kembali.



Ketika kami mengirim data, kondisi ideal di mana paket-paket dalam keadaan stabil, terbang dan belum diakui disebut produk Bandwidth-delay. Kita dapat meningkatkan BDP dengan menggunakan buffer perangkat jaringan. Ketika buffer ini terlampaui, kerugian dimulai.



Dan algoritme TCP biasa hanya bekerja di sisi kanan grafik, di mana kerugian terjadi - kami menuangkan begitu banyak paket sehingga kerugian tidak terhindarkan. Paket melambat dan kami mulai menutup jendela.



BBR, pada gilirannya, bekerja dengan prinsip yang berbeda, dekat dengan pipa kami. Kami hanya menuangkan tas sebanyak yang kami bisa lewati. Pada fase awal, yaitu di awal, kami menuangkan kantong hingga kemacetan dimulai.



Dan terkadang kehilangan paket dimungkinkan. Tapi BBR berusaha menghindari momen ini. Setelah kami mengisi pipa kami, kami mulai memutar kembali. Fase ini disebut drain.







Kami kembali ke koneksi stabil kami, di mana itu akan terisi penuh, tetapi pada saat yang sama kami tidak akan menggunakan buffer tambahan, reservoir tambahan. Dari posisi ini, BBR terus beroperasi.



Dari waktu ke waktu kami akan melihat apa yang terjadi dengan jaringan kami. Kami melacak hampir setiap paket yang dikembalikan kepada kami. Ketika paket dikembalikan kepada kami, kami mulai mencoba sedikit mempercepat jumlah paket, mempercepat paket itu sendiri dengan mengirimkannya ke jaringan.







Dan jika kita tidak memiliki masalah, kita dapat bertahan pada nilai ini. Artinya, terus bekerja dengan kecepatan yang nyaman bagi kami. Namun, jika ada kerugian, kami dapat memutar kembali.



Ketika kami menerima konfirmasi dan melihat bahwa kecepatannya meningkat, kami bisa menunggu sebentar, lihat interval sepuluh detik. Dan jika selama interval ini kami melihat bahwa kecepatan pengiriman paket meningkat dan paket dikonfirmasi lebih cepat, maka kami dapat memasuki fase probe RTT dan memeriksa apakah semuanya masih lebih baik.







Fase semacam itu bergantian, yaitu, kami akan terus memeriksa apa yang kami miliki dengan jaringan.



Algoritma BBR tidak lagi didasarkan pada packet loss, tetapi pada lebar saluran dan waktu tempuh paket.







Faktanya, itu kebal terhadap packet loss. Dia praktis tidak bereaksi terhadap mereka, dan karena itu kami memiliki beberapa masalah. Google berjanji bahwa masalah ini akan diperbaiki di BBR v2.



Kami telah memeriksa fase kami, dan sebelum kami lagi adalah sisir, yang telah saya tunjukkan. Protokol TCP biasa disorot dengan warna merah. Jadi dia mengambil, mengambil, memperlambat, dan lagi kehilangan paket. Dan BBR menetapkan kecepatan yang dia butuhkan, yang akan digunakannya untuk bekerja sepanjang waktu, dan terus-menerus memeriksa jaringan kami untuk melihat apakah sudah menjadi sedikit lebih baik. Dan itu mungkin semakin cepat.



Metrik kami terus diperbarui, kami melacak setiap konfirmasi dari klien dan memeriksa apakah jaringan kami telah dipercepat atau tidak.



Bagaimana tingkat pengiriman paket ini dikendalikan? Kami mengontrol kecepatan pengiriman menggunakan teknik mondar-mandir. Ini diterapkan di penjadwal yang saya sebutkan sebelumnya. Ini adalah penjadwal FQ. Ini juga diterapkan di kernel itu sendiri, tetapi saya akan membicarakannya nanti.



Kami mencoba, seperti di dalam pipa, untuk menuangkan lebih banyak data, dan pada saat yang sama tidak memperlambat, tidak kehilangan paket kami. Tapi BBR tidak sesederhana itu. Kemungkinan besar, Anda tinggal di kontainer atau menggunakan beberapa server untuk database - mungkin untuk gambar.







Dan semua server ini berinteraksi satu sama lain. Ada TCP normal yang diaktifkan, bukan BBR. Dan ketika Anda memiliki gergaji, yang telah kita lihat, ketika jendela mulai runtuh, maka, mungkin, BBR akan mulai meraba-raba bahwa jendela itu runtuh, dan meningkatkan kecepatan pengiriman paket. Dengan demikian, ia akan mengeluarkan TCP biasa dari jaringan kami, mendominasi.



Jika jaringan sangat buruk, masalah lain mungkin terjadi. TCP biasa tidak akan bekerja sama sekali, dan karena BBR praktis tidak sensitif terhadap kehilangan paket, maka BBR akan terus bekerja pada tingkat tertentu.



Kami dapat mengatasi masalah ini dengan pusat data dengan opsi TCP_CONGESTION. Itu terbuka untuk setiap soket, untuk setiap koneksi. Sejauh yang saya tahu, opsi ini tidak diterapkan di hampir semua server web. Dan penyeimbang L7 kami mendukungnya. Tapi kembali ke langkah kita. Jika Anda bekerja dengan kernel lama, maka ada bug dalam implementasi pacing di kernel sebelum versi 4.20. Dalam hal ini, ada baiknya menggunakan penjadwal FQ.







Sekarang setelah Anda mengetahui cara kerja TCP, Anda dapat pergi ke administrator sistem Anda dan memberi tahu dia mengapa Anda harus mengaktifkan BBR.



Mari kita kembali ke sepuluh persen kita. Dari mana asalnya? Jaringan operator sekarang sangat besar. Ini semua tentang uang. Anda dapat membuat saluran untuk 100, 200 terabit dan melewatkan sejumlah besar video 4K, misalnya. Tetapi klien Anda akan tetap berada di titik akhir.



Dan kemungkinan besar, mil terakhir ini ke klien akan menjadi sumber masalah. Semua Wi-Fi dan LTE kami akan kehilangan paket. Kami akan melihat perlambatan saat menggunakan TCP biasa. BBR memecahkan masalah ini. Anda dapat mengaktifkannya hanya dengan dua perintah yang saya tunjukkan. Terimakasih untuk semua.



All Articles