QUIC in action: bagaimana Uber menerapkannya untuk mengoptimalkan kinerja

Protokol QUIC sangat menarik untuk ditonton, jadi kami senang menulis tentangnya. Tetapi jika publikasi sebelumnya tentang QUIC lebih bersifat historis (sejarah lokal, jika Anda suka) sifat dan bahan, maka hari ini kami senang untuk mempublikasikan interpretasi yang berbeda - kami akan berbicara tentang penerapan sebenarnya dari protokol pada tahun 2019. Dan ini bukan tentang infrastruktur kecil yang berbasis di garasi bersyarat, tetapi tentang Uber, yang bekerja hampir di seluruh dunia. Bagaimana para insinyur perusahaan sampai pada keputusan untuk menggunakan QUIC dalam produksi, bagaimana mereka menguji dan apa yang mereka lihat setelah masuk ke dalam produksi - di bawah potongan.
Gambar dapat diklik. Selamat membaca!



Uber adalah skala global, yaitu 600 kota kehadiran, di mana setiap aplikasi bergantung sepenuhnya pada Internet nirkabel dari lebih dari 4.500 operator seluler. Pengguna mengharapkan aplikasi berfungsi tidak hanya cepat, tetapi secara real time - untuk memastikan ini, aplikasi Uber membutuhkan latensi rendah dan koneksi yang sangat andal. Sayangnya, tumpukan HTTP / 2 tidak terasa nyaman di jaringan nirkabel yang dinamis dan rawan kehilangan. Kami menyadari bahwa dalam kasus ini, kinerja rendah terkait langsung dengan implementasi TCP di kernel sistem operasi.

Untuk mengatasi masalah tersebut, kami menerapkan QUIC , protokol modern dengan multiplexing saluran, yang memberi kami kontrol lebih besar atas kinerja protokol transport. Kelompok kerja IETF saat ini menstandarisasi QUIC sebagai HTTP / 3 .

Setelah pengujian terperinci, kami sampai pada kesimpulan bahwa penerapan QUIC dalam aplikasi kami akan membuat penundaan "tail" lebih sedikit dibandingkan dengan TCP. Kami mengamati penurunan kisaran 10-30% untuk lalu lintas HTTPS pada contoh aplikasi pengemudi dan penumpang. QUIC juga memberi kami kendali ujung ke ujung atas paket khusus.

Pada artikel ini, kami berbagi pengalaman kami tentang mengoptimalkan TCP untuk aplikasi Uber menggunakan tumpukan yang mendukung QUIC.

Kata terakhir dari teknologi: TCP


Saat ini, TCP adalah protokol transportasi yang paling banyak digunakan untuk mengirimkan lalu lintas HTTPS di Internet. TCP menyediakan aliran byte yang andal, sehingga mengatasi kemacetan jaringan dan kehilangan lapisan tautan. Meluasnya penggunaan TCP untuk lalu lintas HTTPS dijelaskan oleh keberadaan sebelumnya (hampir setiap OS berisi TCP), ketersediaan pada sebagian besar infrastruktur (misalnya, pada penyeimbang beban, proksi dan CDN HTTPS) dan fungsionalitas out-of-box, yang tersedia di sebagian besar platform dan jaringan.

Sebagian besar pengguna menggunakan aplikasi kami saat bepergian, dan penundaan ekor TCP jauh dari persyaratan waktu-nyata lalu lintas HTTPS kami. Sederhananya, pengguna di seluruh dunia telah menghadapi ini - Gambar 1 menunjukkan penundaan di kota-kota besar:


Gambar 1. Besarnya keterlambatan "tail" bervariasi di kota-kota utama tempat Uber beroperasi.

Terlepas dari kenyataan bahwa ada lebih banyak penundaan di jaringan India dan Brasil daripada di AS dan Inggris, penundaan ekor jauh lebih besar daripada penundaan rata-rata. Dan ini berlaku bahkan untuk AS dan Inggris Raya.

