[Terjemahan] Model benang utusan

Terjemahan artikel: Model benang utusan - https://blog.envoyproxy.io/envoy-threading-model-a8d44b922310

Saya mendapati artikel ini agak menarik, dan oleh kerana Envoy paling kerap digunakan sebagai sebahagian daripada "istio" atau hanya sebagai "pengawal masuk" kubernetes, kebanyakan orang tidak mempunyai interaksi langsung yang sama dengannya seperti, sebagai contoh, dengan tipikal Pemasangan Nginx atau Haproxy. Walau bagaimanapun, jika sesuatu pecah, adalah baik untuk memahami cara ia berfungsi dari dalam. Saya cuba menterjemah sebanyak mungkin teks ke dalam bahasa Rusia, termasuk kata-kata istimewa; bagi mereka yang merasa sakit untuk melihat ini, saya meninggalkan yang asal dalam kurungan. Selamat datang ke kucing.

Dokumentasi teknikal peringkat rendah untuk pangkalan kod Utusan pada masa ini agak jarang. Untuk membetulkan ini, saya bercadang untuk melakukan satu siri catatan blog tentang pelbagai subsistem Utusan. Memandangkan ini adalah artikel pertama, sila beritahu saya pendapat anda dan perkara yang mungkin anda minati dalam artikel akan datang.

Salah satu soalan teknikal yang paling biasa yang saya terima tentang Envoy ialah meminta penerangan peringkat rendah tentang model benang yang digunakannya. Dalam siaran ini, saya akan menerangkan cara Utusan memetakan sambungan ke utas, serta sistem Storan Setempat Thread yang digunakan secara dalaman untuk menjadikan kod lebih selari dan berprestasi tinggi.

Gambaran keseluruhan threading

[Terjemahan] Model benang utusan

Utusan menggunakan tiga jenis aliran:

  • Utama: Benang ini mengawal permulaan dan penamatan proses, semua pemprosesan API XDS (xDiscovery Service), termasuk DNS, pemeriksaan kesihatan, kluster umum dan pengurusan masa jalan, tetapan semula statistik, pentadbiran dan pengurusan proses am - isyarat Linux. mula semula panas, dsb. Semua yang yang berlaku dalam urutan ini adalah tak segerak dan "tidak menyekat". Secara umum, utas utama menyelaras semua proses fungsi kritikal yang tidak memerlukan sejumlah besar CPU untuk dijalankan. Ini membolehkan kebanyakan kod kawalan ditulis seolah-olah ia adalah satu thread.
  • pekerja: Secara lalai, Envoy mencipta benang pekerja untuk setiap benang perkakasan dalam sistem, ini boleh dikawal menggunakan pilihan --concurrency. Setiap rangkaian pekerja menjalankan gelung peristiwa "tidak menyekat", yang bertanggungjawab untuk mendengar setiap pendengar; pada masa penulisan (29 Julai 2017) tidak ada perpecahan pendengar, menerima sambungan baharu, mewujudkan timbunan penapis untuk sambungan, dan memproses semua operasi input/output (IO) sepanjang hayat sambungan. Sekali lagi, ini membolehkan kebanyakan kod pengendalian sambungan ditulis seolah-olah ia berulir tunggal.
  • Penyiram fail: Setiap fail yang Envoy tulis, terutamanya mengakses log, pada masa ini mempunyai benang penyekat bebas. Ini disebabkan oleh fakta bahawa menulis kepada fail yang dicache oleh sistem fail walaupun semasa menggunakan O_NONBLOCK kadang-kadang boleh tersekat (sigh). Apabila benang pekerja perlu menulis ke fail, data sebenarnya dialihkan ke penimbal dalam ingatan di mana ia akhirnya dibuang melalui benang siram fail. Ini adalah satu kawasan kod yang secara teknikalnya semua benang pekerja boleh menyekat kunci yang sama semasa cuba mengisi penimbal memori.

Pengendalian sambungan

Seperti yang dibincangkan secara ringkas di atas, semua rangkaian pekerja mendengar semua pendengar tanpa sebarang sharding. Oleh itu, kernel digunakan untuk menghantar soket yang diterima dengan anggun ke benang pekerja. Inti moden secara amnya sangat baik dalam hal ini, ia menggunakan ciri seperti peningkatan keutamaan input/output (IO) untuk cuba mengisi benang dengan kerja sebelum mereka mula menggunakan benang lain yang juga mendengar pada soket yang sama, dan juga tidak menggunakan round robin mengunci (Spinlock) untuk memproses setiap permintaan.
Setelah sambungan diterima pada utas pekerja, sambungan itu tidak akan pernah meninggalkan utas itu. Semua pemprosesan lanjut sambungan dikendalikan sepenuhnya dalam urutan pekerja, termasuk sebarang tingkah laku pemajuan.

