Hvernig Kafka varð að veruleika

Hvernig Kafka varð að veruleika

Hæ Habr!

Ég vinn í Tinkoff teyminu, sem er að þróa sína eigin tilkynningamiðstöð. Ég þróa að mestu í Java með Spring boot og leysi ýmis tæknileg vandamál sem koma upp í verkefni.

Flestar örþjónustur okkar hafa samskipti sín á milli ósamstillt í gegnum skilaboðamiðlara. Áður fyrr notuðum við IBM MQ sem miðlara sem réði ekki lengur við álagið en var á sama tíma með háar sendingartryggingar.

Í staðinn var okkur boðið Apache Kafka, sem hefur mikla stærðarmöguleika, en því miður krefst nánast einstaklingsbundinnar nálgun við uppsetningu fyrir mismunandi aðstæður. Að auki, að minnsta kosti einu sinni afhendingarbúnaður sem virkar í Kafka sjálfgefið, leyfði ekki að viðhalda tilskildu samræmi út úr kassanum. Næst mun ég deila reynslu okkar af Kafka stillingum, sérstaklega mun ég segja þér hvernig á að stilla og lifa með nákvæmlega einu sinni afhendingu.

Ábyrgð afhending og fleira

Stillingarnar sem fjallað er um hér að neðan munu hjálpa til við að koma í veg fyrir fjölda vandamála með sjálfgefnar tengingarstillingar. En fyrst langar mig að gefa gaum að einni breytu sem mun auðvelda hugsanlega villuleit.

Þetta mun hjálpa viðskiptavinur.auðkenni fyrir framleiðanda og neytendur. Við fyrstu sýn geturðu notað nafn forritsins sem gildi og í flestum tilfellum mun þetta virka. Þó að ástandið þegar forrit notar nokkra neytendur og þú gefur þeim sama client.id, leiðir af sér eftirfarandi viðvörun:

org.apache.kafka.common.utils.AppInfoParser — Error registering AppInfo mbean javax.management.InstanceAlreadyExistsException: kafka.consumer:type=app-info,id=kafka.test-0

Ef þú vilt nota JMX í forriti með Kafka, þá gæti þetta verið vandamál. Í þessu tilviki er best að nota blöndu af heiti forritsins og til dæmis heiti efnisins sem client.id gildi. Árangurinn af uppsetningu okkar má sjá í skipunarúttakinu kafka-neytendahópar frá veitum frá Confluent:

Hvernig Kafka varð að veruleika

Nú skulum við líta á atburðarásina fyrir tryggða sendingu skilaboða. Kafka framleiðandi hefur færibreytu akks, sem gerir þér kleift að stilla eftir hversu margar viðurkenningar klasaleiðtoginn þarf til að íhuga skilaboðin sem hafa verið skrifuð. Þessi færibreyta getur tekið eftirfarandi gildi:

  • 0 — viðurkenning verður ekki tekin til greina.
  • 1 er sjálfgefin færibreyta, aðeins 1 eftirmynd þarf til að staðfesta.
  • −1 — þarf að staðfesta frá öllum samstilltum eftirmyndum (þyrpingauppsetning mín.insync.eftirmyndir).

Af skráðum gildum er ljóst að acks jafnt og −1 gefur sterkustu tryggingu fyrir því að skilaboðin glatist ekki.

Eins og við vitum öll eru dreifð kerfi óáreiðanleg. Til að verjast tímabundnum bilunum, veitir Kafka framleiðandi möguleikann reynir aftur, sem gerir þér kleift að stilla fjölda endursendu tilrauna innan afhendingartími.ms. Þar sem færibreytan fyrir endurtilraunir hefur sjálfgefið gildi Heiltala.MAX_VALUE (2147483647), er hægt að breyta fjölda endurtilrauna skilaboða með því að breyta aðeins delivery.timeout.ms.

Við erum að fara í átt að afhendingu nákvæmlega einu sinni

Upptaldar stillingar gera framleiðanda okkar kleift að koma skilaboðum til skila með mikilli ábyrgð. Við skulum nú tala um hvernig á að tryggja að aðeins eitt eintak af skilaboðum sé skrifað í Kafka efni? Í einfaldasta tilvikinu, til að gera þetta, þarftu að stilla færibreytuna á Producer enable.idempotence að satt. Idempotency tryggir að aðeins ein skilaboð eru skrifuð á tiltekna skiptingu eins efnis. Forsenda þess að hægt sé að virkja getuleysi eru gildin acks = allt, reyndu aftur > 0, hámarksbeiðnir í flugi á hverja tengingu ≤ 5. Ef þessar breytur eru ekki tilgreindar af verktaki, verða ofangreind gildi sjálfkrafa stillt.