Kinerja TCP melalui udara


TCP dibuat untuk jaringan kabel , dengan penekanan pada tautan yang dapat diprediksi dengan baik. Namun, jaringan nirkabel memiliki karakteristik dan kesulitannya sendiri. Pertama, jaringan nirkabel rentan terhadap kehilangan karena gangguan dan pelemahan sinyal. Misalnya, jaringan Wi-Fi sensitif terhadap gelombang mikro, bluetooth, dan gelombang radio lainnya. Jaringan seluler menderita kehilangan sinyal ( path loss ) karena refleksi / penyerapan sinyal oleh benda dan bangunan, serta gangguan dari menara sel tetangga. Hal ini menyebabkan lebih signifikan (4-10 kali) dan berbagai penundaan round-trip (RTT) dan kehilangan paket dibandingkan dengan koneksi kabel.

Untuk mengatasi fluktuasi dan kerugian bandwidth, jaringan seluler biasanya menggunakan buffer besar untuk ledakan lalu lintas. Ini dapat menyebabkan prioritas yang berlebihan, yang berarti penundaan lebih lama. Sangat sering, TCP memperlakukan urutan seperti kehilangan karena peningkatan batas waktu, sehingga TCP cenderung melakukan relai dan dengan demikian mengisi buffer. Masalah ini dikenal sebagai bufferbloat ( buffer jaringan yang berlebihan, pembengkakan buffer ), dan ini merupakan masalah yang sangat serius dari Internet modern.

Akhirnya, kinerja jaringan seluler bervariasi tergantung pada operator, wilayah, dan waktu. Pada Gambar 2, kami mengumpulkan penundaan rata-rata lalu lintas HTTPS ke sel dalam rentang 2 kilometer. Data dikumpulkan untuk dua operator seluler terbesar di Delhi, India. Seperti yang Anda lihat, kinerja bervariasi dari sel ke sel. Juga, kinerja satu operator berbeda dari kinerja yang kedua. Ini dipengaruhi oleh faktor-faktor seperti pola akses jaringan, dengan mempertimbangkan waktu dan lokasi, mobilitas pengguna, serta infrastruktur jaringan, dengan mempertimbangkan kepadatan menara dan rasio jenis jaringan (LTE, 3G, dll.).


Gambar 2. Penundaan untuk contoh radius 2 km. Delhi, India.

Juga, kinerja jaringan seluler bervariasi dari waktu ke waktu. Gambar 3 menunjukkan median keterlambatan pada hari dalam seminggu. Kami juga mengamati perbedaan pada skala yang lebih kecil - dalam satu hari dan satu jam.


Gambar 3. Penundaan tail dapat sangat bervariasi pada hari yang berbeda, tetapi dengan operator yang sama.

Semua hal di atas mengarah pada fakta bahwa kinerja TCP tidak efisien dalam jaringan nirkabel. Namun, sebelum mencari alternatif untuk TCP, kami ingin mengembangkan pemahaman yang akurat tentang hal-hal berikut:
  • Apakah TCP penyebab utama keterlambatan ekor dalam aplikasi kita?
  • Apakah jaringan modern mengalami keterlambatan pulang pergi yang signifikan dan bervariasi?
  • Apa efek dari kehilangan kinerja RTT dan TCP?

Analisis kinerja TCP


Untuk memahami bagaimana kami menganalisis kinerja TCP, mari kita ingat secara singkat bagaimana TCP mentransfer data dari pengirim ke penerima. Pertama, pengirim membuat koneksi TCP dengan melakukan jabat tangan tiga arah: pengirim mengirim paket SYN, menunggu paket SYN-ACK dari penerima, kemudian mengirim paket ACK. Lintasan tambahan kedua dan ketiga digunakan untuk membuat koneksi TCP. Penerima mengakui tanda terima dari setiap paket (ACK) untuk memastikan pengiriman yang andal.

