Jinsi Kafka ikawa ukweli

Jinsi Kafka ikawa ukweli

Habari Habr!

Ninafanya kazi kwenye timu ya Tinkoff, ambayo inaunda kituo chake cha arifa. Mimi huendeleza zaidi katika Java kwa kutumia Boot ya Spring na kutatua shida kadhaa za kiufundi zinazotokea kwenye mradi.

Huduma zetu nyingi ndogo huwasiliana kwa njia isiyosawazisha kupitia wakala wa ujumbe. Hapo awali, tulitumia IBM MQ kama wakala, ambayo haikuweza tena kukabiliana na mzigo, lakini wakati huo huo ilikuwa na dhamana ya juu ya utoaji.

Kama mbadala, tulipewa Apache Kafka, ambayo ina uwezo wa juu wa kuongeza alama, lakini, kwa bahati mbaya, inahitaji mbinu ya mtu binafsi ya usanidi wa hali tofauti. Kwa kuongeza, utaratibu wa utoaji wa angalau mara moja ambao hufanya kazi katika Kafka kwa chaguo-msingi haukuruhusu kudumisha kiwango kinachohitajika cha uthabiti nje ya boksi. Ifuatayo, nitashiriki uzoefu wetu katika usanidi wa Kafka, haswa, nitakuambia jinsi ya kusanidi na kuishi na utoaji mara moja.

Usafirishaji uliohakikishwa na zaidi

Mipangilio iliyojadiliwa hapa chini itasaidia kuzuia idadi ya matatizo na mipangilio ya uunganisho wa chaguo-msingi. Lakini kwanza ningependa kulipa kipaumbele kwa parameter moja ambayo itawezesha utatuzi unaowezekana.

Hii itasaidia mteja.id kwa Mtayarishaji na Mtumiaji. Kwa mtazamo wa kwanza, unaweza kutumia jina la programu kama thamani, na katika hali nyingi hii itafanya kazi. Ingawa hali wakati programu inatumia Wateja kadhaa na unawapa client.id sawa, husababisha onyo lifuatalo:

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

Ikiwa unataka kutumia JMX katika programu na Kafka, basi hii inaweza kuwa shida. Kwa kesi hii, ni bora kutumia mchanganyiko wa jina la programu na, kwa mfano, jina la mada kama thamani ya mteja.id. Matokeo ya usanidi wetu yanaweza kuonekana katika pato la amri kafka-makundi-ya watumiaji kutoka kwa huduma kutoka kwa Confluent:

Jinsi Kafka ikawa ukweli

Sasa hebu tuangalie hali ya uwasilishaji wa ujumbe wa uhakika. Mtayarishaji wa Kafka ana kigezo acks, ambayo hukuruhusu kusanidi baada ya ngapi kukiri kiongozi wa nguzo anahitaji kuzingatia ujumbe ulioandikwa kwa mafanikio. Kigezo hiki kinaweza kuchukua maadili yafuatayo:

  • 0 - kukiri haitazingatiwa.
  • 1 ndio kigezo chaguo-msingi, nakala 1 pekee inahitajika ili kukiri.
  • βˆ’1 - kubali kutoka kwa nakala zote zilizosawazishwa inahitajika (usanidi wa nguzo min.insync.replicas).

Kutoka kwa maadili yaliyoorodheshwa ni wazi kuwa acks sawa na -1 inatoa hakikisho kali zaidi kwamba ujumbe hautapotea.

Kama sisi sote tunajua, mifumo iliyosambazwa sio ya kuaminika. Ili kulinda dhidi ya makosa ya muda mfupi, Kafka Producer hutoa chaguo hujaribu tena, ambayo hukuruhusu kuweka idadi ya majaribio ya kutuma tena ndani uwasilishaji.wakati umeisha.ms. Kwa kuwa kigezo cha kujaribu tena kina thamani chaguomsingi ya Integer.MAX_VALUE (2147483647), idadi ya ujumbe unaojaribu inaweza kurekebishwa kwa kubadilisha delivery.timeout.ms pekee.

Tunasonga kuelekea utoaji mara moja

Mipangilio iliyoorodheshwa huruhusu Mtayarishaji wetu kuwasilisha ujumbe kwa dhamana ya juu. Hebu sasa tuzungumze kuhusu jinsi ya kuhakikisha kwamba nakala moja tu ya ujumbe imeandikwa kwa mada ya Kafka? Katika kesi rahisi zaidi, kwa kufanya hivyo, unahitaji kuweka parameter kwenye Mtayarishaji wezesha.kutokuwa na uwezo kwa kweli. Idempotency inahakikisha kwamba ujumbe mmoja tu umeandikwa kwa sehemu maalum ya mada moja. Masharti ya kuwezesha ujinga ni maadili acks = yote, jaribu tena > 0, max.in.flight.requests.per.connection ≀ 5. Ikiwa vigezo hivi havijabainishwa na msanidi programu, maadili yaliyo hapo juu yatawekwa kiotomatiki.