Ini mempunyai beberapa akibat penting:

  • Semua kumpulan sambungan dalam Utusan diberikan kepada rangkaian pekerja. Jadi, walaupun kumpulan sambungan HTTP/2 hanya membuat satu sambungan ke setiap hos huluan pada satu masa, jika terdapat empat utas pekerja, akan ada empat sambungan HTTP/2 bagi setiap hos huluan dalam keadaan mantap.
  • Sebab Envoy berfungsi dengan cara ini ialah dengan menyimpan segala-galanya pada satu utas pekerja, hampir semua kod boleh ditulis tanpa menyekat dan seolah-olah ia satu thread. Reka bentuk ini memudahkan untuk menulis banyak kod dan skala dengan sangat baik kepada bilangan benang pekerja yang hampir tidak terhad.
  • Walau bagaimanapun, salah satu perkara utama ialah dari sudut ingatan dan kecekapan sambungan, ia sebenarnya sangat penting untuk mengkonfigurasi --concurrency. Mempunyai lebih banyak benang pekerja daripada yang diperlukan akan membazirkan memori, mencipta lebih banyak sambungan terbiar dan mengurangkan kadar pengumpulan sambungan. Di Lyft, kontena kereta sampingan utusan kami berjalan dengan serentak yang sangat rendah supaya prestasi secara kasar sepadan dengan perkhidmatan yang mereka duduki. Kami menjalankan Envoy sebagai proksi kelebihan hanya pada konkurensi maksimum.

Apakah maksud tidak menyekat?

Istilah "tidak menyekat" telah digunakan beberapa kali setakat ini apabila membincangkan cara utas utama dan pekerja berfungsi. Semua kod ditulis dengan andaian bahawa tiada apa yang pernah disekat. Walau bagaimanapun, ini tidak sepenuhnya benar (apa yang tidak sepenuhnya benar?).

Utusan menggunakan beberapa kunci proses yang panjang:

  • Seperti yang dibincangkan, semasa menulis log akses, semua benang pekerja memperoleh kunci yang sama sebelum penimbal log dalam memori diisi. Masa memegang kunci sepatutnya sangat rendah, tetapi kemungkinan kunci itu dipertandingkan pada konkurensi tinggi dan daya pemprosesan yang tinggi.
  • Utusan menggunakan sistem yang sangat kompleks untuk mengendalikan statistik yang setempat kepada rangkaian. Ini akan menjadi topik siaran berasingan. Walau bagaimanapun, saya akan menyebut secara ringkas bahawa sebagai sebahagian daripada memproses statistik benang secara tempatan, kadangkala perlu untuk mendapatkan kunci pada "stor statistik" pusat. Penguncian ini tidak sepatutnya diperlukan.
  • Benang utama secara berkala perlu menyelaraskan dengan semua benang pekerja. Ini dilakukan dengan "menerbitkan" daripada utas utama kepada utas pekerja, dan kadangkala daripada utas pekerja kembali ke utas utama. Menghantar memerlukan kunci supaya mesej yang diterbitkan boleh beratur untuk penghantaran kemudian. Kunci ini tidak boleh dipertikaikan secara serius, tetapi ia masih boleh disekat secara teknikal.
  • Apabila Envoy menulis log ke aliran ralat sistem (ralat standard), ia memperoleh kunci pada keseluruhan proses. Secara umum, pembalakan tempatan Envoy dianggap buruk dari sudut prestasi, jadi tidak banyak perhatian diberikan untuk menambah baiknya.
  • Terdapat beberapa kunci rawak lain, tetapi tiada satu pun daripada mereka yang kritikal prestasi dan tidak boleh dicabar.

Ulirkan storan tempatan

Oleh kerana cara Envoy memisahkan tanggungjawab utas utama daripada tanggungjawab utas pekerja, terdapat keperluan bahawa pemprosesan kompleks boleh dilakukan pada utas utama dan kemudian diberikan kepada setiap utas pekerja dengan cara yang sangat serentak. Bahagian ini menerangkan Storan Tempatan Benang Utusan (TLS) pada tahap tinggi. Dalam bahagian seterusnya saya akan menerangkan bagaimana ia digunakan untuk menguruskan kluster.
[Terjemahan] Model benang utusan