Jika suatu paket atau ACK hilang, pengirim mengirim ulang setelah batas waktu (RTO, batas waktu pengiriman ulang ). RTO dihitung secara dinamis berdasarkan berbagai faktor, misalnya, penundaan RTT yang diharapkan antara pengirim dan penerima.


Gambar 4. Pertukaran paket TCP / TLS termasuk mekanisme transmisi ulang.

Untuk menentukan bagaimana TCP bekerja dalam aplikasi kami, kami memantau paket TCP dengan tcpdump selama seminggu pada traffic traffic yang datang dari server perbatasan India. Kemudian kami menganalisis koneksi TCP menggunakan tcptrace . Selain itu, kami membuat aplikasi Android yang mengirimkan lalu lintas yang ditiru ke server uji, sebanyak mungkin meniru lalu lintas nyata. Smartphone dengan aplikasi ini dibagikan kepada beberapa karyawan yang mengumpulkan log selama beberapa hari.

Hasil dari kedua percobaan itu konsisten satu sama lain. Kami melihat penundaan RTT yang tinggi; nilai ekor hampir 6 kali lebih tinggi dari nilai median; nilai rata-rata aritmatika penundaan - lebih dari 1 detik. Banyak koneksi yang hilang, menyebabkan TCP mentransmisikan kembali 3,5% dari semua paket. Di daerah dengan kemacetan, seperti bandara dan stasiun kereta, kami mengamati kerugian 7%. Hasil tersebut menimbulkan keraguan pada kebijaksanaan konvensional bahwa skema transmisi ulang canggih yang digunakan dalam jaringan seluler secara signifikan mengurangi kehilangan transportasi. Di bawah ini adalah hasil tes dari aplikasi "simulator":
Metrik jaringanNilai-nilai
RTT, milidetik [50%, 75%, 95%, 99%][350, 425, 725, 2300]
Perbedaan RTT, detik~ 1,2 s rata-rata
Paket hilang dalam koneksi yang tidak stabilRata-rata ~ 3,5% (7% di daerah dengan kemacetan)

Hampir setengah dari koneksi ini memiliki setidaknya satu paket yang hilang, yang sebagian besar adalah paket SYN dan SYN-ACK. Sebagian besar implementasi TCP menggunakan nilai RTO 1 detik untuk paket SYN, yang meningkat secara eksponensial untuk kerugian selanjutnya. Waktu pemuatan aplikasi dapat meningkat karena fakta bahwa TCP akan memerlukan lebih banyak waktu untuk membuat koneksi.

Dalam hal paket data, RTO tinggi sangat mengurangi pemanfaatan jaringan yang bermanfaat dengan adanya kerugian sementara pada jaringan nirkabel. Kami menemukan bahwa waktu pengiriman ulang rata-rata adalah sekitar 1 detik dengan penundaan hampir 30 detik. Keterlambatan tinggi di tingkat TCP menyebabkan waktu tunggu dan coba ulang HTTPS, yang selanjutnya meningkatkan latensi dan ketidakefisienan jaringan.

Sementara persentil ke-75 dari RTT yang diukur adalah sekitar 425 ms, persentil ke-75 untuk TCP hampir 3 detik. Ini mengisyaratkan bahwa kerugian memaksa TCP untuk membuat 7-10 lintasan agar berhasil mengirim data. Ini mungkin disebabkan oleh perhitungan RTO yang tidak efektif, ketidakmampuan TCP untuk dengan cepat menanggapi hilangnya paket terakhir di jendela, dan ketidakefisienan algoritma kontrol kemacetan, yang tidak membedakan antara kehilangan dan kehilangan nirkabel karena kelebihan jaringan. Di bawah ini adalah hasil uji TCP loss:
Statistik kehilangan paket TCPNilai
Persentase koneksi dengan setidaknya 1 paket loss45%
Persentase koneksi dengan kehilangan selama pembuatan koneksi30%
Persentase koneksi dengan kehilangan selama pertukaran data76%
Distribusi Keterlambatan Pengiriman Ulang, Detik [50%, 75%, 95%, 99%][1, 2,8, 15, 28]
Distribusi transmisi ulang untuk satu paket atau segmen TCP[1,3,6,7]

