Чӣ тавр Кафка ба воқеият табдил ёфт

Чӣ тавр Кафка ба воқеият табдил ёфт

Эй Ҳабр!

Ман дар дастаи Tinkoff кор мекунам, ки маркази огоҳии худро таҳия мекунад. Ман асосан дар Java бо истифода аз пурборкунии Spring таҳия мекунам ва мушкилоти гуногуни техникиеро, ки дар лоиҳа ба миён меоянд, ҳал мекунам.

Аксарияти микросервисҳои мо тавассути брокери паёмӣ бо ҳамдигар асинхронӣ муошират мекунанд. Пештар, мо IBM MQ-ро ҳамчун брокер истифода мебурдем, ки дигар аз ӯҳдаи сарборӣ баромада наметавонист, аммо дар айни замон кафолати интиқоли баланд дошт.

Ҳамчун ивазкунанда, ба мо Apache Kafka пешниҳод карда шуд, ки потенсиали баланди миқёсӣ дорад, аммо, мутаассифона, муносибати қариб инфиродӣ ба конфигуратсия барои сенарияҳои гуногунро талаб мекунад. Илова бар ин, механизми интиқоли ҳадди аққал як маротиба, ки дар Кафка ба таври нобаёнӣ кор мекунад, имкон намедиҳад, ки сатҳи зарурии мувофиқат аз қуттӣ нигоҳ дошта шавад. Минбаъд, ман таҷрибаи худро дар конфигуратсияи Кафка мубодила мекунам, аз ҷумла, ман ба шумо мегӯям, ки чӣ гуна конфигуратсия кардан ва зиндагӣ карданро бо як маротиба интиқол додан мумкин аст.

Интиқоли кафолатнок ва ғайра

Танзимоте, ки дар зер баррасӣ мешаванд, барои пешгирӣ кардани як қатор мушкилот бо танзимоти пайвасти пешфарз кӯмак мекунанд. Аммо аввал ман мехоҳам ба як параметр диққат диҳам, ки ислоҳи имконпазирро осон мекунад.

Ин кӯмак хоҳад кард client.id барои истеҳсолкунанда ва истеъмолкунанда. Дар назари аввал, шумо метавонед номи барномаро ҳамчун арзиш истифода баред ва дар аксари ҳолатҳо ин кор хоҳад кард. Гарчанде ки вазъияте, ки барнома якчанд истеъмолкунандагонро истифода мебарад ва шумо ба онҳо ҳамон як client.id медиҳед, боиси огоҳии зерин мегардад:

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

Агар шумо хоҳед, ки JMX-ро дар барнома бо Кафка истифода баред, пас ин метавонад мушкилот бошад. Барои ин ҳолат, беҳтар аст, ки маҷмӯи номи барнома ва масалан, номи мавзӯъро ҳамчун арзиши client.id истифода баред. Натиҷаи конфигуратсияи моро дар баромади фармон дидан мумкин аст кафка-гуруххои истеъмолкунандагон аз коммуналӣ аз Confluent:

Чӣ тавр Кафка ба воқеият табдил ёфт

Акнун биёед ба сенарияи расонидани кафолати паём назар кунем. Кафка Продюсер параметр дорад акс, ки ба шумо имкон медиҳад конфигуратсия кунед, ки пас аз чанд эътироф кардани роҳбари кластер паёмро бомуваффақият навишташуда баррасӣ кунед. Ин параметр метавонад арзишҳои зеринро гирад:

  • 0 — эътироф ба назар гирифта намешавад.
  • 1 параметри пешфарз аст, барои эътироф танҳо 1 нусха лозим аст.
  • −1 — аз ҳама репликаҳои ҳамоҳангшуда тасдиқ кардан лозим аст (танзими кластер min.insync.replicas).

Аз арзишҳои номбаршуда маълум аст, ки аксҳои баробар ба −1 кафолати қавитаринро медиҳад, ки паём гум намешавад.

