Sdílet prostřednictvím


Správa clusteru v Orleans

Orleans poskytuje správu clusterů prostřednictvím integrovaného protokolu členství, který někdy označujeme jako členství v clusteru. Cílem tohoto protokolu je, aby všechny sila (Orleans servery) souhlasily se sadou aktuálně živého sila, detekovala neúspěšná sila a umožnila novým sila připojit se ke clusteru.

Protokol spoléhá na externí službu, která poskytuje abstrakci IMembershipTable. IMembershipTable je plochá odolná tabulka, kterou používáme pro dva účely. Za prvé, používá se jako rendezvous bod pro sila najít navzájem a Orleans klienty najít sila. Za druhé se používá k ukládání aktuálního zobrazení členství (seznam živých sila) a pomáhá koordinovat dohodu o zobrazení členství.

V současné době máme více implementací IMembershipTable: na základě Azure Table Storage, Azure Cosmos DB, ADO.NET (PostgreSQL, MySQL/MariaDB, SQL Server, Oracle), Apache ZooKeeper, Consul IO, AWS DynamoDB, MongoDB, Redis, Apache Cassandraa implementace v paměti pro vývoj.

Kromě IMembershipTable každého sila se účastní plně distribuovaný protokol členství peer-to-peer, který detekuje neúspěšná sila a dosáhne dohody o sadě živých sila. Níže popisujeme interní implementaci protokolu členství Orleans.

