[Tərcümə] Envoy iplik modeli

Məqalənin tərcüməsi: Envoy threading modeli - https://blog.envoyproxy.io/envoy-threading-model-a8d44b922310

Bu məqalə mənə olduqca maraqlı göründü və Elçi ən çox “istio” nun bir hissəsi kimi və ya sadəcə kubernetlərin “giriş nəzarətçisi” kimi istifadə edildiyi üçün insanların çoxu onunla məsələn, tipik məqalələrlə eyni birbaşa əlaqədə deyil. Nginx və ya Haproxy quraşdırmaları. Ancaq bir şey qırılırsa, içəridən necə işlədiyini başa düşmək yaxşı olardı. Mümkün olduğu qədər mətni rus dilinə, o cümlədən xüsusi sözlər də çevirməyə çalışdım, baxmaq ağrılı olanlar üçün orijinalı mötərizədə buraxdım. Pişik altında xoş gəlmisiniz.

Elçi kod bazasında aşağı səviyyəli texniki sənədlər hazırda olduqca seyrəkdir. Bunu düzəltmək üçün müxtəlif Envoy alt sistemləri haqqında bir sıra bloq yazıları hazırlamağı planlaşdırıram. Bu, ilk məqalə olduğundan, zəhmət olmasa, nə düşündüyünüzü və gələcək məqalələrdə nə ilə maraqlana biləcəyinizi mənə bildirin.

Envoy haqqında aldığım ən çox yayılmış texniki suallardan biri istifadə olunan iplik modelinin aşağı səviyyəli təsviri tələbidir. Bu yazıda mən Envoy-un iplərlə əlaqəni necə xəritələndirdiyini, həmçinin kodu daha paralel və performanslı etmək üçün daxili olaraq istifadə edilən Thread Local Storage sisteminin təsvirini təsvir edəcəyəm.

Mövzuların təsviri (Treading icmalı)

[Tərcümə] Envoy iplik modeli

Elçi üç fərqli axın növündən istifadə edir:

  • Əsas (Əsas): Bu başlıq prosesin başlanğıcını və sonunu, bütün XDS (xDiscovery Service) API emalını, o cümlədən DNS, sağlamlıq yoxlanışı, ümumi klaster və xidmət prosesinin idarə edilməsi (işləmə vaxtı), statistik sıfırlama, idarəetmə və ümumi prosesin idarə edilməsini idarə edir - Linux siqnalları, isti yenidən başladın və s. Bu mövzuda baş verən hər şey asinxrondur və "bloklanmır". Ümumiyyətlə, əsas ip çox sayda CPU tələb etməyən bütün kritik funksional prosesləri əlaqələndirir. Bu, əksər idarəetmə kodunu tək yivli kimi yazmağa imkan verir.
  • İşçi: Varsayılan olaraq, Envoy sistemdəki hər bir aparat ipi üçün işçi mövzu yaradır, bu seçim ilə idarə edilə bilər --concurrency. Hər bir işçi mövzu hər bir dinləyicini (dinləyicini) dinləmək (dinləmək) üçün cavabdeh olan "bloklanmayan" hadisə dövrəsinə (hadisə dövrəsinə) başlayır, yazı zamanı (29 iyul 2017-ci il) heç bir parçalanma (parçalanma) yoxdur. dinləyicinin (dinləyicinin) yeni əlaqələri qəbul etməsi, əlaqə üçün filtr yığınının yaradılması və əlaqənin ömrü boyu bütün giriş/çıxış (IO) əməliyyatlarının idarə edilməsi. Yenə də, bu, əksər əlaqə idarəetmə kodunu tək yivli kimi yazmağa imkan verir.
  • Fayl (Fayl yuyucusu): Elçinin yazdığı hər bir fayl, əsasən qeydlərə giriş, hazırda müstəqil bloklama mövzusuna malikdir. Bu, istifadə edərkən belə fayl sistemi tərəfindən keşlənmiş fayllara yazılması ilə əlaqədardır O_NONBLOCK bəzən blok edə bilər (ah çəkə). İşçi mövzuları bir fayla yazmaq lazım olduqda, məlumatlar əslində yaddaşdakı buferə köçürülür və orada nəhayət ipdən təmizlənir faylın yuyulması. Bu, texniki olaraq bütün işçi iplərin yaddaş buferini doldurmağa çalışarkən eyni kilidi bloklaya biləcəyi bir kod sahəsidir.

