[Превод] Енвои тхреадинг модел

Превод чланка: Енвои тхреадинг модел - хттпс://блог.енвоипроки.ио/енвои-тхреадинг-модел-а8д44б922310

Овај чланак ми је био прилично занимљив, а пошто се Енвои најчешће користи као део „истио“ или једноставно као „контролор улаза“ кубернетеса, већина људи нема исту директну интеракцију са њим као, на пример, са типичним Нгинк или Хапроки инсталације. Међутим, ако се нешто поквари, било би добро разумети како то функционише изнутра. Покушао сам да преведем што већи део текста на руски, укључујући и посебне речи, за оне којима је то болно да гледају, оригинале сам оставио у загради. Добродошли у мачку.

Техничка документација ниског нивоа за базу кодова Енвои је тренутно прилично оскудна. Да бих ово поправио, планирам да направим серију постова на блогу о различитим подсистемима Енвои-а. Пошто је ово први чланак, јавите ми шта мислите и шта би вас могло занимати у будућим чланцима.

Једно од најчешћих техничких питања које добијам о Енвои-у је тражење ниског нивоа описа навојевног модела који користи. У овом посту ћу описати како Енвои мапира везе са нитима, као и систем Тхреад Лоцал Стораге који интерно користи да учини код паралелнијим и високим перформансама.

Преглед навоја

[Превод] Енвои тхреадинг модел

Енвои користи три различите врсте токова:

  • Главни: Ова нит контролише покретање и завршетак процеса, сву обраду КСДС (кДисцовери Сервице) АПИ-ја, укључујући ДНС, проверу здравља, опште управљање кластерима и рунтиме-ом, ресетовање статистике, администрацију и опште управљање процесима - Линук сигнале, итд дешава у овој нити је асинхрона и "неблокирајућа". Генерално, главна нит координира све процесе критичне функционалности који не захтевају велику количину ЦПУ-а за покретање. Ово омогућава да се већина контролног кода напише као да је једнострука.
  • Радник: Подразумевано, Енвои креира радну нит за сваку хардверску нит у систему, ово се може контролисати помоћу опције --concurrency. Свака радничка нит покреће „неблокирајућу“ петљу догађаја, која је одговорна за слушање сваког слушаоца у време писања (29. јула 2017.) нема дељења слушаоца, прихватања нових веза, инстанцирања стека филтера за; везу и обраду свих улазно/излазних (ИО) операција током животног века везе. Опет, ово омогућава да већина кода за руковање везом буде написана као да је једнонитна.
  • Филе флусхер: Свака датотека коју Енвои пише, углавном евиденције приступа, тренутно има независну нит за блокирање. Ово је због чињенице да је писање у датотеке кеширане од стране система датотека чак и када се користи O_NONBLOCK понекад може бити блокиран (уздах). Када радне нити треба да запишу у датотеку, подаци се заправо премештају у бафер у меморији где се на крају испуштају кроз нит испирање датотеке. Ово је једна област кода у којој технички све радне нити могу блокирати исту браву док покушавају да попуне меморијски бафер.

Руковање везом

Као што је горе укратко објашњено, све радне нити слушају све слушаоце без икаквог дељења. Дакле, кернел се користи за елегантно слање прихваћених утичница у радне нити. Модерни кернели су генерално веома добри у овоме, користе функције као што је појачавање приоритета за унос/излаз (ИО) како би покушали да попуне нит радом пре него што почну да користе друге нити које такође слушају на истом сокету, а такође не користе роунд робин закључавање (Спинлоцк) за обраду сваког захтева.
Једном када је веза прихваћена на радној нити, она никада не напушта ту нит. Сва даља обрада везе се у потпуности обрађује у радној нити, укључујући свако понашање прослеђивања.

Ово има неколико важних последица:

  • Сви скупови веза у Енвои-у су додељени радној нити. Дакле, иако скупови ХТТП/2 веза успостављају само једну везу са сваким узводним хостом у исто време, ако постоје четири радне нити, постојаће четири ХТТП/2 везе по узводном хосту у стабилном стању.
  • Разлог зашто Енвои ради на овај начин је тај што задржавањем свега на једној радној нити, скоро цео код може бити написан без блокирања и као да је једнонит. Овај дизајн олакшава писање великог броја кода и невероватно добро се прилагођава скоро неограниченом броју радничких нити.
  • Међутим, један од главних закључака је да је са становишта меморијског скупа и ефикасности везе, заправо веома важно конфигурисати --concurrency. Ако имате више радничких нити него што је потребно, губите меморију, стварате више неактивних веза и смањујете стопу окупљања веза. У Лифту, наши контејнери за приколице за изасланике раде са веома малом истовременошћу, тако да перформансе приближно одговарају услугама поред којих се налазе. Покрећемо Енвои као маргинални прокси само уз максималну истовременост.