Protokol členství

  1. Při spuštění každého sila přidá položku pro sebe do dobře známé sdílené tabulky pomocí implementace IMembershipTable. Kombinace identity sila (ip:port:epoch) a ID nasazení služby (ID klastru) se v tabulce používá jako jedinečný klíč. Epocha je jen čas v klíštěcích, kdy se toto silo spustilo, a proto ip:port:epoch je zaručeno, že v daném Orleans nasazení bude jedinečný.

  2. Sila se navzájem monitorují přímo prostřednictvím sond aplikací („jsi naživu“ heartbeats). Sondy se odesílají jako přímé zprávy ze sila do sila přes stejné TCP sokety, které používají silos pro komunikaci. Sondy tak plně korelují se skutečnými problémy se sítí a stavem serveru. Každé silo prozkoumává konfigurovatelnou sadu dalších sil. Silo vybere, koho se má testovat výpočtem konzistentních hodnot hash na jiné identitě sila, které tvoří virtuální okruh všech identit, a výběr sila následníků X v okruhu (jedná se o dobře známou distribuovanou techniku označovanou jako konzistentní hashovací a je široce používána v mnoha distribuovaných hashovacích tabulkách, jako je Chord DHT).

  3. Pokud silo S nezíská odpovědi sondy Y z monitorovaného serveru P, podezřívá ho napsáním časového razítka do řádku P v IMembershipTable.

  4. Pokud má P více než Z podezření v rámci K sekund, pak S napíše do Pova řádku, že P je mrtvý, a odešle kopii aktuální tabulky členství do všech ostatních sil. Silo pravidelně aktualizuje tabulku, takže snímek je optimalizací, která zkracuje čas potřebný pro všechna sila, aby se dozvěděla o nové verzi zobrazení členství.

  5. Další podrobnosti:

    1. Podezření je zapsáno IMembershipTabledo , ve speciálním sloupci v řádku odpovídající P. Když S podezřívá P, napíše: "at time TTT S podezření P".

    2. Jedno podezření nestačí k deklaraci P jako mrtvého. K deklaraci P jako mrtvého potřebujete podezření z různých sil v konfigurovatelném časovém intervalu T, obvykle 3 minuty. Podezření je zapsáno pomocí optimistického řízení souběžnosti poskytovaného IMembershipTable

    3. Podezřelý silo S přečte řádek P.

    4. Pokud S se jedná o poslední podezřelého (v období od T, jak je napsané ve sloupci podezření), S se rozhodne deklarovat P jako mrtvého. V tomto případě se S přidá do seznamu podezřelých a také píše ve sloupci Stav P, že P je mrtvý.

    5. V opačném případě, pokud S není posledním podezřelým, S se jenom přidá do sloupce podezřelého.

    6. V obou případech zpětný zápis používá číslo verze nebo značku ETag, která byla přečtena, takže aktualizace tohoto řádku jsou serializovány. V případě, že zápis selhal z důvodu neshody verze nebo značky ETag, S se pokusí znovu přečíst a pokusit se o zápis, pokud nebyl P již označený jako mrtvý).

    7. Na vysoké úrovni je tato posloupnost "čtení, místní úpravy, zpětný zápis" transakce. K tomu však nepoužíváme nutně transakce úložiště. Kód "Transakce" se provádí místně na serveru a používáme optimistickou souběžnost, kterou IMembershipTable poskytuje k zajištění izolace a atomicity.

  6. Každý silo pravidelně čte celou tabulku členství pro své nasazení. Tímto způsobem se sila učí o nových silach, které se připojují, a o dalších silach, které jsou deklarovány mrtvé.

  7. Vysílání snímku: Pro snížení frekvence periodického čtení tabulky pokaždé, když silo zapíše do tabulky (podezření, nové připojení atd.), odešle snímek aktuálního stavu tabulky všem ostatním silům. Vzhledem k tomu, že je tabulka členství konzistentní a monotonicky verzovaná, každá aktualizace vytvoří jedinečný verzovaný snímek, který lze bezpečně sdílet. To umožňuje okamžité šíření změn členství bez čekání na periodický cyklus čtení. Pravidelné čtení je stále zachováno jako záložní mechanismus v případě, že distribuce snímků selže.

  8. Seřazená zobrazení členství: Protokol členství zajišťuje, že všechny konfigurace členství jsou globálně a zcela seřazené. Toto řazení poskytuje dvě klíčové výhody:

    1. zaručené připojení: Když se ke clusteru připojí nové silo, musí ověřit obousměrné připojení ke všem ostatním aktivním silům. Pokud některé existující silo nereaguje (potenciálně značí problém s připojením k síti), nové silo se nesmí připojit. Tím se zajistí úplné připojení mezi všemi silami v clusteru při spuštění. Níže si prohlédněte poznámku o IAmAlive pro případ zotavení po havárii.

    2. konzistentní aktualizace adresáře: Protokoly vyššího řádu, jako je distribuovaný adresář zrn, spoléhají na to, že všechna sila musí zajistit konzistentní a monotónní zobrazení členství. To umožňuje chytřejší řešení duplicitních aktivací zrnek. Další podrobnosti najdete v dokumentaci k adresáři obilí.

    podrobnosti implementace:

    1. IMembershipTable vyžaduje atomické aktualizace, aby se zajistilo globální celkové pořadí změn:

      • Implementace musí aktualizovat položky tabulky (seznam sila) i číslo verze atomicky.
      • Toho lze dosáhnout pomocí databázových transakcí (jako v SQL Serveru) nebo atomických operací porovnání a zaměnění pomocí ETag (jako v Azure Table Storage).
      • Konkrétní mechanismus závisí na možnostech základního systému úložiště.
    2. Zvláštní řádek verze členství v tabulce sleduje změny:

      • Každý zápis do tabulky (podezření, prohlášení o smrti, sloučení) zvýší toto číslo verze.
      • Všechny zápisy jsou serializovány skrz tento řádek pomocí atomárních aktualizací.
      • Monotonicky se zvyšující verze zajišťuje celkové řazení všech změn členství.
    3. Když silo S aktualizuje stav silo P:

      • S nejprve přečte nejnovější stav tabulky.
      • V jedné atomické operaci aktualizuje řádek u P a zároveň zvýší číslo verze.
      • Pokud atomická aktualizace selže (např. kvůli souběžným úpravám), operace se opakuje s exponenciálním odstupňováním.

    aspekty škálovatelnosti:

    Serializování všech zápisů přes verzový řádek může mít vliv na škálovatelnost kvůli zvýšeným konfliktům. Protokol byl prokázáno v produkčním prostředí s až 200 silami, ale může čelit problémům nad tisíc sila. U velmi rozsáhlých nasazení zůstávají ostatní části Orleans (zasílání zpráv, složkový adresář, hostování) škálovatelné i v případě, že se aktualizace členství stanou úzkým hrdlem.

  9. výchozí konfigurace: Výchozí konfigurace byla ručně vyladěna během produkčního využití v Azure. Ve výchozím nastavení: každé silo je monitorováno třemi dalšími sily, dvě podezření stačí k prohlášení sila za mrtvé, a to pouze na základě podezření z posledních tří minut (jinak jsou považována za zastaralá). sondy se odesílají každých deset sekund a museli byste vynechat tři sondy, abyste měli podezření na silo.

  10. samoobslužné monitorování: Detektor chyb zahrnuje nápady z lifeguarda Hashicorp výzkumu (papírový, talk, blog) ke zlepšení stability clusteru během katastrofických událostí, kdy velká část clusteru dochází k částečnému selhání. Komponenta LocalSiloHealthMonitor hodnotí stav každého sila pomocí několika heuristik.

    • Aktivní stav v tabulce členství
    • Žádné podezření z jiných sil
    • Nedávné úspěšné odpovědi sondy
    • Přijaté nedávné požadavky sondy
    • Rychlost odezvy fondu vláken (pracovní položky spouštěné během 1 sekundy)
    • Přesnost časovače (spuštění do 3 sekund od rozvrhu)

    Skóre stavu silo má vliv na vypršení časového limitu sondy: sila není v pořádku (bodování 1–8) mají ve srovnání se zdravými silami vyšší časové limity (skóre 0). To má dvě výhody:

    • Poskytuje více času pro úspěch sond, když je síť nebo systém ve stresu.
    • Zvyšuje pravděpodobnost, že nezdravá sila budou prohlášena za nefunkční, než budou moci nesprávně vyřadit zdravá sila.

    To je obzvláště užitečné ve scénářích, jako je vyhladovění poolu vláken, kdy pomalé uzly můžou jinak nesprávně podezřívat zdravé uzly, jednoduše proto, že nedokážou zpracovat odpovědi dostatečně rychle.

  11. Nepřímé sondování: Další funkce inspirovaná Lifeguard, která zlepšuje přesnost detekce selhání tím, že snižuje pravděpodobnost chybné deklarace zdravého sila jako mrtvého v případě, že je silo nezdravé nebo rozdělené. Když má monitorovací silo dva pokusy o sondu zbývající pro cílové silo před odesláním hlasu, aby bylo deklarováno, že je mrtvé, využívá nepřímé sondování:

    • Silo monitorování náhodně vybere další silo jako zprostředkovatele a požádá jej, aby prozkoumalo cíl.
    • Zprostředkovatel se pokusí kontaktovat cílové silo.
    • Pokud cíl během časového limitu neodpoví, zprostředkující odešle negativní potvrzení.
    • Pokud monitorovací silo obdrželo negativní potvrzení od zprostředkovatele a zprostředkovatel prohlašuje, že je v pořádku (prostřednictvím samokontroly, jak je popsáno výše), monitorovací silo vydá hlas, aby cíl prohlásilo za nefunkční.
    • Při výchozí konfiguraci požadovaných dvou hlasů se záporné potvrzení z nepřímé sondy počítá jako oba hlasy, což umožňuje rychlejší deklaraci mrtvých silos, když je selhání potvrzeno ze strany více perspektiv.
  12. vynucování dokonalé detekce selhání: Jakmile je v tabulce deklarováno mrtvé silo, považuje se za mrtvé všemi, i když není mrtvé (pouze dočasně izolované nebo se ztratily signály heartbeat). Všichni s ním přestanou komunikovat a jakmile se naučí, že je mrtvý (čtením nového stavu z tabulky), spáchá sebevraždu a ukončí svůj proces. V důsledku toho musí existovat infrastruktura, aby bylo možné restartovat silo jako nový proces (při spuštění se vygeneruje nové číslo epochy). Když je hostovaná v Azure, stane se to automaticky. Pokud není, vyžaduje se jiná infrastruktura, například služba Windows nakonfigurovaná tak, aby se automaticky restartovala při selhání nebo nasazení Kubernetes.

  13. Co se stane, když není tabulka po určitou dobu přístupná:

    Pokud je služba úložiště mimo provoz, není k dispozici nebo je s ní problémy s komunikací, Orleans protokol nehlásí sila jako mrtvá omylem. Provozní sila budou fungovat bez jakýchkoli problémů. Orleans ale nebude moct deklarovat mrtvou silo (pokud zjistí, že některá silo jsou mrtvá prostřednictvím zmeškaných sond, nebude moct napsat tento fakt do tabulky) a nebude také moct povolit připojení nových sila. Takže úplnost bude trpět, ale přesnost ne – oddělování tabulky nikdy nezpůsobí, aby Orleans chybně deklaroval silo jako mrtvé. Také v případě částečného síťového oddílu (pokud některé sila mají přístup k tabulce a některé ne), může se stát, že Orleans deklaruje mrtvé silo jako mrtvé, ale bude to nějakou dobu trvat, než se o tom všechny ostatní sila dozví. Detekce by tedy mohla být zpožděná, ale Orleans kvůli nedostupnosti tabulky nikdy nespravuje silo.

  14. IAmAlive zapisuje pro diagnostiku a obnovu po havárii:

    Kromě prezenčních signálů, které se odesílají mezi silami, každý silo pravidelně aktualizuje časové razítko "I Am Alive" v jeho řádku v tabulce. Slouží k dvěma účelům:

    1. V případě diagnostiky poskytuje správcům systémů jednoduchý způsob kontroly dostupnosti clusteru a určení, kdy byl uzel naposledy aktivní. Časové razítko se obvykle aktualizuje každých 5 minut.
    2. Pokud silo v rámci zotavení po havárii neaktualizovalo časové razítko po několik období (konfigurovaných prostřednictvím NumMissedTableIAmAliveLimit), nové silos ho při kontrolách připojení při spuštění ignorují, což umožní clusteru zotavit se ze situací, kdy se silo zhroutilo bez řádného úklidu.