Əlaqənin idarə edilməsi

Yuxarıda qısaca müzakirə edildiyi kimi, bütün işçi mövzular heç bir seqmentasiya olmadan bütün dinləyiciləri dinləyir. Beləliklə, ləpə qəbul edilmiş soketləri işçi iplərə ağıllı şəkildə göndərmək üçün istifadə olunur. Müasir ləpələr ümumiyyətlə bu işdə çox bacarıqlıdırlar, eyni rozetkada dinləyən digər iplərdən istifadə etməyə başlamazdan əvvəl iş parçasını işlə doldurmağa cəhd etmək üçün I/O prioritet gücləndirilməsi kimi xüsusiyyətlərdən istifadə edirlər və həmçinin spinlockdan (Spinlock) istifadə etmirlər. hər sorğunu emal edin.
Bir əlaqə işçi ipdə qəbul edildikdən sonra o, heç vaxt həmin ipdən çıxmır. Əlaqənin bütün sonrakı emalları hər hansı ötürmə davranışı da daxil olmaqla, tamamilə işçi ipdə idarə olunur.

Bunun bir neçə mühüm təsiri var:

  • Envoy-da bütün əlaqə hovuzları hər bir işçi ipinə aiddir. Beləliklə, HTTP/2 əlaqə hovuzları hər bir yuxarı axın hostu ilə eyni vaxtda yalnız bir əlaqə yaratsa da, dörd işçi tel varsa, sabit vəziyyətdə hər yuxarı host üçün dörd HTTP/2 bağlantısı olacaq.
  • Envoy-un bu şəkildə işləməsinin səbəbi odur ki, hər şeyi bir işçi ipdə saxlamaqla, demək olar ki, bütün kodlar bloksuz və sanki tək yivli kimi yazıla bilər. Bu dizayn çoxlu kod yazmağı asanlaşdırır və demək olar ki, qeyri-məhdud sayda işçi ipləri üçün inanılmaz dərəcədə yaxşı tərəzi edir.
  • Bununla belə, əsas tapıntılardan biri odur ki, yaddaş hovuzunun və əlaqələrin səmərəliliyi baxımından parametrin tənzimlənməsi əslində çox vacibdir. --concurrency. Lazım olduğundan daha çox işçi ipinə sahib olmaq yaddaşı itirəcək, daha çox boş bağlantılar yaradacaq və əlaqə hovuzunun vurma sürətini yavaşlatacaq. Lyft-də, elçi yan araba konteynerlərimiz çox aşağı eyni vaxtda işləyir, buna görə də performans onların yanında oturduqları xidmətlərlə təxminən bərabərdir. Biz Envoy-u yalnız maksimum paralellikdə kənar proxy kimi işlədirik.

Bloklanmayan nə deməkdir

Əsas və işçi iplərin necə işlədiyini müzakirə edərkən "bloklanmayan" termini indiyə qədər bir neçə dəfə istifadə edilmişdir. Bütün kodlar heç bir şeyin bloklanmadığı fərziyyəsi əsasında yazılır. Ancaq bu, tamamilə doğru deyil (nə tamamilə doğru deyil?).