Aplikasi QUIC


Awalnya dirancang oleh Google, QUIC adalah protokol transportasi multi-utas, modern yang berjalan di atas UDP. Saat ini, QUIC sedang dalam proses standardisasi (kami sudah menulis bahwa ada dua versi QUIC, yang penasaran dapat mengikuti tautan - kira-kira Penerjemah). Seperti yang ditunjukkan pada Gambar 5, QUIC dihosting di bawah HTTP / 3 (sebenarnya, HTTP / 2 di atas QUIC - ini adalah HTTP / 3, yang sekarang sangat standar). Itu sebagian menggantikan HTTPS dan lapisan TCP, menggunakan UDP untuk membentuk paket. QUIC hanya mendukung transfer data yang aman, karena TLS sepenuhnya terintegrasi dalam QUIC.


Gambar 5: QUIC bekerja di bawah HTTP / 3, menggantikan TLS, yang dulu bekerja di bawah HTTP / 2.

Di bawah ini kami mencantumkan alasan yang meyakinkan kami untuk menggunakan QUIC untuk memperkuat TCP:
  • Pengaturan koneksi 0-RTT. QUIC memungkinkan penggunaan kembali otorisasi dari koneksi sebelumnya, mengurangi jumlah jabat tangan keamanan. Di masa depan, TLS1.3 akan mendukung 0-RTT, tetapi jabat tangan TCP tiga arah masih akan diperlukan.
  • Mengatasi pemblokiran HoL. HTTP / 2 menggunakan satu koneksi TCP untuk setiap klien untuk meningkatkan kinerja, tetapi ini dapat menyebabkan blok HoL (head-of-line). QUIC menyederhanakan multiplexing dan mengirimkan permintaan ke aplikasi secara independen satu sama lain.
  • manajemen kemacetan. QUIC ada di level aplikasi, membuatnya lebih mudah untuk memperbarui algoritma transport utama, yang mengontrol pengiriman, berdasarkan parameter jaringan (jumlah kehilangan atau RTT). Sebagian besar implementasi TCP menggunakan algoritma CUBIC , yang tidak optimal untuk lalu lintas sensitif yang tertunda. Algoritma yang baru dikembangkan seperti BBR memodelkan jaringan dengan lebih akurat dan mengoptimalkan latensi. QUIC memungkinkan Anda untuk menggunakan BBR dan memperbarui algoritme ini karena meningkatkan .
  • menebus kerugian. QUIC memanggil dua TLP ( tail loss probe ) sebelum RTO kebakaran - bahkan ketika kerugiannya sangat mencolok. Ini berbeda dari implementasi TCP. TLP mengirim ulang terutama paket terakhir (atau baru, jika ada) untuk memicu pengisian cepat. Pemrosesan tail tail sangat berguna untuk bagaimana Uber bekerja dengan jaringan, yaitu untuk transmisi data yang pendek, episodik, dan sensitif terhadap penundaan.
  • ACK dioptimalkan. Karena setiap paket memiliki nomor seri yang unik, tidak ada masalah membedakan antara paket ketika mereka disampaikan. Paket ACK juga mengandung waktu untuk memproses paket dan menghasilkan ACK sisi klien. Fitur-fitur ini memastikan bahwa QUIC menghitung RTT lebih akurat. QUIC ACK mendukung hingga 256 rentang NACK , membantu pengirim menjadi lebih tangguh untuk bertukar paket dan menggunakan lebih sedikit byte dalam proses. ACK selektif ( SACK ) dalam TCP tidak menyelesaikan masalah ini dalam semua kasus.
  • migrasi koneksi. Koneksi QUIC diidentifikasi oleh ID 64-bit, jadi jika klien mengubah alamat IP, Anda dapat terus menggunakan ID dari koneksi lama pada alamat IP baru, tanpa gangguan. Ini adalah praktik yang sangat umum untuk aplikasi seluler ketika pengguna beralih antara Wi-Fi dan koneksi seluler.

