Utilizemu l'architettura di microserviziu in i nostri prughjetti. Quandu si verificanu i colli di bottiglia di rendiment, assai tempu hè passatu per monitorà è analizà i logs. Quandu si registranu i timings di l'operazioni individuali in un schedariu di log, hè di solitu difficiuli di capisce ciò chì hà purtatu à l'invucazione di queste operazioni, per seguità a sequenza di l'azzioni o u cambiamentu di u tempu di una operazione relative à l'altru in diversi servizii.
Per minimizzà u travagliu manuale, avemu decisu di utilizà unu di i strumenti di traccia. Circa cumu è perchè pudete aduprà traccia è cumu l'avemu fattu, è serà discutitu in questu articulu.
Chì prublemi ponu esse risolti cù traccia
Truvate i colli di bottiglia di rendiment sia in un serviziu unicu sia in tuttu l'arburu di esecutivu trà tutti i servizii participanti. Per esempiu:
Molti brevi chjamati consecutivi trà servizii, per esempiu, à geocoding o à una basa di dati.
Longu I / O aspetta, cum'è trasferimenti di rete o letture di discu.
Long parsing di dati.
Operazioni longu chì necessitanu cpu.
Sezzioni di codice chì ùn sò micca necessarii per ottene u risultatu finali è ponu esse eliminati o ritardati.
Capisce chjaramente in quale sequenza ciò chì hè chjamatu è ciò chì succede quandu l'operazione hè realizata.
Pò esse vistu chì, per esempiu, u Request hè ghjuntu à u serviziu WS -> u serviziu WS hà aghjustatu dati attraversu u serviziu R -> dopu mandatu una dumanda à u serviziu V -> u serviziu V hà carricatu assai dati da u R. serviziu -> andò à u serviziu P -> u serviziu P si n'andò di novu à u serviziu R -> u serviziu V ignorò u risultatu è andò à u serviziu J -> è solu dopu vultò a risposta à u serviziu WS, mentre cuntinueghja à calculà qualcosa altru in u fondo.
Senza una tale traccia o documentazione dettagliata per tuttu u prucessu, hè assai difficiuli di capisce ciò chì succede quandu si vede u codice per a prima volta, è u codice hè spargugliatu in diversi servizii è ammucciatu daretu à una mansa di bins è interfaccia.
Raccolta di informazioni nantu à l'arburu di l'esekzione per l'analisi differita sussegwenti. In ogni tappa di l'esekzione, pudete aghjunghje l'infurmazioni à a traccia chì hè dispunibule in questa fase è poi scopre quale dati di input hà purtatu à un scenariu simili. Per esempiu:
ID d'utilizatore
Diritti
Tipu di metudu sceltu
Errore di logu o di esecuzione
Trasformendu e tracce in un subset di metrica è più analisi digià in forma di metrica.
Chì traccia pò logu. Span
In traccia ci hè u cuncettu di un span, questu hè un analogu di un logu, à a cunsola. U spa hà:
Nome, di solitu u nome di u metudu chì hè statu eseguitu
U nome di u serviziu in quale u span hè statu generatu
ID unicu propiu
Qualchì tipu di meta infurmazione in a forma di una chjave / valore chì hè stata loggata in questu. Per esempiu, i paràmetri di u metudu o u metudu finiscinu cù un errore o micca
Tempi di iniziu è di fine per questu span
ID span parenti
Ogni span hè mandatu à u cullettivu di span per esse guardatu in a basa di dati per una rivisione più tardi appena hà finitu a so esecuzione. In u futuru, pudete custruisce un arbre di tutti i spazii cunnettendu per l'id parent. Quandu analizà, pudete truvà, per esempiu, tutti i spazii in qualchì serviziu chì hà pigliatu più di qualchì tempu. In più, andendu à un spaziu specificu, vede l'arbulu tutale sopra è sottu à questu span.
Opentrace, Jagger è cumu l'avemu implementatu per i nostri prughjetti
Ci hè un standard cumuni traccia aperta, chì descrive cumu è ciò chì deve esse recullatu, senza esse ligatu da traccia à una implementazione specifica in ogni lingua. Per esempiu, in Java, tuttu u travagliu cù tracce hè realizatu per mezu di l'API Opentrace cumuni, è sottu, per esempiu, Jaeger o una implementazione predeterminata viota chì ùn faci nunda pò esse oculata.
Avemu aduprà Jaeger cum'è una implementazione di Opentrace. Hè custituitu di parechji cumpunenti:
Jaeger-agent hè un agentu lucale chì hè generalmente installatu in ogni macchina è i servizii sò logati in questu in u portu predeterminatu locale. Se ùn ci hè micca un agentu, e tracce di tutti i servizii nantu à sta macchina sò generalmente disattivati
Jaeger-collector - tutti l'agenti mandanu tracce cullette à ellu, è li mette in a basa di dati selezziunata
A basa di dati hè a so cassandra preferita, ma usemu elasticsearch, ci sò implementazioni per un paru di altre basa di dati è una implementazione in memoria chì ùn salva nunda à u discu.
Jaeger-query hè un serviziu chì và à a basa di dati è torna tracce digià cullate per l'analisi
Jaeger-ui hè una interfaccia web per a ricerca è a visualizazione di tracce, va à jaeger-query
Un cumpunente separatu pò esse chjamatu l'implementazione di l'opentrace jaeger per lingue specifiche, attraversu quale spans sò mandati à jaeger-agent. Cunnettendu Jagger in Java vene à implementà l'interfaccia io.opentracing.Tracer, dopu chì tutte e tracce à traversu volaranu à l'agente reale.
Ancu per u cumpunente di primavera, pudete cunnette opentracing-spring-cloud-starter è implementazione da Jaeger opentracing-spring-jaeger-cloud-starter chì cunfigurà automaticamente a traccia per tuttu ciò chì passa per questi cumpunenti, per esempiu http richieste à i cuntrolli, dumande à a basa di dati attraversu jdbc, etc.
Logging di traccia in Java
In un locu à u livellu superiore, u primu Span deve esse creatu, questu pò esse fattu automaticamente, per esempiu, da u controller di primavera quandu una dumanda hè ricevutu, o manualmente s'ellu ùn ci hè nimu. Hè tandu trasmessu attraversu u Scope sottu. Se qualcunu di i metudi quì sottu volenu aghjunghje un Span, piglia l'attuale ActiveSpan da u Scope, crea un novu Span è dice chì u so parente hè l'activeSpan risultante, è face u novu Span attivu. Quandu chjamanu servizii esterni, u span attivu attuale hè passatu à elli, è quelli servizii creanu novi spazii cù riferimentu à questu span.
Tuttu u travagliu passa per l'istanza Tracer, pudete uttene per mezu di u mecanismu DI, o GlobalTracer.get () cum'è una variabile globale se u mecanismu DI ùn funziona micca. Per automaticamente, se u tracciante ùn hè micca inizializatu, NoopTracer torna chì ùn faci nunda.
In più, u scopu attuale hè ottenutu da u tracciatore attraversu u ScopeManager, un novu scopu hè creatu da u currente cù un ligame di u novu span, è dopu u Scope creatu hè chjusu, chì chjude u span creatu è torna u Scope precedente à u statu attivu. Scope hè ligatu à un filu, cusì quandu a prugrammazione multi-threaded, ùn deve micca scurdate di trasferisce u span attivu à un altru filu, per più attivazione di u Scope di un altru filu cù riferimentu à questu span.
Per a prugrammazione multi-threaded, ci hè ancu TracedExecutorService è wrappers simili chì trasmette automaticamente u span attuale à u filu quandu i travaglii asincroni sò lanciati:
private ExecutorService executor = new TracedExecutorService(
Executors.newFixedThreadPool(10), GlobalTracer.get()
);
HttpClient httpClient = new TracingHttpClientBuilder().build();
I prublemi chì avemu affruntatu
Beans è DI ùn sò micca sempre u travagliu se u tracciante ùn hè micca usatu in un serviziu o cumpunente, allora Autowired Tracer ùn pò micca travaglià è avete da aduprà GlobalTracer.get ().
L'annotazioni ùn funziona micca s'ellu ùn hè micca un cumpunente o serviziu, o se u metudu hè chjamatu da un metudu vicinu di a stessa classe. Avete da esse attentu à verificà ciò chì funziona è aduprà a creazione manuale di traccia se @Traced ùn funziona micca. Pudete ancu aghjunghje un compilatore supplementu per l'annotazioni java, allora duveranu travaglià in ogni locu.
Ogni serviziu deve avè u so propiu spring.application.name sottu à quale e tracce seranu registrate. Chì faci un nome separatu per a vendita è a prova, per ùn interferiscenu micca cun elli.
Se utilizate GlobalTracer è tomcat, allora tutti i servizii chì funzionanu in questu tomcat anu un GlobalTracer, perchè tutti anu u listessu nome di serviziu.
Quandu aghjunghje tracce à un metudu, deve esse sicuru chì ùn hè micca chjamatu parechje volte in un ciclu. Hè necessariu aghjunghje una traccia cumuna per tutte e chjama, chì guarantisci u tempu di travagliu tutale. Altrimenti, una carica eccessiva serà creata.
Una volta in jaeger-ui, dumande troppu grande sò state fatte per un gran numaru di tracce, è postu ch'elli ùn aspittàvanu micca una risposta, anu fattu di novu. In u risultatu, jaeger-query hà cuminciatu à manghjà assai memoria è rallentà elastica. Aiutatu da riavvià jaeger-query
Probabilisticu chì filtra tracce cù una certa probabilità data.
Ratelimiting chì limita u numeru di tracce per seconda. Pudete cunfigurà sti paràmetri nantu à u cliente, sia in u jaeger-agent sia in u cullettore. Avà usemu const 1 in a pila di valutatore, postu chì ùn sò micca assai richieste, ma piglianu assai tempu. In u futuru, se questu eserciterà una carica eccessiva nantu à u sistema, pudete limità.
Sè vo aduprate Cassandra, da manera predeterminata, guarda solu tracce per dui ghjorni. Avemu aduprà elasticsearch e tracce sò guardati per tuttu u tempu è ùn sò micca sguassati. Un indice separatu hè creatu per ogni ghjornu, per esempiu jaeger-service-2019-03-04. In u futuru, avete bisognu di cunfigurà a pulizia automatica di vechji tracce.
Per vede e tracce avete bisognu:
Selezziunate u serviziu da quale vulete filtrà e tracce, per esempiu, tomcat7-default per un serviziu chì hè in esecuzione in u tomcat è ùn pò micca avè u so nome.
Allora selezziunate l'operazione, l'intervallu di tempu è u tempu minimu di operazione, per esempiu da 10 seconde, per piglià solu esecuzioni longu.
Andate à una di e tracce è vede ciò chì rallentava quì.
Inoltre, s'ellu hè cunnisciutu qualchì id di dumanda, pudete truvà una traccia da questu id per mezu di una ricerca di tag, se questu id hè registratu in u span di traccia.