Elçi bir neçə uzun proses kilidindən istifadə edir:

  • Daha əvvəl müzakirə edildiyi kimi, giriş jurnallarını yazarkən bütün işçi iplər yaddaşdaxili jurnal buferini doldurmazdan əvvəl eyni kilidi əldə edir. Kilidin saxlama müddəti çox aşağı olmalıdır, lakin bu kilidin yüksək paralellik və yüksək ötürmə qabiliyyəti ilə mübahisələndirilməsi mümkündür.
  • Elçi, mövzu üçün lokal olan statistikanı idarə etmək üçün çox mürəkkəb sistemdən istifadə edir. Bu ayrı bir yazının mövzusu olacaq. Bununla belə, qısaca qeyd edəcəyəm ki, iplik statistikasının yerli emalının bir hissəsi olaraq, bəzən mərkəzi "statistika mağazasında" bir kilid əldə etmək lazımdır. Bu kilid heç vaxt tələb olunmamalıdır.
  • Əsas ip vaxtaşırı bütün işçi iplərlə əlaqələndirilməlidir. Bu, əsas ipdən işçi iplərə, bəzən isə işçi ipliklərdən əsas ipə "göndərmə" yolu ilə həyata keçirilir. Göndərmə kilid tələb edir ki, dərc edilmiş mesaj daha sonra çatdırılmaq üçün növbəyə götürülə bilsin. Bu qıfıllar heç vaxt ciddi mübahisələrə yol verməməlidir, lakin onlar hələ də texniki cəhətdən kilidlənə bilər.
  • Elçi sistem xətası axınına jurnal yazdıqda (standart xəta), o, bütün proses kilidini əldə edir. Ümumiyyətlə, Elçinin yerli ağac kəsimi performans baxımından dəhşətli hesab olunur, ona görə də onun təkmilləşdirilməsinə çox diqqət yetirilmir.
  • Bir neçə başqa təsadüfi kilidlər var, lakin onların heç biri performans baxımından kritik deyil və heç vaxt mübahisə edilməməlidir.

Yerli yaddaşa keçin

Elçi əsas iplik məsuliyyətlərini işçi iplik məsuliyyətlərindən ayırdığına görə, mürəkkəb emalın əsas ipdə aparıla bilməsi və sonra hər bir işçi ipinə yüksək dərəcədə paralellik təmin edilməsi tələbi var. Bu bölmə Envoy Thread Local Storage (TLS) sistemini yüksək səviyyədə təsvir edir. Növbəti hissədə onun klasteri idarə etmək üçün necə istifadə edildiyini təsvir edəcəyəm.
[Tərcümə] Envoy iplik modeli

Artıq təsvir edildiyi kimi, əsas mövzu Elçi prosesində demək olar ki, bütün idarəetmə funksiyalarını və idarəetmə müstəvisinin funksionallığını idarə edir. Burada idarəetmə müstəvisi bir az sıxılıb, lakin Elçi prosesinin özü baxımından nəzərdən keçirildikdə və işçi iplərin yerinə yetirdiyi ötürmə ilə müqayisədə məna kəsb edir. Bir qayda olaraq, əsas ip prosesi müəyyən işlər görür və sonra bu işin nəticəsinə uyğun olaraq hər bir işçi ipini yeniləməli, işçi mövzu hər giriş üçün bir kilid yaratmaq lazım deyil isə.

TLS (Thread local storage) Elçi sistemi aşağıdakı kimi işləyir:

  • Əsas mövzuda işləyən kod bütün proses üçün TLS yuvası ayıra bilər. Bu mücərrəd olsa da, praktikada O(1) çıxışını təmin edən vektora indeksdir.
  • Əsas mövzu öz yuvasına ixtiyari məlumatları təyin edə bilər. Bu həyata keçirildikdə, məlumatlar hadisə dövrəsində normal bir hadisə kimi hər bir işçi ipinə dərc olunur.
  • İşçi mövzuları TLS yuvasından oxuya və orada mövcud olan hər hansı yerli iplik məlumatını əldə edə bilər.

Baxmayaraq ki, bu, RCU (Read-Copy-Update) bloklama konsepsiyasına çox oxşar olan çox sadə və inanılmaz dərəcədə güclü paradiqmadır. Prinsipcə, işçi iplər iş davam edərkən TLS yuvalarında heç bir məlumat dəyişikliyi görmür. Dəyişiklik yalnız iş hadisələri arasındakı hərəkətsiz dövrdə baş verir.

Elçi bundan iki fərqli şəkildə istifadə edir:

  • Hər bir işçi mövzuda müxtəlif məlumatların saxlanması ilə bu məlumatlara heç bir bloklama olmadan daxil olur.
  • Qlobal məlumatlara paylaşılan göstəricini hər bir işçi mövzuda yalnız oxumaq rejimində saxlamaqla. Beləliklə, hər bir işçi mövzuda iş görülərkən azaldıla bilməyən bir məlumat istinad sayı var. Yalnız bütün işçilər sakitləşdikdə və yeni paylaşılan məlumatları yüklədikdə köhnə məlumatlar məhv ediləcək. Bu RCU ilə eynidir.