Alternatif untuk QUIC


Kami melihat pendekatan alternatif untuk menyelesaikan masalah sebelum memilih QUIC.

Pertama-tama, kami mencoba menggunakan TPC PoP (Points of Presence) untuk menyelesaikan koneksi TCP yang lebih dekat dengan pengguna. Pada dasarnya, PoP mengakhiri koneksi TCP dengan perangkat seluler yang lebih dekat ke jaringan seluler dan proksi lalu lintas ke infrastruktur asli. Menutup TCP lebih dekat, kita berpotensi mengurangi RTT dan memastikan bahwa TCP akan lebih responsif terhadap lingkungan nirkabel yang dinamis. Namun, percobaan kami menunjukkan bahwa sebagian besar, RTT dan kerugian berasal dari jaringan seluler dan penggunaan PoP tidak memberikan peningkatan kinerja yang signifikan.

Kami juga melihat ke arah penyetelan parameter TCP. Mengkonfigurasi TCP stack pada server tepi heterogen kami sulit karena TCP memiliki implementasi yang berbeda di berbagai versi OS. Sulit untuk mengimplementasikan ini dan menguji berbagai konfigurasi jaringan. Mengonfigurasi TCP secara langsung pada perangkat seluler tidak dimungkinkan karena kurangnya otoritas. Lebih penting lagi, chip seperti koneksi dengan 0-RTT dan peningkatan prediksi RTT sangat penting untuk arsitektur protokol, dan oleh karena itu tidak mungkin untuk mencapai manfaat yang signifikan hanya dengan mengkonfigurasi TCP.

Akhirnya, kami mengevaluasi beberapa protokol berbasis UDP yang memecahkan masalah streaming video - kami ingin tahu apakah protokol ini akan membantu dalam kasus kami. Sayangnya, mereka tidak memiliki banyak pengaturan keamanan, dan mereka juga membutuhkan koneksi TCP tambahan untuk metadata dan mengontrol informasi.

Penelitian kami menunjukkan bahwa QUIC hampir merupakan satu-satunya protokol yang dapat membantu masalah lalu lintas Internet, dengan tetap mempertimbangkan keamanan dan kinerja.

Integrasi QUIC ke dalam platform


Untuk berhasil mengintegrasikan QUIC dan meningkatkan kinerja aplikasi dalam kondisi komunikasi yang buruk, kami mengganti tumpukan lama (HTTP / 2 melalui TLS / TCP) dengan protokol QUIC. Kami menggunakan pustaka jaringan Cronet dari Proyek Chromium , yang berisi protokol Google versi asli - gQUIC. Implementasi ini juga terus ditingkatkan untuk mengikuti spesifikasi IETF terbaru.

Pertama, kami mengintegrasikan Cronet ke aplikasi Android kami untuk menambahkan dukungan QUIC. Integrasi dilakukan untuk meminimalkan biaya migrasi. Alih-alih mengganti sepenuhnya tumpukan jaringan lama yang menggunakan pustaka OkHttp , kami mengintegrasikan Cronet DI BAWAH kerangka OkHttp API. Dengan mengintegrasikan dengan cara ini, kami menghindari perubahan dalam panggilan jaringan kami (yang digunakan Retrofit ) di tingkat API.

Mirip dengan pendekatan ke perangkat Android, kami menerapkan Cronet dalam aplikasi Uber untuk iOS, memotong lalu lintas HTTP dari API jaringan menggunakan NSURLProtocol . Abstraksi ini, disediakan oleh iOS Foundation, memproses data URL khusus protokol dan memastikan bahwa kami dapat mengintegrasikan Cronet ke aplikasi iOS kami tanpa biaya migrasi yang signifikan.

Quic Diselesaikan di Google Cloud Balancers