Tabulka členství

Jak už bylo zmíněno, IMembershipTable používá se jako redezvous bod pro sila najít navzájem a Orleans klienty najít sila a také pomáhá koordinovat dohodu o zobrazení členství. Hlavní úložiště Orleans obsahuje implementace pro mnoho systémů, jako jsou Azure Table Storage, Azure Cosmos DB, PostgreSQL, MySQL/MariaDB, SQL server, Apache ZooKeeper, Consul IO, Apache Cassandra, MongoDB, Redis, AWS DynamoDB a implementace v paměti pro vývoj.

  1. Azure Table Storage – v této implementaci používáme ID nasazení Azure jako klíč oddílu a identitu sila (ip:port:epoch) jako klíč řádku. Společně zaručují jedinečný klíč na silo. Pro řízení souběžnosti používáme optimistické řízení souběžnosti založené na značkách tabulky Azure. Pokaždé, když čteme z tabulky, uložíme značku ETag pro každý řádek pro čtení a použijeme tuto značku ETag při pokusu o zápis zpět. Značky ETag se automaticky přiřazují a kontrolují službou Azure Table Service při každém zápisu. U transakcí s více řádky využíváme podporu dávkových transakcí poskytovaných tabulkou Azure, která zaručuje serializovatelné transakce přes řádky se stejným klíčem oddílu.

  2. SQL Server – v této implementaci se nakonfigurované ID nasazení používá k rozlišení mezi nasazeními a silami, do kterých nasazení patří. Identita sil je definována jako kombinace deploymentID, ip, port, epoch v odpovídajících tabulkách a sloupcích. Relační back-end používá optimistické řízení souběžnosti a transakce, podobně jako postup použití ETags v implementaci tabulky Azure. Relační implementace očekává, že databázový stroj vygeneruje použitou značku ETag. V případě SQL Serveru, na SQL Server 2000 vygenerovaná ETag je jeden získaný z volání NEWID(). Používá se SQL Server 2005 a novější ROWVERSION . Orleans čte a zapisuje relační značky ETag jako neprůzné VARBINARY(16) značky a ukládá je do paměti jako řetězce kódované v base64 . Orleans podporuje vkládání s více řádky pomocí UNION ALL (pro Oracle včetně DUAL), která se v současné době používá k vkládání statistických dat. Přesná implementace a odůvodnění SQL Serveru se můžete podívat na CreateOrleansTables_SqlServer.sql.

  3. Apache ZooKeeper – v této implementaci používáme nakonfigurované ID nasazení jako kořenový uzel a identitu sila (ip:port@epoch) jako podřízený uzel. Společně zaručují jedinečnou cestu na silo. Pro řízení souběžnosti používáme optimistické řízení souběžnosti na základě verze uzlu. Pokaždé, když načteme z kořenového uzlu nasazení, uložíme verzi pro každý uzel silo pro čtení a tuto verzi použijeme při pokusu o zápis zpět. Pokaždé, když se data uzlu změní, se číslo verze atomicky zvýší službou ZooKeeper. U transakcí s více řádky používáme víceřádkové transakce, které zaručuje serializovatelné transakce nad uzly silo se stejným nadřazeným ID nasazení uzel.

  4. Consul V/V – k implementaci tabulky členství jsme použili úložiště klíč/hodnota consul. Další podrobnosti najdete v části Consul-Deployment .

  5. AWS DynamoDB – V této implementaci používáme ID nasazení clusteru jako klíč oddílu a identitu Silo (ip-port-generation) jako RangeKey, který vytváří jednotu záznamu. Optimistická souběžnost se provádí atributem ETag tak, že v DynamoDB vytvoří podmíněné zápisy. Logika implementace je poměrně podobná službě Azure Table Storage.

  6. Apacha Cassandra – v této implementaci jako klíč oddílu používáme složené ID služby a ID clusteru a identitu sila (ip:port:epoch) jako klíč řádku. Společně zaručují jedinečný řádek pro každé silo. Pro řízení souběžnosti používáme optimistické řízení souběžnosti založené na statické verzi sloupce pomocí zjednodušené transakce. Tento sloupec verze se sdílí pro všechny řádky v oddílu či clusteru, takže poskytuje konzistentně narůstající číslo verze pro každou tabulku členů v clusteru. V této implementaci nejsou žádné transakce s více řádky.

  7. Emulace v paměti pro nastavení vývoje Pro tuto implementaci používáme speciální systémovou zrnitost. Toto zrno se nachází na určeném primárním silu, který se používá pouze pro nastavení vývoje. V jakémkoli skutečném využití primárního sila produkčního prostředí se nevyžaduje.