Klaster yeniləməsi

Bu bölmədə mən TLS-in (Thread local storage) klasteri idarə etmək üçün necə istifadə edildiyini təsvir edəcəyəm. Klaster idarəçiliyinə xDS və/və ya DNS API emalı və sağlamlığın yoxlanılması daxildir.
[Tərcümə] Envoy iplik modeli

Klaster axınının idarə edilməsinə aşağıdakı komponentlər və addımlar daxildir:

  1. Klaster meneceri Envoy daxilində bütün məlum klaster yuxarı axınlarını, CDS (Cluster Discovery Service) API, SDS (Gizli Kəşf Xidməti) və EDS (Endpoint Discovery Service) API-lərini, DNS-ni və aktiv xarici yoxlamaları idarə edən komponentdir. O, aşkar edilmiş hostları və sağlamlıq vəziyyətini özündə əks etdirən hər bir yuxarı klasterin "nəhayət ardıcıl" görünüşünün yaradılmasına cavabdehdir.
  2. Sağlamlıq yoxlanışı aktiv sağlamlıq yoxlanışı həyata keçirir və sağlamlıq vəziyyətindəki dəyişiklikləri klaster menecerinə bildirir.
  3. CDS (Cluster Discovery Service) / SDS (Secret Discovery Service) / EDS (Endpoint Discovery Service) / DNS klaster üzvlüyünü müəyyən etmək üçün həyata keçirilir. Vəziyyət dəyişikliyi klaster menecerinə qaytarılır.
  4. Hər bir işçi ipi daim bir hadisə dövrəsini icra edir.
  5. Klaster meneceri klaster üçün vəziyyətin dəyişdiyini müəyyən etdikdə, o, klasterin yeni yalnız oxunuş şəklini yaradır və onu hər bir işçi mövzuya göndərir.
  6. Növbəti hərəkətsiz dövr ərzində işçi mövzu ayrılmış TLS yuvasındakı snapşotu yeniləyəcək.
  7. Balansı yükləmək üçün hostu müəyyən etməli olan I/O hadisəsi zamanı yük balanslaşdırıcısı host haqqında məlumat üçün TLS (Mövzu yerli yaddaşı) yuvasını sorğulayacaq. Bunun üçün kilidlər tələb olunmur. Qeyd edək ki, TLS həmçinin hadisələri yeniləmə zamanı işə sala bilər ki, yük balanslaşdırıcıları və digər komponentlər keşləri, məlumat strukturlarını və s. yenidən hesablaya bilsin. Bu, bu yazının əhatə dairəsi xaricindədir, lakin kodun müxtəlif yerlərində istifadə olunur.

Yuxarıdakı prosedurdan istifadə edərək, Elçi hər bir sorğunu heç bir bloklamadan (əvvəlcədən təsvir edilənlərdən başqa) emal edə bilər. TLS kodunun özünün mürəkkəbliyindən başqa, kodun çoxunun çox iş parçacığının necə işlədiyini və tək yivli rejimdə yazıla biləcəyini başa düşməyə ehtiyac yoxdur. Bu, əla performansla yanaşı, kodun çox hissəsini yazmağı asanlaşdırır.

TLS-dən istifadə edən digər alt sistemlər

Envoy proqramında TLS (Thread local storage) və RCU (Read Copy Update) geniş istifadə olunur.