Di sisi backend, terminasi QUIC disediakan oleh infrastruktur penyeimbang Beban Google Cloud, yang menggunakan header alt-svc sebagai respons untuk mendukung QUIC. Secara umum, penyeimbang menambahkan header alt-svc ke setiap permintaan HTTP dan sudah memvalidasi dukungan QUIC untuk domain. Ketika klien Cronet menerima respons HTTP dengan tajuk ini, ia menggunakan QUIC untuk permintaan HTTP berikutnya ke domain ini. Segera setelah penyeimbang menyelesaikan QUIC, infrastruktur kami secara eksplisit mengirimkan tindakan ini melalui HTTP2 / TCP ke pusat data kami.

Kinerja: Hasil


Performa luar biasa adalah alasan utama kami mencari protokol yang lebih baik. Pertama, kami membuat dudukan dengan emulasi jaringan untuk mengetahui bagaimana QUIC akan berperilaku dengan profil jaringan yang berbeda. Untuk menguji operasi QUIC di jaringan nyata, kami bereksperimen di sekitar New Delhi menggunakan lalu lintas jaringan yang diemulasikan sangat mirip dengan panggilan HTTP dalam aplikasi penumpang.

Eksperimen 1


Inventaris untuk eksperimen:
  • Perangkat uji Android dengan tumpukan OkHttp dan Cronet untuk memastikan bahwa kami mengirim lalu lintas HTTPS melalui TCP dan QUIC, masing-masing;
  • server emulasi berbasis Java yang mengirimkan jenis HTTPS header yang sama dalam tanggapan dan memuat perangkat klien untuk menerima permintaan dari mereka;
  • Proxy cloud yang secara fisik terletak dekat dengan India untuk menyelesaikan koneksi TCP dan QUIC. Sementara kami menggunakan proxy terbalik pada NGINX untuk menyelesaikan TCP, sulit untuk menemukan proxy reverse open source untuk QUIC. Kami membuat proxy terbalik untuk QUIC sendiri, menggunakan tumpukan QUIC dasar dari Chromium dan menerbitkannya dalam kromium sebagai sumber terbuka.


Gambar 6. Set perjalanan untuk tes TCP vs QUIC terdiri dari perangkat Android dengan OkHttp dan Cronet, proksi cloud untuk mengakhiri koneksi, dan server emulasi.

Eksperimen 2


Ketika Google menyediakan QUIC menggunakan Google Cloud Load Balancing , kami menggunakan inventaris yang sama, tetapi dengan satu modifikasi: alih-alih NGINX, kami mengambil Google balancers untuk menyelesaikan koneksi TCP dan QUIC dari perangkat, serta untuk mengarahkan lalu lintas HTTPS ke server emulasi . Balancers didistribusikan di seluruh dunia, tetapi gunakan server PoP yang paling dekat dengan perangkat (berkat geolokasi).


Gambar 7. Dalam percobaan kedua, kami ingin membandingkan penundaan penyelesaian TCP dan QUIC: menggunakan Google Cloud dan menggunakan proxy cloud kami.

Akibatnya, beberapa wahyu menunggu kami:
  • Pemutusan PoP meningkatkan kinerja TCP. Karena penyeimbang melengkapi koneksi TCP lebih dekat ke pengguna dan dioptimalkan dengan sempurna, ini menghasilkan RTT yang lebih rendah, yang meningkatkan kinerja TCP. QUIC , TCP ( 10-30 ).
  • (hops) . QUIC- ( 50 ), , โ€“ 15%- 20%- 99 TCP. , โ€“ (bottleneck) .


8. , QUIC TCP.


, QUIC Android iOS-. A/B , QUIC Uber. , , .

(95 99 ) โ€“ LTE, 3G, 2G.

9. QUIC TCP .


, โ€“ QUIC , , :


, , 80% QUIC , 15% QUIC TCP. , - , Cronet TCP , UDP- . , QUIC.

QUIC


, . . , , TCP QUIC . QUIC- .

, .

Source: https://habr.com/ru/post/id463073/


All Articles