Тавре ки ҳамаи мо медонем, системаҳои тақсимшуда эътимоднок нестанд. Барои муҳофизат аз хатогиҳои муваққатӣ, Kafka Producer имкон медиҳад бори дигар кушиш мекунад, ки ба шумо имкон медиҳад, ки шумораи кӯшишҳои ирсоли дубораро дар дохили он муқаррар кунед teslim.timeout.ms. Азбаски параметри такрорӣ арзиши пешфарзии Integer.MAX_VALUE (2147483647) дорад, шумораи кӯшишҳои такрории паёмро бо роҳи тағир додани танҳо delivery.timeout.ms танзим кардан мумкин аст.

Мо ба сӯи як бор интиқол ҳаракат мекунем

Танзимоти номбаршуда ба Истеҳсолкунандаи мо имкон медиҳад, ки паёмҳоро бо кафолати баланд расонад. Акнун биёед дар бораи он сӯҳбат кунем, ки чӣ гуна бояд танҳо як нусхаи паём ба мавзӯи Кафка навишта шавад? Дар соддатарин ҳолат, барои ин кор, шумо бояд параметрро дар Истеҳсолкунанда насб кунед фаъол кардан.қудрат ба ростӣ. Имконият кафолат медиҳад, ки танҳо як паём ба қисмати мушаххаси як мавзӯъ навишта мешавад. Шарти пешакии имкон додани номутаносибӣ арзишҳо мебошанд acks = ҳама, такрор кардан > 0, max.in.flight.requests.per.connection ≤ 5. Агар ин параметрҳо аз ҷониби таҳиякунанда муайян нашуда бошанд, арзишҳои дар боло овардашуда ба таври худкор муқаррар карда мешаванд.

Вақте ки idempotency танзим карда мешавад, боварӣ ҳосил кардан лозим аст, ки ҳамон як паёмҳо ҳар дафъа дар як қисмҳо хотима меёбанд. Инро тавассути гузоштани калиди partitioner.class ва параметр ба Истеҳсолкунанда анҷом додан мумкин аст. Биёед бо калид оғоз кунем. Он бояд барои ҳар як пешниҳод якхела бошад. Инро бо истифода аз ҳама гуна ID-ҳои тиҷоратӣ аз паёми аслӣ ба осонӣ ба даст овардан мумкин аст. Параметри partitioner.class арзиши пешфарз дорад - DefaultPartitioner. Бо ин стратегияи тақсимкунӣ, мо ба таври нобаёнӣ чунин амал мекунем:

  • Агар қисмат ҳангоми фиристодани паём ба таври возеҳ муайян карда шавад, мо онро истифода мебарем.
  • Агар қисмат муайян нашуда бошад, аммо калид муайян карда шуда бошад, қисмро аз рӯи хэши калид интихоб кунед.
  • Агар қисмат ва калид муайян нашуда бошад, қисмҳоро як ба як интихоб кунед (давр-робин).

Ҳамчунин, бо истифода аз як калид ва ирсол idempotent бо параметр max.in.flight.requests.per.connection = 1 ба шумо коркарди соддашудаи паёмро дар Истеъмолкунанда медиҳад. Инчунин бояд дар хотир дошт, ки агар назорати дастрасӣ дар кластери шумо танзим карда шуда бошад, пас ба шумо ҳуқуқ барои беэҳтиётона навиштан ба мавзӯъ лозим мешавад.

Агар шумо ногаҳон қобилияти фиристодани идемпотент бо калид надошта бошед ё мантиқи тарафи Продюсер нигоҳ доштани мутобиқати маълумотро байни қисмҳои гуногун талаб кунад, пас транзаксияҳо ба наҷот меоянд. Илова бар ин, бо истифода аз амалиёти занҷирӣ, шумо метавонед шартан сабтро дар Кафка, масалан, бо сабт дар базаи маълумот ҳамоҳанг созед. Барои фаъол кардани ирсоли транзаксия ба Истеҳсолкунанда, он бояд беимзо бошад ва ба таври иловагӣ муқаррар карда шавад transactional.id. Агар кластери Кафкаи шумо назорати дастрасиро танзим карда бошад, пас сабти транзаксионӣ, ба монанди сабти идемпотент, бояд иҷозати навиштанро дошта бошад, ки онҳоро метавон бо истифодаи ниқоб бо истифода аз арзиши дар transactional.id нигоҳ доштан дод.