Seperti yang telah diterangkan, utas utama mengendalikan hampir semua fungsi satah pengurusan dan kawalan dalam proses Utusan. Pesawat kawalan agak terbeban di sini, tetapi apabila anda melihatnya dalam proses Utusan itu sendiri dan membandingkannya dengan pemajuan yang dilakukan oleh benang pekerja, ia masuk akal. Peraturan umum ialah proses utas utama melakukan beberapa kerja, dan kemudian ia perlu mengemas kini setiap utas pekerja mengikut hasil kerja itu. dalam kes ini, benang pekerja tidak perlu memperoleh kunci pada setiap akses.

Sistem TLS (Thread local storage) Envoy berfungsi seperti berikut:

  • Kod yang berjalan pada utas utama boleh memperuntukkan slot TLS untuk keseluruhan proses. Walaupun ini diabstraksikan, dalam praktiknya ia adalah indeks ke dalam vektor, menyediakan akses O(1).
  • Benang utama boleh memasang data sewenang-wenang ke dalam slotnya. Apabila ini selesai, data diterbitkan kepada setiap urutan pekerja sebagai acara gelung peristiwa biasa.
  • Benang pekerja boleh membaca dari slot TLS mereka dan mendapatkan sebarang data setempat benang yang tersedia di sana.

Walaupun ia adalah paradigma yang sangat mudah dan sangat berkuasa, ia sangat serupa dengan konsep penyekatan RCU(Read-Copy-Update). Pada asasnya, urutan pekerja tidak pernah melihat sebarang perubahan data dalam slot TLS semasa kerja sedang berjalan. Perubahan berlaku hanya semasa tempoh rehat antara acara kerja.

Utusan menggunakan ini dalam dua cara berbeza:

  • Dengan menyimpan data yang berbeza pada setiap urutan pekerja, data boleh diakses tanpa sebarang sekatan.
  • Dengan mengekalkan penunjuk dikongsi kepada data global dalam mod baca sahaja pada setiap urutan pekerja. Oleh itu, setiap urutan pekerja mempunyai kiraan rujukan data yang tidak boleh dikurangkan semasa kerja sedang dijalankan. Hanya apabila semua pekerja bertenang dan memuat naik data kongsi baharu, data lama akan dimusnahkan. Ini sama dengan RCU.

Urutan kemas kini kelompok

Dalam bahagian ini, saya akan menerangkan cara TLS (Thread local storage) digunakan untuk mengurus kluster. Pengurusan kluster termasuk API xDS dan/atau pemprosesan DNS, serta pemeriksaan kesihatan.
[Terjemahan] Model benang utusan

Pengurusan aliran kluster merangkumi komponen dan langkah berikut:

  1. Pengurus Kluster ialah komponen dalam Utusan yang mengurus semua huluan kluster yang diketahui, API Kluster Discovery Service (CDS), API Secret Discovery Service (SDS) dan Endpoint Discovery Service (EDS), DNS dan pemeriksaan luaran yang aktif. pemeriksaan kesihatan. Ia bertanggungjawab untuk mencipta pandangan "akhirnya konsisten" bagi setiap kelompok huluan, yang merangkumi hos yang ditemui serta status kesihatan.
  2. Pemeriksa kesihatan melakukan pemeriksaan kesihatan yang aktif dan melaporkan perubahan status kesihatan kepada pengurus kluster.
  3. CDS (Cluster Discovery Service) / SDS (Secret Discovery Service) / EDS (Endpoint Discovery Service) / DNS dilakukan untuk menentukan keahlian kelompok. Perubahan keadaan dikembalikan kepada pengurus kluster.
  4. Setiap rangkaian pekerja secara berterusan melaksanakan gelung peristiwa.
  5. Apabila pengurus kluster menentukan bahawa keadaan untuk kluster telah berubah, ia mencipta syot kilat baca sahaja keadaan kluster dan menghantarnya ke setiap urutan pekerja.
  6. Semasa tempoh senyap seterusnya, urutan pekerja akan mengemas kini syot kilat dalam slot TLS yang diperuntukkan.
  7. Semasa acara I/O yang sepatutnya menentukan hos untuk memuatkan baki, pengimbang beban akan meminta slot TLS (Thread local storage) untuk mendapatkan maklumat tentang hos. Ini tidak memerlukan kunci. Ambil perhatian juga bahawa TLS juga boleh mencetuskan peristiwa kemas kini supaya pengimbang beban dan komponen lain boleh mengira semula cache, struktur data, dsb. Ini di luar skop siaran ini, tetapi digunakan di pelbagai tempat dalam kod.

Menggunakan prosedur di atas, Utusan boleh memproses setiap permintaan tanpa sebarang sekatan (kecuali seperti yang diterangkan sebelum ini). Selain daripada kerumitan kod TLS itu sendiri, kebanyakan kod tidak perlu memahami cara multithreading berfungsi dan boleh ditulis single-threading. Ini menjadikan kebanyakan kod lebih mudah untuk ditulis sebagai tambahan kepada prestasi unggul.