Шта значи неблокирање?

Термин „неблокирање“ је коришћен неколико пута до сада када се расправља о томе како функционишу главна и радна нити. Сав код је написан под претпоставком да никада ништа није блокирано. Међутим, ово није сасвим тачно (шта није сасвим тачно?).

Енвои користи неколико дугих закључавања процеса:

  • Као што је већ поменуто, приликом писања дневника приступа, све радне нити стичу исто закључавање пре него што се попуни бафер евиденције у меморији. Време задржавања закључавања би требало да буде веома мало, али је могуће да се закључавање оспори уз високу истовременост и високу пропусност.
  • Енвои користи веома сложен систем за руковање статистикама које су локалне за нит. Ово ће бити тема посебног поста. Међутим, укратко ћу поменути да је у оквиру локалне обраде статистике нити понекад потребно закључати централно „складиште статистике“. Ово закључавање никада не би требало да буде потребно.
  • Главна нит периодично мора да се координира са свим радничким нитима. Ово се ради „објављивањем“ из главне нити у радне нити, а понекад и из радних нити назад у главну нит. Слање захтева закључавање како би објављена порука могла да се стави у ред чекања за каснију испоруку. Ове браве никада не би требало озбиљно да се оспоравају, али се ипак технички могу блокирати.
  • Када Енвои упише евиденцију у ток системских грешака (стандардна грешка), закључава цео процес. Уопштено говорећи, Енвои-јево локално евидентирање се сматра ужасним са становишта перформанси, тако да се није много пажње посветило његовом побољшању.
  • Постоји неколико других насумичних закључавања, али ниједно од њих није критично за перформансе и никада се не треба оспорити.

Локална меморија нити

Због начина на који Енвои одваја одговорности главне нити од одговорности радне нити, постоји захтев да се сложена обрада може обавити на главној нити и затим доставити свакој радној нити на веома истовремен начин. Овај одељак описује локалну меморију слања нити (ТЛС) на високом нивоу. У следећем одељку ћу описати како се користи за управљање кластером.
[Превод] Енвои тхреадинг модел

Као што је већ описано, главна нит управља практично свим функцијама управљачке и контролне равни у процесу Изасланика. Контролна раван је овде мало преоптерећена, али када је погледате у оквиру самог процеса Енвои и упоредите је са прослеђивањем које обављају радне нити, има смисла. Опште правило је да процес главне нити обавља неки посао, а затим треба да ажурира сваку радну нит према резултату тог рада. у овом случају, радна нит не мора да закључава сваки приступ.

Енвои-јев ТЛС (Тхреад лоцал стораге) систем ради на следећи начин:

  • Код који се покреће на главној нити може доделити ТЛС слот за цео процес. Иако је ово апстраховано, у пракси је то индекс у вектор, који обезбеђује О(1) приступ.
  • Главна нит може да инсталира произвољне податке у свој слот. Када се ово уради, подаци се објављују свакој радној нити као нормални догађај петље.
  • Радничке нити могу читати из свог ТЛС слота и преузимати све локалне податке који су тамо доступни.

Иако је то веома једноставна и невероватно моћна парадигма, веома је слична концепту РЦУ (Реад-Цопи-Упдате) блокирања. У суштини, радничке нити никада не виде промене података у ТЛС слотовима док рад ради. Промена се дешава само током периода одмора између радних догађаја.

Изасланик ово користи на два различита начина:

  • Чувањем различитих података у свакој радној нити, подацима се може приступити без икаквог блокирања.
  • Одржавањем заједничког показивача на глобалне податке у режиму само за читање на свакој радној нити. Дакле, свака радна нит има број референци података који се не може смањити док је рад у току. Тек када се сви радници смире и поставе нове заједничке податке, стари подаци ће бити уништени. Ово је идентично са РЦУ.

Нити ажурирања кластера

У овом одељку ћу описати како се ТЛС (Тхреад лоцал стораге) користи за управљање кластером. Управљање кластером укључује кДС АПИ и/или ДНС обраду, као и проверу здравља.
[Превод] Енвои тхреадинг модел