Ба таври расмӣ, ҳама гуна сатр, ба монанди номи барнома, метавонад ҳамчун муайянкунандаи транзаксия истифода шавад. Аммо агар шумо якчанд мисоли ҳамон як барномаро бо ҳамон transactional.id оғоз кунед, пас намунаи аввалини оғозшуда бо хато қатъ карда мешавад, зеро Кафка онро раванди зомби мешуморад.

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.

Барои ҳалли ин мушкилот, мо ба номи барнома суффиксро дар шакли номи мизбон илова мекунем, ки мо онро аз тағирёбандаҳои муҳити зист мегирем.

Истеҳсолкунанда танзим шудааст, аммо транзаксияҳо дар Кафка танҳо доираи паёмро назорат мекунанд. Новобаста аз вазъи транзаксия, паём фавран ба мавзӯъ меравад, аммо дорои атрибутҳои иловагии система мебошад.

Барои пешгирӣ кардани хондани чунин паёмҳо аз ҷониби Истеъмолкунанда, он бояд параметрро муқаррар кунад изолятсия.сатҳи ба арзиши read_committed. Чунин Истеъмолкунанда метавонад паёмҳои транзаксиониро мисли пештара ва паёмҳои транзаксиониро танҳо пас аз анҷом додани ӯҳдадорӣ хонад.
Агар шумо ҳамаи танзимоти дар боло номбаршударо муқаррар карда бошед, пас шумо маҳз як маротиба интиқолро танзим кардаед. Табрик мекунем!

Аммо як нозукии дигар вуҷуд дорад. Transactional.id, ки мо дар боло танзим кардем, воқеан префикси транзаксия аст. Дар мудири транзаксия рақами пайдарпай ба он илова карда мешавад. Идентификатори гирифташуда ба transactional.id.expiration.ms, ки дар кластери Кафка танзим шудааст ва арзиши пешфарз "7 рӯз" дорад. Агар дар давоми ин муддат барнома ягон паём нагирифта бошад, пас ҳангоми кӯшиши интиқоли навбатии транзаксия шумо қабул хоҳед кард Истиснои InvalidPidMapping. Ҳамоҳангсози транзаксия пас аз он рақами пайдарпайии навро барои амалиёти навбатӣ медиҳад. Аммо, агар InvalidPidMappingException дуруст коркард нашавад, паём метавонад гум шавад.

Ба ҷои натиҷаҳо

Тавре ки шумо мебинед, танҳо фиристодани паём ба Кафка кофӣ нест. Шумо бояд маҷмӯи параметрҳоро интихоб кунед ва барои тағир додани зуд омода бошед. Дар ин мақола, ман кӯшиш кардам, ки ба таври муфассал танзимоти интиқолро як маротиба нишон диҳам ва якчанд мушкилотро бо конфигуратсияҳои client.id ва transactional.id, ки мо дучор шудаем, тавсиф намоям. Дар зер мухтасари танзимоти Истеҳсолкунанда ва Истеъмолкунанда оварда шудааст.

Истеҳсолкунанда:

  1. acks = ҳама
  2. такрор > 0
  3. enable.idempotence = ҳақиқӣ
  4. max.in.flight.requests.per.connection ≤ 5 (1 барои ирсоли бо тартиб)
  5. transactional.id = ${application-name}-${stname}

Истеъмолкунанда:

  1. isolation.level = read_committed

Барои кам кардани хатогиҳо дар замимаҳои оянда, мо дар конфигуратсияи баҳорӣ печони худро сохтем, ки дар он арзишҳо барои баъзе параметрҳои номбаршуда аллакай муқаррар карда шудаанд.

Инҳоянд якчанд мавод барои омӯзиши мустақилона:

Манбаъ: will.com

Илова Эзоҳ