Wakati hali ya kutokuwa na uwezo imesanidiwa, ni muhimu kuhakikisha kuwa ujumbe sawa unaishia katika sehemu zinazofanana kila wakati. Hii inaweza kufanywa kwa kuweka kitufe cha partitioner.class na parameta kwa Producer. Hebu tuanze na ufunguo. Lazima iwe sawa kwa kila uwasilishaji. Hili linaweza kufikiwa kwa urahisi kwa kutumia kitambulisho chochote cha biashara kutoka kwa chapisho asili. Kigezo cha partitioner.class kina thamani chaguo-msingi - DefaultPartitioner. Kwa mkakati huu wa kugawa, kwa chaguo-msingi tunafanya kama hii:

  • Ikiwa kizigeu kimeainishwa wazi wakati wa kutuma ujumbe, basi tunaitumia.
  • Ikiwa ugawaji haujainishwa, lakini ufunguo umeelezwa, chagua kizigeu na hashi ya ufunguo.
  • Ikiwa kizigeu na ufunguo hazijaainishwa, chagua sehemu moja baada ya nyingine (robin ya pande zote).

Pia, kwa kutumia ufunguo na utumaji usio na uwezo na parameta max.in.flight.requests.per.connection = 1 hukupa uchakataji wa ujumbe uliorahisishwa kwenye Mtumiaji. Inafaa pia kukumbuka kuwa ikiwa udhibiti wa ufikiaji umesanidiwa kwenye nguzo yako, basi utahitaji haki za kuandika kwa mada bila kujali.

Ikiwa ghafla unakosa uwezo wa kutuma bila uwezo kwa ufunguo au mantiki kwenye upande wa Mtayarishaji inahitaji kudumisha uwiano wa data kati ya sehemu tofauti, basi shughuli zitakuokoa. Kwa kuongezea, kwa kutumia shughuli ya mnyororo, unaweza kusawazisha rekodi huko Kafka, kwa mfano, na rekodi kwenye hifadhidata. Ili kuwezesha utumaji wa muamala kwa Mtayarishaji, lazima kiwe kisicho na uwezo na kiweke zaidi muamala.id. Ikiwa nguzo yako ya Kafka ina udhibiti wa ufikiaji uliosanidiwa, basi rekodi ya muamala, kama rekodi isiyo na uwezo, itahitaji ruhusa za kuandika, ambazo zinaweza kutolewa kwa barakoa kwa kutumia thamani iliyohifadhiwa katika transactional.id.

Rasmi, mfuatano wowote, kama vile jina la programu, unaweza kutumika kama kitambulisho cha muamala. Lakini ukizindua matukio kadhaa ya programu sawa na transactional.id sawa, basi tukio la kwanza lililozinduliwa litasimamishwa na hitilafu, kwani Kafka itazingatia kuwa mchakato wa zombie.

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.

Ili kutatua tatizo hili, tunaongeza kiambishi kwa jina la programu kwa namna ya jina la mwenyeji, ambalo tunapata kutoka kwa vigezo vya mazingira.

Mtayarishaji amesanidiwa, lakini miamala kwenye Kafka inadhibiti tu upeo wa ujumbe. Bila kujali hali ya manunuzi, ujumbe mara moja huenda kwenye mada, lakini una sifa za ziada za mfumo.

Ili kuzuia ujumbe kama huo kusomwa na Mtumiaji kabla ya wakati, inahitaji kuweka kigezo kiwango.kutengwa kusoma_thamani uliyojitolea. Mtumiaji kama huyo ataweza kusoma jumbe zisizo za miamala kama hapo awali, na jumbe za miamala baada tu ya ahadi.
Ikiwa umeweka mipangilio yote iliyoorodheshwa mapema, basi umesanidi uwasilishaji mara moja. Hongera!

Lakini kuna nuance moja zaidi. Transactional.id, ambayo tulisanidi hapo juu, ndiyo kiambishi awali cha muamala. Kwenye kidhibiti cha shughuli, nambari ya mlolongo huongezwa kwake. Kitambulisho kilichopokelewa kinatolewa kwa muamala.id.expiration.ms, ambayo imesanidiwa kwenye kundi la Kafka na ina thamani chaguo-msingi ya "siku 7". Ikiwa wakati huu programu haijapokea ujumbe wowote, basi unapojaribu kutuma muamala unaofuata utapokea InvalidPidMappingException. Mratibu wa shughuli kisha atatoa nambari mpya ya mfuatano kwa muamala unaofuata. Hata hivyo, ujumbe unaweza kupotea ikiwa InvalidPidMappingException haitashughulikiwa ipasavyo.

Badala ya matokeo

Kama unaweza kuona, haitoshi tu kutuma ujumbe kwa Kafka. Unahitaji kuchagua mchanganyiko wa vigezo na uwe tayari kufanya mabadiliko ya haraka. Katika makala haya, nilijaribu kuonyesha kwa undani usanidi wa uwasilishaji mara moja haswa na nikaelezea shida kadhaa na usanidi wa client.id na transactional.id ambao tulikumbana nao. Ufuatao ni muhtasari wa mipangilio ya Mtayarishaji na Mtumiaji.

Mzalishaji:

  1. acks = wote
  2. inajaribu tena > 0
  3. wezesha.upungufu = kweli
  4. max.in.flight.requests.per.connection ≀ 5 (1 kwa ajili ya kutuma kwa utaratibu)
  5. transactional.id = ${application-name}-${hostname}

Mtumiaji:

  1. kujitenga.level = kusoma_kujitolea

Ili kupunguza makosa katika programu za siku zijazo, tulitengeneza karatasi yetu wenyewe juu ya usanidi wa msimu wa joto, ambapo maadili ya baadhi ya vigezo vilivyoorodheshwa tayari yamewekwa.

Hapa kuna nyenzo kadhaa za kujisomea:

Chanzo: mapenzi.com

Kuongeza maoni