Principy návrhu

Přirozenou otázkou, která může být položena, je, proč se nespoléhat zcela na Apache ZooKeeper nebo etcd pro implementaci členství v clusteru, potenciálně s využitím vestavěné podpory ZooKeeper pro členství ve skupině s efemérními uzly? Proč jsme obtěžovali implementaci našeho protokolu členství? Existují především tři důvody:

  1. Nasazení / hostování v cloudu:

    Zookeeper není hostovaná služba. To znamená, že zákazníci v cloudovém prostředí Orleans by museli nasazovat, spouštět a spravovat svou instanci clusteru ZK. To je jen další zbytečná zátěž, kterou jsme nechtěli vynutit na naše zákazníky. Pomocí tabulky Azure spoléháme na hostované spravované služby, díky čemuž je život zákazníka mnohem jednodušší. V podstatě v cloudu používejte Cloud jako platformu, ne jako infrastrukturu. Na druhé straně při spouštění místních a správě serverů se spoléhá na ZK jako na implementaci IMembershipTable této možnosti.

  2. Přímá detekce selhání:

    Při použití členství ve skupině ZK s dočasnými uzly se detekce selhání provádí mezi Orleans servery (klienty ZK) a servery ZK. Nemusí to nutně souviset se skutečnými problémy se sítí mezi Orleans servery. Naším přáním bylo, aby detekce selhání přesně odrážela stav komunikace uvnitř clusteru. Konkrétně v našem návrhu, pokud Orleans silo nemůže komunikovat s IMembershipTable ním není považováno za mrtvé a může pokračovat v práci. Na rozdíl od toho jsme použili členství ve skupině ZK s dočasnými uzly, které odpojí od serveru ZK, může způsobit Orleans , že je neaktivní silo (klient ZK), zatímco může být aktivní a plně funkční.

  3. Přenositelnost a flexibilita:

    V rámci Orleansfilozofie nechceme vynucovat silnou závislost na žádné konkrétní technologii, ale spíše mít flexibilní návrh, kde lze různé komponenty snadno přepínat s různými implementacemi. Toto je přesně účel, který IMembershipTable abstrakce slouží.