Subsistem lain yang menggunakan TLS

TLS (Thread local storage) dan RCU (Read Copy Update) digunakan secara meluas dalam Envoy.

Contoh penggunaan:

  • Mekanisme untuk menukar fungsi semasa pelaksanaan: Senarai semasa fungsi yang didayakan dikira dalam urutan utama. Setiap urutan pekerja kemudiannya diberikan petikan baca sahaja menggunakan semantik RCU.
  • Menggantikan jadual laluan: Untuk jadual laluan yang disediakan oleh RDS (Route Discovery Service), jadual laluan dibuat pada utas utama. Gambar baca sahaja kemudiannya akan diberikan kepada setiap urutan pekerja menggunakan semantik RCU (Read Copy Update). Ini menjadikan menukar jadual laluan cekap secara atom.
  • Cache pengepala HTTP: Ternyata, mengira pengepala HTTP untuk setiap permintaan (semasa menjalankan ~25K+ RPS setiap teras) agak mahal. Utusan mengira pengepala secara berpusat kira-kira setiap setengah saat dan memberikannya kepada setiap pekerja melalui TLS dan RCU.

Terdapat kes lain, tetapi contoh sebelumnya harus memberikan pemahaman yang baik tentang kegunaan TLS.

Perangkap prestasi yang diketahui

Walaupun Envoy menunjukkan prestasi yang agak baik secara keseluruhan, terdapat beberapa bidang penting yang memerlukan perhatian apabila ia digunakan dengan konkurensi dan daya pemprosesan yang sangat tinggi:

  • Seperti yang diterangkan dalam artikel ini, pada masa ini semua benang pekerja memperoleh kunci apabila menulis kepada penimbal memori log akses. Pada konkurensi yang tinggi dan daya pemprosesan yang tinggi, anda perlu mengumpulkan log akses untuk setiap utas pekerja dengan mengorbankan penghantaran luar pesanan apabila menulis ke fail akhir. Sebagai alternatif, anda boleh membuat log akses berasingan untuk setiap urutan pekerja.
  • Walaupun statistik sangat dioptimumkan, pada kesesuaian dan daya pemprosesan yang sangat tinggi kemungkinan besar akan ada perbalahan atom pada statistik individu. Penyelesaian kepada masalah ini ialah kaunter setiap benang pekerja dengan tetapan semula berkala kaunter pusat. Ini akan dibincangkan dalam entri seterusnya.
  • Seni bina semasa tidak akan berfungsi dengan baik jika Envoy digunakan dalam senario di mana terdapat sangat sedikit sambungan yang memerlukan sumber pemprosesan yang ketara. Tiada jaminan bahawa sambungan akan diagihkan sama rata antara rangkaian pekerja. Ini boleh diselesaikan dengan melaksanakan pengimbangan sambungan pekerja, yang akan membolehkan pertukaran sambungan antara rangkaian pekerja.

Kesimpulan

Model threading Envoy direka untuk memberikan kemudahan pengaturcaraan dan keselarian besar-besaran dengan mengorbankan memori dan sambungan yang mungkin membazir jika tidak dikonfigurasikan dengan betul. Model ini membolehkannya berfungsi dengan sangat baik pada kiraan benang dan daya pemprosesan yang sangat tinggi.
Seperti yang saya nyatakan secara ringkas di Twitter, reka bentuk ini juga boleh dijalankan di atas timbunan rangkaian mod pengguna penuh seperti DPDK (Data Plane Development Kit), yang boleh menyebabkan pelayan konvensional mengendalikan berjuta-juta permintaan sesaat dengan pemprosesan L7 penuh. Ia akan menjadi sangat menarik untuk melihat apa yang akan dibina dalam beberapa tahun akan datang.
Satu ulasan pantas terakhir: Saya telah ditanya berkali-kali mengapa kami memilih C++ untuk Utusan. Alasannya ialah ia masih merupakan satu-satunya bahasa gred industri yang digunakan secara meluas di mana seni bina yang diterangkan dalam siaran ini boleh dibina. C++ pastinya tidak sesuai untuk semua atau bahkan banyak projek, tetapi untuk kes penggunaan tertentu ia masih merupakan satu-satunya alat untuk menyelesaikan kerja.

Pautan ke kod

Pautan ke fail dengan antara muka dan pelaksanaan pengepala dibincangkan dalam siaran ini:

Sumber: www.habr.com

Tambah komen