Þegar idempotency er stillt er nauðsynlegt að tryggja að sömu skilaboðin lendi í sömu skiptingum í hvert skipti. Þetta er hægt að gera með því að stilla partitioner.class lykilinn og færibreytuna á Producer. Byrjum á lyklinum. Það verður að vera það sama fyrir hverja sendingu. Þetta er auðveldlega hægt að ná með því að nota hvaða viðskiptaauðkenni sem er frá upprunalegu færslunni. Færibreytan partitioner.class hefur sjálfgefið gildi - Default Partitioner. Með þessari skiptingarstefnu hegðum við sjálfgefið svona:

  • Ef skiptingin er sérstaklega tilgreind þegar skilaboðin eru send, þá notum við það.
  • Ef skiptingin er ekki tilgreind, en lykillinn er tilgreindur, veldu skiptinguna með kjötkássa lykilsins.
  • Ef skiptingin og lykillinn eru ekki tilgreindir skaltu velja skiptingarnar eitt í einu (round-robin).

Einnig, með því að nota lykil og ídempotent sendingu með færibreytu max.in.flight.requests.per.connection = 1 veitir þér straumlínulagaða skilaboðavinnslu hjá neytanda. Það er líka þess virði að muna að ef aðgangsstýring er stillt á klasanum þínum, þá þarftu réttindi til að skrifa af sjálfsdáðum um efni.

Ef skyndilega skortir þig hæfileikann til að senda með lykli eða rökfræðin á framleiðandahliðinni krefst þess að viðhalda gagnasamræmi milli mismunandi skiptinga, þá munu viðskipti koma til bjargar. Að auki, með því að nota keðjuviðskipti, geturðu samstillt færslu í Kafka með skilyrðum, til dæmis við færslu í gagnagrunninum. Til að hægt sé að senda færslur til framleiðandans verður hún að vera óstyrk og stillt til viðbótar viðskipta.auðkenni. Ef Kafka þyrpingin þín er með aðgangsstýringu stillt, þá mun viðskiptaskrá, eins og idempotent skrá, þurfa skrifheimildir, sem hægt er að veita með grímu með því að nota gildið sem er geymt í transactional.id.

Formlega er hægt að nota hvaða streng sem er, eins og nafn forritsins, sem færsluauðkenni. En ef þú ræsir nokkur tilvik af sama forriti með sama transactional.id, þá verður fyrsta tilvikið stöðvað með villu, þar sem Kafka mun líta á það sem uppvakningaferli.

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.

Til að leysa þetta vandamál bætum við viðskeyti við nafn forritsins í formi hýsingarheitisins, sem við fáum úr umhverfisbreytum.

Framleiðandinn er stilltur, en viðskipti á Kafka stjórna aðeins umfangi skilaboðanna. Burtséð frá færslustöðunni fara skilaboðin strax í umræðuefnið en hafa fleiri kerfiseiginleika.

Til að koma í veg fyrir að slík skilaboð séu lesin af neytanda fyrirfram þarf hann að stilla færibreytuna einangrun.stig til read_committed gildi. Slíkur neytandi mun geta lesið skilaboð sem ekki eru viðskipti eins og áður, og viðskiptaskilaboð aðeins eftir skuldbindingu.
Ef þú hefur stillt allar stillingar sem taldar voru upp fyrr, þá hefur þú stillt nákvæmlega einu sinni afhendingu. Til hamingju!

En það er enn eitt blæbrigðið. Transactional.id, sem við stilltum hér að ofan, er í raun viðskiptaforskeytið. Á viðskiptastjóranum er raðnúmeri bætt við hann. Móttekið auðkenni er gefið út til transactional.id.expiration.ms, sem er stillt á Kafka þyrping og hefur sjálfgefið gildi „7 dagar“. Ef á þessum tíma hefur forritið ekki fengið nein skilaboð, þá færðu þegar þú reynir næstu viðskiptasendingu InvalidPidMappingException. Viðskiptastjóri gefur síðan út nýtt raðnúmer fyrir næstu færslu. Hins vegar geta skilaboðin glatast ef InvalidPidMappingException er ekki meðhöndlað á réttan hátt.

Í stað samtals

Eins og þú sérð er ekki nóg að senda bara skilaboð til Kafka. Þú þarft að velja blöndu af breytum og vera tilbúinn til að gera skjótar breytingar. Í þessari grein reyndi ég að sýna í smáatriðum uppsetninguna nákvæmlega einu sinni og lýsti nokkrum vandamálum með client.id og transactional.id stillingarnar sem við lentum í. Hér að neðan er samantekt á stillingum framleiðanda og neytenda.

Leikstjóri:

  1. acks = allt
  2. reynir aftur > 0
  3. enable.idempotence = satt
  4. max.in.flight.requests.per.connection ≤ 5 (1 fyrir skipulega sendingu)
  5. transactional.id = ${application-name}-${hostname}

Neytandi:

  1. isolation.level = read_committed

Til að lágmarka villur í framtíðarforritum, bjuggum við til okkar eigin umbúðir yfir vorstillingarnar, þar sem gildi fyrir sumar af breytunum sem eru skráðar eru þegar stillt.

Hér eru nokkur efni til sjálfsnáms:

Heimild: www.habr.com

Bæta við athugasemd