Äau Habr!
Es strÄdÄju Tinkoff komandÄ, kas izstrÄdÄ savu paziÅojumu centru. Es galvenokÄrt izstrÄdÄju Java, izmantojot Spring boot un risinu dažÄdas tehniskas problÄmas, kas rodas projektÄ.
LielÄkÄ daļa mÅ«su mikropakalpojumu savstarpÄji sazinÄs asinhroni, izmantojot ziÅojumu brokeri. IepriekÅ” kÄ brokeris izmantojÄm IBM MQ, kas vairs netika galÄ ar slodzi, bet tajÄ paÅ”Ä laikÄ bija augstas piegÄdes garantijas.
KÄ nomaiÅa mums tika piedÄvÄta Apache Kafka, kurai ir augsts mÄrogoÅ”anas potenciÄls, bet diemžÄl nepiecieÅ”ama gandrÄ«z individuÄla pieeja dažÄdu scenÄriju konfigurÄÅ”anai. TurklÄt vismaz vienreizÄjais piegÄdes mehÄnisms, kas pÄc noklusÄjuma darbojas KafkÄ, neļÄva saglabÄt nepiecieÅ”amo konsekvences lÄ«meni no kastes. TÄlÄk es dalÄ«Å”os pieredzÄ par Kafka konfigurÄciju, jo Ä«paÅ”i, es jums pastÄstÄ«Å”u, kÄ konfigurÄt un dzÄ«vot ar precÄ«zi piegÄdes reizi.
GarantÄta piegÄde un vairÄk
TÄlÄk aprakstÄ«tie iestatÄ«jumi palÄ«dzÄs novÄrst vairÄkas problÄmas ar noklusÄjuma savienojuma iestatÄ«jumiem. Bet vispirms es gribÄtu pievÄrst uzmanÄ«bu vienam parametram, kas atvieglos iespÄjamo atkļūdoÅ”anu.
Tas palÄ«dzÄs klienta.id ražotÄjiem un patÄrÄtÄjiem. No pirmÄ acu uzmetiena kÄ vÄrtÄ«bu varat izmantot lietojumprogrammas nosaukumu, un vairumÄ gadÄ«jumu tas darbosies. Lai gan situÄcija, kad lietojumprogramma izmanto vairÄkus patÄrÄtÄjus un jÅ«s tiem pieŔķirat vienu un to paÅ”u client.id, tiek parÄdÄ«ts Å”Äds brÄ«dinÄjums:
org.apache.kafka.common.utils.AppInfoParser ā Error registering AppInfo mbean javax.management.InstanceAlreadyExistsException: kafka.consumer:type=app-info,id=kafka.test-0
Ja vÄlaties izmantot JMX lietojumprogrammÄ ar Kafka, tÄ varÄtu bÅ«t problÄma. Å ajÄ gadÄ«jumÄ kÄ klienta.id vÄrtÄ«bu vislabÄk ir izmantot lietojumprogrammas nosaukuma un, piemÄram, tÄmas nosaukuma kombinÄciju. MÅ«su konfigurÄcijas rezultÄtu var redzÄt komandas izvadÄ kafka-patÄrÄtÄju grupas no komunÄlajiem pakalpojumiem no Confluent:
Tagad apskatÄ«sim scenÄriju garantÄtai ziÅojumu piegÄdei. Kafka Producer ir parametrs acks, kas ļauj konfigurÄt pÄc cik apstiprinÄjumiem klastera vadÄ«tÄjam ir nepiecieÅ”ams uzskatÄ«t, ka ziÅojums ir veiksmÄ«gi uzrakstÄ«ts. Å im parametram var bÅ«t Å”Ädas vÄrtÄ«bas:
- 0 ā apstiprinÄjums netiks Åemts vÄrÄ.
- 1 ir noklusÄjuma parametrs, lai apstiprinÄtu, ir nepiecieÅ”ama tikai 1 kopija.
- ā1 ā ir nepiecieÅ”ams apstiprinÄjums no visÄm sinhronizÄtajÄm replikÄm (klastera iestatÄ«Å”ana min.insync.replicas).
No uzskaitÄ«tajÄm vÄrtÄ«bÄm ir skaidrs, ka acks, kas vienÄds ar ā1, dod visspÄcÄ«gÄko garantiju, ka ziÅojums netiks pazaudÄts.
KÄ mÄs visi zinÄm, sadalÄ«tÄs sistÄmas nav uzticamas. Lai aizsargÄtu pret pÄrejoÅ”iem defektiem, Kafka Producer nodroÅ”ina iespÄju mÄÄ£ina vÄlreiz, kas ļauj iestatÄ«t atkÄrtotas nosÅ«tÄ«Å”anas mÄÄ£inÄjumu skaitu piegÄde.timeout.ms. TÄ kÄ atkÄrtojumu parametra noklusÄjuma vÄrtÄ«ba ir Integer.MAX_VALUE (2147483647), ziÅojuma atkÄrtojumu skaitu var pielÄgot, mainot tikai delivery.timeout.ms.
MÄs virzÄmies uz precÄ«zi vienu piegÄdi
NorÄdÄ«tie iestatÄ«jumi ļauj mÅ«su ražotÄjam piegÄdÄt ziÅojumus ar augstu garantiju. Tagad parunÄsim par to, kÄ nodroÅ”inÄt, lai Kafkas tÄmai tiktu rakstÄ«ta tikai viena ziÅojuma kopija? VienkÄrÅ”ÄkajÄ gadÄ«jumÄ, lai to izdarÄ«tu, ir jÄiestata parametrs Producer iespÄjot.idempotence uz patiesÄ«bu. Idempotence garantÄ, ka vienas tÄmas noteiktÄ nodalÄ«jumÄ tiek rakstÄ«ts tikai viens ziÅojums. Idempotences iespÄjoÅ”anas priekÅ”noteikums ir vÄrtÄ«bas acks = visi, mÄÄ£iniet vÄlreiz > 0, max.in.flight.requests.per.connection ā¤ 5. Ja izstrÄdÄtÄjs nav norÄdÄ«jis Å”os parametrus, iepriekÅ” minÄtÄs vÄrtÄ«bas tiks iestatÄ«tas automÄtiski.
Kad idempotence ir konfigurÄta, ir jÄnodroÅ”ina, lai tie paÅ”i ziÅojumi katru reizi nonÄktu vienÄdos nodalÄ«jumos. To var izdarÄ«t, iestatot partitioner.class atslÄgu un parametru uz Producer. SÄksim ar atslÄgu. Tam ir jÄbÅ«t vienÄdam katram iesniegumam. To var viegli panÄkt, izmantojot jebkuru no sÄkotnÄjÄs ziÅas uzÅÄmuma ID. Parametram partitioner.class ir noklusÄjuma vÄrtÄ«ba ā
- Ja, nosÅ«tot ziÅojumu, nodalÄ«jums ir skaidri norÄdÄ«ts, mÄs to izmantojam.
- Ja nodalÄ«jums nav norÄdÄ«ts, bet atslÄga ir norÄdÄ«ta, atlasiet nodalÄ«jumu pÄc atslÄgas jaukÅ”anas.
- Ja nodalÄ«jums un atslÄga nav norÄdÄ«ti, atlasiet nodalÄ«jumus pa vienam (apkÄrtÄjÄ pÄrbaude).
ArÄ« atslÄgas izmantoÅ”ana un idempotenta sÅ«tÄ«Å”ana ar parametru max.in.flight.requests.per.connection = 1 sniedz jums racionalizÄtu ziÅojumu apstrÄdi patÄrÄtÄjam. Ir arÄ« vÄrts atcerÄties, ka, ja jÅ«su klasterÄ« ir konfigurÄta piekļuves kontrole, jums bÅ«s nepiecieÅ”amas tiesÄ«bas identiski rakstÄ«t tÄmÄ.
Ja pÄkÅ”Åi jums trÅ«kst idempotenta sÅ«tÄ«Å”anas ar atslÄgu iespÄju vai loÄ£ika Producer pusÄ prasa saglabÄt datu konsekvenci starp dažÄdiem nodalÄ«jumiem, tad transakcijas nÄks palÄ«gÄ. TurklÄt, izmantojot Ä·Ädes darÄ«jumu, jÅ«s varat nosacÄ«ti sinhronizÄt ierakstu KafkÄ, piemÄram, ar ierakstu datubÄzÄ. Lai iespÄjotu darÄ«jumu nosÅ«tÄ«Å”anu RažotÄjam, tai jÄbÅ«t idempotentam un papildus iestatÄ«tam transakciju.id. Ja jÅ«su Kafka klasterim ir konfigurÄta piekļuves kontrole, darÄ«juma ierakstam, tÄpat kÄ idempotentam ierakstam, bÅ«s nepiecieÅ”amas rakstÄ«Å”anas atļaujas, kuras var pieŔķirt, izmantojot masku, izmantojot transakcijÄ.id saglabÄto vÄrtÄ«bu.
FormÄli jebkuru virkni, piemÄram, lietojumprogrammas nosaukumu, var izmantot kÄ darÄ«juma identifikatoru. Bet, ja palaižat vairÄkas vienas un tÄs paÅ”as lietojumprogrammas instances ar vienu un to paÅ”u transakciju.id, pirmÄ palaitÄ instance tiks apturÄta ar kļūdu, jo Kafka to uzskatÄ«s par zombiju procesu.
org.apache.kafka.common.errors.ProducerFencedException: Producer attempted an operation with an old epoch. Either there is a newer producer with the same transactionalId, or the producer's transaction has been expired by the broker.
Lai atrisinÄtu Å”o problÄmu, lietojumprogrammas nosaukumam pievienojam sufiksu resursdatora nosaukuma formÄ, ko iegÅ«stam no vides mainÄ«gajiem.
RažotÄjs ir konfigurÄts, bet darÄ«jumi Kafka kontrolÄ tikai ziÅojuma apjomu. NeatkarÄ«gi no darÄ«juma statusa, ziÅojums nekavÄjoties pÄriet uz tÄmu, bet tam ir papildu sistÄmas atribÅ«ti.
Lai novÄrstu Å”Ädu ziÅojumu lasÄ«Å”anu PatÄrÄtÄjam pirms laika, tam ir jÄiestata parametrs izolÄcija.lÄ«menis uz read_committed vÄrtÄ«bu. Å Äds PatÄrÄtÄjs varÄs lasÄ«t ziÅojumus, kas nav saistÄ«ti ar darÄ«jumiem, tÄpat kÄ iepriekÅ”, un darÄ«jumu ziÅojumus tikai pÄc apÅemÅ”anÄs.
Ja esat iestatÄ«jis visus iepriekÅ” norÄdÄ«tos iestatÄ«jumus, tad esat konfigurÄjis tieÅ”i piegÄdes reizi. Apsveicam!
Bet ir vÄl viena nianse. Transaction.id, kuru mÄs konfigurÄjÄm iepriekÅ”, faktiski ir darÄ«juma prefikss. DarÄ«jumu pÄrvaldniekÄ tam tiek pievienots kÄrtas numurs. SaÅemtais identifikators tiek izsniegts transakcija.id.expiration.ms, kas ir konfigurÄts Kafka klasterÄ« un kura noklusÄjuma vÄrtÄ«ba ir ā7 dienasā. Ja Å”ajÄ laikÄ aplikÄcija nav saÅÄmusi nevienu ziÅojumu, tad, izmÄÄ£inot nÄkamo darÄ«juma sÅ«tÄ«jumu, jÅ«s saÅemsit InvalidPidMappingException. PÄc tam darÄ«juma koordinators nÄkamajam darÄ«jumam izsniegs jaunu kÄrtas numuru. TomÄr ziÅojums var tikt pazaudÄts, ja InvalidPidMappingException netiek pareizi apstrÄdÄts.
Kopsummu vietÄ
KÄ redzat, nepietiek vienkÄrÅ”i nosÅ«tÄ«t ziÅojumus Kafkai. Jums ir jÄizvÄlas parametru kombinÄcija un jÄbÅ«t gatavam Ätri veikt izmaiÅas. Å ajÄ rakstÄ es centos detalizÄti parÄdÄ«t precÄ«zu piegÄdes iestatÄ«Å”anu un aprakstÄ«ju vairÄkas problÄmas ar konfigurÄcijÄm client.id un transactional.id, ar kurÄm mÄs saskÄrÄmies. TÄlÄk ir sniegts ražotÄju un patÄrÄtÄju iestatÄ«jumu kopsavilkums.
RažotÄjs:
- acks = viss
- mÄÄ£inÄjumi > 0
- enable.idempotence = patiess
- max.in.flight.requests.per.connection ā¤ 5 (1 kÄrtÄ«gai nosÅ«tÄ«Å”anai)
- transakcijas.id = ${lietojumprogrammas nosaukums}-${saimniekdatora nosaukums}
PatÄrÄtÄjs:
- isolation.level = read_committed
Lai samazinÄtu kļūdas turpmÄkajÄs lietojumprogrammÄs, mÄs izveidojÄm paÅ”i savu aptinumu virs atsperes konfigurÄcijas, kur jau ir iestatÄ«tas vÄrtÄ«bas dažiem no uzskaitÄ«tajiem parametriem.
Å eit ir daži materiÄli paÅ”mÄcÄ«bai:
Avots: www.habr.com