V našich projektoch využívame mikroservisnú architektúru. Keď dôjde k prekážkam výkonu, veľa času sa strávi monitorovaním a analýzou protokolov. Pri protokolovaní časovania jednotlivých operácií do log súboru je zvyčajne ťažké pochopiť, čo viedlo k vyvolaniu týchto operácií, sledovať postupnosť akcií alebo časový posun jednej operácie voči druhej v rôznych službách.
Aby sme minimalizovali ručnú prácu, rozhodli sme sa použiť jeden z nástrojov na sledovanie. O tom, ako a prečo môžete použiť sledovanie a ako sme to urobili, sa bude diskutovať v tomto článku.
Aké problémy je možné vyriešiť sledovaním
Nájdite prekážku výkonu v rámci jednej služby aj v celom vykonávacom strome medzi všetkými zúčastnenými službami. Napríklad:
Mnoho krátkych po sebe idúcich hovorov medzi službami, napríklad do geokódovania alebo do databázy.
Dlhé I/O čakania, ako sú sieťové prenosy alebo čítanie disku.
Dlhá analýza údajov.
Dlhé operácie vyžadujúce CPU.
Časti kódu, ktoré nie sú potrebné na získanie konečného výsledku a môžu byť odstránené alebo oneskorené.
Jasne pochopte, v akom poradí sa volá a čo sa stane, keď sa operácia vykoná.
Je vidieť, že napríklad prišla Požiadavka na službu WS -> služba WS doplnila údaje cez službu R -> potom poslala požiadavku na službu V -> služba V načítala veľa údajov zo služby. Služba R -> prešla do služby P -> služba P prešla znova do služby R -> služba V ignorovala výsledok a prešla do služby J -> a až potom vrátila odpoveď službe WS, pričom pokračovala vo výpočte niečoho iného v pozadie.
Bez takejto stopy alebo podrobnej dokumentácie k celému procesu je veľmi ťažké pochopiť, čo sa deje pri prvom pohľade na kód a kód je roztrúsený po rôznych službách a skrytý za kopou košov a rozhraní.
Zhromažďovanie informácií o strome vykonávania pre následnú odloženú analýzu. V každej fáze vykonávania môžete do sledovania pridať informácie, ktoré sú v tejto fáze dostupné, a potom zistiť, aké vstupné údaje viedli k podobnému scenáru. Napríklad:
ID používateľa
práva
Typ zvolenej metódy
Chyba protokolu alebo vykonania
Premena stôp na podmnožinu metrík a ďalšia analýza už vo forme metrík.
Aká stopa môže zaznamenať. Span
Pri sledovaní existuje koncept rozpätia, je to analóg jedného denníka ku konzole. Kúpele majú:
Názov, zvyčajne názov metódy, ktorá bola vykonaná
Názov služby, v ktorej bol vygenerovaný rozsah
Vlastné jedinečné ID
Nejaký druh meta informácií vo forme kľúča/hodnoty, ktorý bol doň prihlásený. Napríklad parametre metódy alebo metóda skončila s chybou alebo nie
Časy začiatku a konca pre toto obdobie
ID rodičovského rozsahu
Každý rozsah je odoslaný do zberača rozsahov, aby bol uložený v databáze na neskoršie preskúmanie, hneď ako dokončí svoju realizáciu. V budúcnosti môžete vytvoriť strom všetkých rozsahov pripojením podľa ID rodiča. Pri analýze môžete nájsť napríklad všetky rozpätia v niektorej službe, ktorá trvala viac ako nejaký čas. Ďalej, keď prejdete na konkrétne rozpätie, uvidíte celý strom nad a pod týmto rozpätím.
Opentrace, Jagger a ako sme to implementovali do našich projektov
Existuje spoločný štandard opentrace, ktorý popisuje, ako a čo by sa malo zhromažďovať, bez toho, aby bol viazaný sledovaním konkrétnej implementácie v akomkoľvek jazyku. Napríklad v Jave sa všetka práca so stopami vykonáva cez bežné API Opentrace a pod ním sa dá skryť napríklad Jaeger alebo prázdna predvolená implementácia, ktorá nič nerobí.
Používame Morský vták ako implementácia Opentrace. Skladá sa z niekoľkých komponentov:
Jaeger-agent je lokálny agent, ktorý je zvyčajne nainštalovaný na každom počítači a služby sú doň prihlásené na lokálnom predvolenom porte. Ak neexistuje žiadny agent, stopy všetkých služieb na tomto počítači sú zvyčajne zakázané
Jaeger-collector - všetci agenti mu posielajú zozbierané stopy a on ich vloží do vybranej databázy
Databáza je ich preferovaná cassandra, ale používame elasticsearch, existujú implementácie pre niekoľko ďalších databáz a implementácia v pamäti, ktorá neukladá nič na disk
Jaeger-query je služba, ktorá ide do databázy a vracia už zozbierané stopy na analýzu
Jaeger-ui je webové rozhranie na vyhľadávanie a prezeranie stôp, ide do jaeger-query
Samostatným komponentom možno nazvať implementáciu opentrace jaeger pre špecifické jazyky, prostredníctvom ktorej sú rozpätia odosielané jaeger-agentovi. Pripojenie Jaggera v Jave prichádza na implementáciu rozhrania io.openracing.Tracer, po ktorom všetky stopy cez neho preletia k skutočnému agentovi.
Tiež pre pružinový komponent môžete pripojiť opentracing-jar-cloud-starter a implementácia od spoločnosti Jaeger opentracing-spring-jaeger-cloud-starter ktorý automaticky nakonfiguruje sledovanie všetkého, čo prechádza cez tieto komponenty, napríklad http požiadavky na radiče, požiadavky do databázy cez jdbc atď.
Sleduje protokolovanie v Jave
Niekde na najvyššej úrovni musí byť vytvorené prvé rozpätie, to sa dá urobiť automaticky, napríklad pružinovým ovládačom pri prijatí požiadavky, alebo manuálne, ak žiadna neexistuje. Potom sa prenáša prostredníctvom nižšie uvedeného rozsahu. Ak niektorá z nižšie uvedených metód chce pridať rozsah, zoberie aktuálne aktívne rozpätie z rozsahu, vytvorí nové rozpätie a povie, že jeho rodičom je výsledné aktívne rozpätie, a urobí nové rozpätie aktívnym. Pri volaní externých služieb sa im odovzdá aktuálny aktívny rozsah a tieto služby vytvoria nové rozsahy s odkazom na tento rozsah.
Všetka práca prechádza cez inštanciu Tracer, môžete ju získať cez mechanizmus DI alebo GlobalTracer.get () ako globálnu premennú, ak mechanizmus DI nefunguje. V predvolenom nastavení, ak tracer nebol inicializovaný, NoopTracer sa vráti, čo nerobí nič.
Ďalej sa aktuálny rozsah získa zo sledovača cez ScopeManager, z aktuálneho sa vytvorí nový rozsah s naviazaním nového rozsahu a potom sa vytvorený rozsah uzavrie, čím sa zatvorí vytvorený rozsah a vráti sa predchádzajúci rozsah na aktívny stav. Rozsah je viazaný na vlákno, takže pri viacvláknovom programovaní nesmiete zabudnúť preniesť aktívny rozsah do iného vlákna, pre ďalšiu aktiváciu rozsahu iného vlákna s odkazom na tento rozsah.
Pre viacvláknové programovanie existuje aj TracedExecutorService a podobné wrappery, ktoré automaticky preposielajú aktuálne rozpätie do vlákna pri spustení asynchrónnych úloh:
private ExecutorService executor = new TracedExecutorService(
Executors.newFixedThreadPool(10), GlobalTracer.get()
);
HttpClient httpClient = new TracingHttpClientBuilder().build();
Problémy, ktorým sme čelili
Beans a DI nie vždy fungujú, ak sa sledovač nepoužíva v službe alebo komponente Automaticky zapojené Tracer nemusí fungovať a budete musieť použiť GlobalTracer.get().
Anotácie nefungujú, ak nejde o komponent alebo službu, alebo ak je metóda volaná zo susednej metódy rovnakej triedy. Musíte byť opatrní, aby ste skontrolovali, čo funguje, a ak @Traced nefunguje, použite manuálne vytváranie sledovania. Môžete tiež pripojiť ďalší kompilátor pre anotácie Java, potom by mali fungovať všade.
Try with resources nefunguje v groovy, musíte nakoniec použiť try.
Každá služba musí mať svoj vlastný spring.application.name, pod ktorým sa budú zaznamenávať stopy. Čo robí samostatný názov pre predaj a test, aby im spolu neprekážali.
Ak používate GlobalTracer a kocúra, potom všetky služby spustené v tomto kocúriku majú jeden GlobalTracer, takže všetky budú mať rovnaký názov služby.
Pri pridávaní stôp do metódy si musíte byť istí, že nie je volaná mnohokrát v slučke. Pre všetky hovory je potrebné pridať jednu spoločnú stopu, ktorá zaručí celkový čas práce. V opačnom prípade sa vytvorí nadmerné zaťaženie.
Raz v jaeger-ui boli príliš veľké požiadavky na veľké množstvo stôp, a keďže nečakali na odpoveď, urobili to znova. Ako výsledok, jaeger-query začal jesť veľa pamäte a spomaľovať elasticitu. Pomohlo reštartovanie jaeger-query
Pravdepodobnosť, ktorá filtruje stopy s určitou danou pravdepodobnosťou.
Ratelimiting, ktorý obmedzuje počet stôp za sekundu. Tieto nastavenia môžete nakonfigurovať na klientovi, buď na jaeger-agent alebo na kolektore. Teraz používame const 1 v zásobníku valuátorov, pretože nie je príliš veľa požiadaviek, ale trvajú dlho. V budúcnosti, ak to bude nadmerne zaťažovať systém, môžete to obmedziť.
Ak používate cassandru, v predvolenom nastavení ukladá stopy iba dva dni. Používame ElasticSearch a stopy sú uložené po celú dobu a nie sú odstránené. Pre každý deň je vytvorený samostatný index, napríklad jaeger-service-2019-03-04. V budúcnosti budete musieť nakonfigurovať automatické čistenie starých stôp.
Na zobrazenie stôp potrebujete:
Vyberte službu, podľa ktorej chcete filtrovať stopy, napríklad tomcat7-default pre službu, ktorá je spustená v tomcat a nemôže mať svoj vlastný názov.
Potom vyberte operáciu, časový interval a minimálnu dobu prevádzky, napríklad od 10 sekúnd, aby sa vykonávali iba dlhé operácie.
Choďte na jednu zo stôp a uvidíte, čo sa tam spomalilo.
Tiež, ak je známe nejaké ID požiadavky, potom môžete nájsť sledovanie podľa tohto ID pomocou vyhľadávania značiek, ak je toto ID zaznamenané v rozsahu sledovania.