İstifadə nümunələri:

  • İcra zamanı funksionallığın dəyişdirilməsi mexanizmi: Aktiv funksiyaların cari siyahısı əsas mövzuda qiymətləndirilir. Daha sonra hər bir işçi mövzu RCU semantikasından istifadə edərək yalnız oxumaq üçün nəzərdə tutulmuş görüntü ilə təmin edilir.
  • Marşrut cədvəllərinin dəyişdirilməsi: RDS (Marşrut Kəşfetmə Xidməti) tərəfindən təmin edilən marşrut cədvəlləri üçün marşrut cədvəlləri əsas mövzuda yaradılır. Yalnız oxumaq üçün nəzərdə tutulmuş görüntü daha sonra RCU (Read Copy Update) semantikasından istifadə edərək hər bir işçi mövzuya təqdim ediləcək. Bu, marşrut cədvəllərinin dəyişdirilməsini atomik cəhətdən səmərəli edir.
  • HTTP başlığının keşləşdirilməsi: Göründüyü kimi, hər sorğu üçün HTTP başlığının hesablanması (əsas başına ~25K+ RPS-də) olduqca bahadır. Elçi mərkəzləşdirilmiş şəkildə təxminən hər yarım saniyədə bir başlığı hesablayır və onu TLS və RCU vasitəsilə hər bir işçiyə təqdim edir.

Başqa hallar da var, lakin əvvəlki nümunələr TLS-nin nə üçün istifadə edildiyini yaxşı başa düşməlidir.

Məlum performans tələləri

Elçi ümumilikdə kifayət qədər yaxşı performans göstərsə də, çox yüksək paralellik və ötürmə qabiliyyəti ilə istifadə edildikdə diqqət tələb edən bir neçə diqqətəlayiq sahə var:

  • Bu məqalədə artıq təsvir olunduğu kimi, hal-hazırda bütün işçi mövzular giriş jurnalının yaddaş buferinə yazarkən kilid əldə edir. Yüksək paralellik və yüksək ötürmə qabiliyyəti, son fayla yazarkən sıradan çıxmış çatdırılma qiymətinə hər bir işçi ipi üçün giriş jurnallarının yığılmasını tələb edəcəkdir. Alternativ olaraq, hər bir işçi mövzu üçün ayrıca giriş jurnalı yarada bilərsiniz.
  • Statistikalar çox yüksək səviyyədə optimallaşdırılsa da, çox yüksək paralellik və ötürmə qabiliyyətinə malik olsa da, fərdi statistikada atom çəkişməsi ola bilər. Bu problemin həlli mərkəzi sayğacların vaxtaşırı sıfırlanması ilə hər bir işçi iplik sayğacdır. Bu, sonrakı yazıda müzakirə olunacaq.
  • Emal üçün əhəmiyyətli resurs tələb edən çox az əlaqənin olduğu bir ssenaridə Elçi yerləşdirilərsə, mövcud arxitektura yaxşı işləməyəcək. Bağlantıların işçi mövzuları arasında bərabər paylanacağına zəmanət yoxdur. Bu, işçi telləri arasında əlaqələrin mübadiləsinə imkan verəcək işçi əlaqə balansının tətbiqi ilə həll edilə bilər.

Nəticə

Envoy threading modeli düzgün konfiqurasiya edilmədikdə potensial israfçı yaddaş və bağlantılar hesabına proqramlaşdırma asanlığı və kütləvi paralellik üçün nəzərdə tutulmuşdur. Bu model ona çox yüksək ip saylarında və ötürmə qabiliyyətində çox yaxşı performans göstərməyə imkan verir.
Twitter-də qısaca qeyd etdiyim kimi, dizayn eyni zamanda DPDK (Data Plane Development Kit) kimi tam funksiyalı istifadəçi rejimli şəbəkə yığınının üstündə də işləyə bilər ki, bu da normal serverlərin tam L7 emalı ilə saniyədə milyonlarla sorğunu idarə etməsi ilə nəticələnə bilər. . Yaxın bir neçə ildə nə tikiləcəyini görmək çox maraqlı olacaq.
Sonuncu qısa şərh: Məndən dəfələrlə soruşublar ki, niyə Elçi üçün C++ dilini seçmişik. Səbəb hələ də bu yazıda təsvir edilən arxitekturanın qurulması üçün hələ də yeganə geniş istifadə olunan istehsal səviyyəsində dil olmasıdır. C++ bütün və ya hətta bir çox layihələr üçün mütləq uyğun deyil, lakin müəyyən istifadə halları üçün hələ də işi yerinə yetirmək üçün yeganə vasitədir.

Koda keçidlər

Bu yazıda müzakirə olunan interfeyslər və başlıqların tətbiqi ilə fayllara keçidlər:

Mənbə: www.habr.com

Добавить комментарий