Управљање током кластера укључује следеће компоненте и кораке:

  1. Цлустер Манагер је компонента у оквиру Енвои-а која управља свим познатим кластерима, АПИ-јем услуге откривања кластера (ЦДС), АПИ-јем услуге тајног откривања (СДС) и услуге откривања крајњих тачака (ЕДС), ДНС-ом и активним спољним проверама. Одговоран је за креирање „евентуално конзистентног“ приказа сваког узводног кластера, који укључује откривене домаћине као и здравствени статус.
  2. Провера здравља врши активну проверу здравља и пријављује промене здравственог статуса менаџеру кластера.
  3. ЦДС (Цлустер Дисцовери Сервице) / СДС (Сецрет Дисцовери Сервице) / ЕДС (Ендпоинт Дисцовери Сервице) / ДНС се изводе да би се утврдило чланство у кластеру. Промена стања се враћа менаџеру кластера.
  4. Свака радна нит континуирано извршава петљу догађаја.
  5. Када менаџер кластера утврди да се стање за кластер променило, креира нови снимак стања кластера само за читање и шаље га свакој радној нити.
  6. Током следећег мирног периода, радна нит ће ажурирати снимак у додељеном ТЛС слоту.
  7. Током И/О догађаја који би требало да одреди равнотежу оптерећења између хоста, балансатор оптерећења ће захтевати ТЛС (локално складиштење нити) слот да би добио информације о хосту. Ово не захтева браве. Имајте на уму и да ТЛС такође може да покрене догађаје ажурирања тако да балансери оптерећења и друге компоненте могу поново да израчунају кеш меморије, структуре података итд. Ово је ван оквира овог поста, али се користи на различитим местима у коду.

Користећи горњу процедуру, Енвои може обрадити сваки захтев без икаквог блокирања (осим како је претходно описано). Осим сложености самог ТЛС кода, већина кода не мора да разуме како функционише вишенитност и може се писати као једнонит. Ово чини већи део кода лакшим за писање поред супериорних перформанси.

Други подсистеми који користе ТЛС

ТЛС (Тхреад лоцал стораге) и РЦУ (Реад Цопи Упдате) се широко користе у Енвои-у.

Примери коришћења:

  • Механизам за промену функционалности током извршавања: Тренутна листа омогућених функционалности се израчунава у главној нити. Свакој радној нити се тада даје снимак само за читање користећи РЦУ семантику.
  • Замена табела рута: За табеле рута које обезбеђује РДС (Роуте Дисцовери Сервице), табеле рута се креирају на главној нити. Снимак само за читање ће накнадно бити обезбеђен свакој радној нити користећи семантику РЦУ (Реад Цопи Упдате). Ово чини промену табела рута атомски ефикасним.
  • Кеширање ХТТП заглавља: Како се испоставило, израчунавање ХТТП заглавља за сваки захтев (док ради ~25К+ РПС по језгру) је прилично скупо. Изасланик централно израчунава заглавље отприлике сваке пола секунде и пружа га сваком раднику преко ТЛС-а и РЦУ-а.

Постоје и други случајеви, али претходни примери би требало да пруже добро разумевање за шта се користи ТЛС.

Познате замке перформанси

Иако Енвои генерално ради прилично добро, постоји неколико значајних области које захтевају пажњу када се користи са веома великом конкурентношћу и пропусношћу:

  • Као што је описано у овом чланку, тренутно све радне нити добијају закључавање приликом писања у бафер меморије дневника приступа. Уз високу конкурентност и високу пропусност, мораћете да групишете евиденције приступа за сваку радну нит на рачун испоруке ван редоследа приликом писања у коначну датотеку. Алтернативно, можете креирати посебан дневник приступа за сваку радничку нит.
  • Иако је статистика веома оптимизована, при веома високој конкурентности и пропусности вероватно ће доћи до атомских сукоба у појединачним статистикама. Решење овог проблема су бројачи по радној нити са периодичним ресетовањем централних бројача. О томе ће бити речи у следећем посту.
  • Тренутна архитектура неће добро функционисати ако је Енвои распоређен у сценарију где постоји врло мало веза које захтевају значајне ресурсе за обраду. Не постоји гаранција да ће везе бити равномерно распоређене међу радничким нитима. Ово се може решити имплементацијом балансирања везе радника, што ће омогућити размену веза између радних нити.

Закључак

Енвои-јев модел навоја је дизајниран да обезбеди лакоћу програмирања и масивни паралелизам на рачун потенцијално трошне меморије и веза ако нису правилно конфигурисани. Овај модел му омогућава да ради веома добро при веома великом броју нити и пропусности.
Као што сам укратко поменуо на Твитеру, дизајн такође може да ради на врху комплетног мрежног стека у корисничком режиму као што је ДПДК (Кит за развој плана података), што може резултирати конвенционалним серверима који обрађују милионе захтева у секунди уз потпуну Л7 обраду. Биће веома интересантно видети шта ће се градити у наредних неколико година.
Последњи брзи коментар: Питали су ме много пута зашто смо изабрали Ц++ за Енвои. Разлог остаје тај што је то и даље једини широко коришћени индустријски језик на којем се може изградити архитектура описана у овом посту. Ц++ дефинитивно није погодан за све или чак многе пројекте, али је за одређене случајеве употребе и даље једини алат за обављање посла.

Везе до кода

Везе до датотека са интерфејсима и имплементацијама заглавља о којима се расправља у овом посту:

Извор: ввв.хабр.цом

Додај коментар