Vlastnosti protokolu členství

  1. Dokáže zpracovat libovolný počet selhání:

    Náš algoritmus dokáže zpracovat libovolný počet selhání (tj. f<=n), včetně úplného restartování clusteru. To je na rozdíl od "tradičních" řešení založených na Paxos , která vyžadují kvorum, což je obvykle většina. Viděli jsme v produkčních situacích, kdy byla více než polovina sila dole. Náš systém zůstal funkční, zatímco členství založené na Paxosu by nebylo schopno postupovat.

  2. Provoz do tabulky je velmi světlý:

    Skutečné sondy putují přímo mezi servery a ne do tabulky. To by vygenerovalo velké množství provozu plus by bylo méně přesné z hlediska detekce selhání - pokud silo nemohlo dosáhnout tabulky, chybělo by napsat jeho jsem živý prezenční signál a ostatní by ho zabili.

  3. Nastavitelná přesnost versus úplnost:

    I když nemůžete dosáhnout dokonalé i přesné detekce selhání, jeden obvykle chce mít možnost kompromisu přesnosti (nechcete deklarovat silo, které je živé jako mrtvé) s úplností (chcete deklarovat mrtvý silo, který je skutečně mrtvý co nejdříve). Konfigurovatelné hlasy pro deklaraci mrtvých a zmeškaných sond umožňují obchodování těchto dvou. Další informace naleznete v tématu Yale University: Computer Science Failure Detectors.

  4. Scale (Měřítko):

    Protokol dokáže zpracovat tisíce a pravděpodobně i desítky tisíc serverů. To je na rozdíl od tradičních řešení založených na Paxosu, jako jsou komunikační protokoly skupiny, které se ví, že se nemají škálovat nad desítky.

  5. Diagnostika:

    Tabulka je také velmi pohodlná pro diagnostiku a řešení potíží. Správci systému mohou okamžitě najít v tabulce aktuální seznam živého sila, stejně jako vidět historii všech zabitých sila a podezření. To je užitečné zejména při diagnostice problémů.

  6. Proč potřebujeme spolehlivé trvalé úložiště pro implementaci IMembershipTable:

    Pro IMembershipTable používáme trvalé úložiště pro dva účely. Za prvé, používá se jako rendezvous bod pro sila najít navzájem a Orleans klienty najít sila. Zadruhé používáme spolehlivé úložiště, abychom mohli koordinovat dohodu o zobrazení členství. I když provádíme detekci selhání přímo mezi silami, ukládáme zobrazení členství ve spolehlivém úložišti a používáme mechanismus řízení souběžnosti, který toto úložiště poskytuje, abychom dosáhli dohody o tom, kdo je živý a kdo je mrtvý. Tímto způsobem náš protokol vysoudí pevný problém distribuovaného konsensu s cloudem. V tom, že plně využíváme sílu základní cloudové platformy a skutečně ji používáme jako platformu jako službu (PaaS).

  7. Přímé zápisy IAmAlive do tabulky pouze pro diagnostiku:

    Kromě prezenčních signálů, které se odesílají mezi silami, každý silo také pravidelně aktualizuje sloupec "I Am Alive" v jeho řádku v tabulce. Tento sloupec "I Am Alive" se používá pouze pro ruční řešení potíží a diagnostiku a nepoužívá se samotným protokolem členství. Obvykle se píše s mnohem nižší frekvencí (jednou za 5 minut) a slouží jako velmi užitečný nástroj pro správce systému ke kontrole živého clusteru nebo snadné zjištění, kdy silo bylo naživu.

Poděkování

Chtěli bychom potvrdit příspěvek Alexe Kogana k návrhu a implementaci první verze tohoto protokolu. Tato práce byla provedena jako součást letního stáže v Microsoft Research v létě roku 2011. Implementace IMembershipTable založená na ZooKeeperu byla provedena Shayem Hazorem, implementace SQL IMembershipTable byla provedena Veikko Eevou, implementace AWS DynamoDB IMembershipTable byla provedena Gutembergem Ribeiro a implementace IMembershipTable založená na Consulu byla provedena Paulem Northem, a nakonec byla implementace Apache Cassandra IMembershipTable upravena z OrleansCassandraUtilsArshií001.