Кафка хэрхэн бодит байдал болсон

Кафка хэрхэн бодит байдал болсон

Хөөе Хабр!

Би өөрийн мэдэгдлийн төвийг хөгжүүлж буй Tinkoff багт ажилладаг. Би ихэвчлэн Spring boot ашиглан Java хэлийг хөгжүүлж, төсөл дээр гарч буй техникийн янз бүрийн асуудлыг шийддэг.

Манай микро үйлчилгээнүүдийн ихэнх нь мессеж брокероор дамжуулан бие биетэйгээ асинхрон байдлаар харилцдаг. Өмнө нь бид 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-тэй тэнцэх хэмжээ нь мессеж алдагдахгүй байх баталгааг өгдөг.

Бидний мэдэж байгаагаар тархсан системүүд найдваргүй байдаг. Түр зуурын алдаанаас хамгаалахын тулд Кафка Продюсер сонголтыг санал болгодог дахин оролдоно, энэ нь танд дахин илгээх оролдлогын тоог тохируулах боломжийг олгодог хүргэх.цаг хугацаа хэтэрсэн.мс. Дахин оролдох параметр нь Integer.MAX_VALUE (2147483647) гэсэн өгөгдмөл утгатай тул мессеж дахин оролдох тоог зөвхөн delivery.timeout.ms-г өөрчлөх замаар тохируулж болно.

Бид яг нэг удаа хүргэлт рүү явж байна

Жагсаалтад орсон тохиргоонууд нь манай Продюсерийг өндөр баталгаатай мессеж хүргэх боломжийг олгодог. Одоо Кафкагийн сэдэвт мессежийн зөвхөн нэг хуулбар бичигдсэн эсэхийг хэрхэн баталгаажуулах талаар ярилцъя? Хамгийн энгийн тохиолдолд үүнийг хийхийн тулд та Producer дээр параметрийг тохируулах хэрэгтэй идэвхжүүлэх.idempotence үнэн рүү. Idempotency нь нэг сэдвийн тодорхой хэсэг рүү зөвхөн нэг мессеж бичигдэхийг баталгаажуулдаг. Идпотенцийг идэвхжүүлэх урьдчилсан нөхцөл бол үнэт зүйлс юм acks = бүгд, дахин оролдоно уу > 0, max.in.flight.requests.per.connection ≤ 5. Хэрэв эдгээр параметрүүдийг хөгжүүлэгч заагаагүй бол дээрх утгыг автоматаар тохируулах болно.

Idempotency-г тохируулах үед ижил зурвасууд ижил хуваалтууд дээр дуусдаг байх ёстой. Үүнийг partitioner.class түлхүүр болон параметрийг Producer болгож тохируулж болно. Түлхүүрээс эхэлцгээе. Энэ нь мэдүүлэг болгонд ижил байх ёстой. Анхны нийтлэл дээрх бизнесийн ID-г ашиглан үүнийг хялбархан хийж болно. Partitioner.class параметр нь анхдагч − утгатай байна DefaultPartitioner. Энэхүү хуваах стратегийн тусламжтайгаар бид анхдагч байдлаар дараах байдлаар ажилладаг:

  • Хэрэв мессеж илгээхдээ хуваалтыг тодорхой зааж өгсөн бол бид үүнийг ашигладаг.
  • Хэрэв хуваалтыг заагаагүй боловч түлхүүрийг зааж өгсөн бол түлхүүрийн хэшээр хуваалтыг сонгоно уу.
  • Хэрэв хуваалт болон түлхүүрийг заагаагүй бол хуваалтуудыг нэг нэгээр нь сонгоно уу (дугуй).

Мөн параметр бүхий түлхүүр болон idempotent илгээлтийг ашиглан max.in.flight.requests.per.connection = 1 Хэрэглэгчийн мессежийг хялбархан боловсруулах боломжийг танд олгоно. Хэрэв таны кластер дээр хандалтын хяналт тохируулагдсан бол тухайн сэдэв рүү шууд бичих эрх хэрэгтэй болно гэдгийг санах нь зүйтэй.

Хэрэв та гэнэт түлхүүрээр idempotent илгээх чадваргүй бол эсвэл Продюсер талын логик нь өөр өөр хуваалтуудын хооронд өгөгдлийн нийцтэй байдлыг хангах шаардлагатай бол гүйлгээ нь аврах ажилд ирнэ. Нэмж дурдахад, гинжин гүйлгээг ашиглан та Кафка дахь бичлэгийг, жишээлбэл, мэдээллийн сан дахь бичлэгтэй нөхцөлт байдлаар синхрончлох боломжтой. Үйлдвэрлэгч рүү гүйлгээний илгээлтийг идэвхжүүлэхийн тулд энэ нь идэвхгүй бөгөөд нэмэлт тохируулагдсан байх ёстой transactional.id. Хэрэв таны Кафка кластерт хандалтын хяналт тохируулагдсан бол гүйлгээний бүртгэлд idempotent бичлэг гэх мэт бичих эрх шаардлагатай бөгөөд энэ нь 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.

Энэ асуудлыг шийдэхийн тулд бид орчны хувьсагчдаас олж авсан хостын нэр хэлбэрээр програмын нэрэнд дагавар нэмдэг.

Үйлдвэрлэгчийг тохируулсан боловч Кафка дээрх гүйлгээ нь зөвхөн мессежийн хамрах хүрээг хянадаг. Гүйлгээний статусаас үл хамааран мессеж нь тухайн сэдэв рүү шууд очдог боловч системийн нэмэлт шинж чанаруудтай.

Хэрэглэгч ийм мессежийг урьдчилан уншихаас урьдчилан сэргийлэхийн тулд параметрийг тохируулах шаардлагатай тусгаарлалт.түвшин уншсан_утга. Ийм Хэрэглэгч гүйлгээний бус мессежийг өмнөх шигээ, гүйлгээний мессежийг зөвхөн амлалт хийсний дараа унших боломжтой болно.
Хэрэв та өмнө нь жагсаасан бүх тохиргоог хийсэн бол яг нэг удаа хүргэлтийг тохируулсан болно. Баяр хүргэе!

Гэхдээ бас нэг нюанс бий. Бидний дээр тохируулсан Transactional.id нь үнэндээ гүйлгээний угтвар юм. Гүйлгээний менежер дээр дарааллын дугаар нэмэгдэнэ. Хүлээн авсан таних тэмдэг нь өгөгдсөн гүйлгээний.id.хугацаа.ms, Кафка кластер дээр тохируулагдсан бөгөөд анхдагч утга нь "7 хоног". Хэрэв энэ хугацаанд програм ямар ч мессеж хүлээн аваагүй бол дараагийн гүйлгээний илгээмжийг оролдох үед та хүлээн авах болно InvalidPidMappingException. Дараа нь гүйлгээний зохицуулагч дараагийн гүйлгээнд зориулж шинэ дарааллын дугаар олгоно. Гэсэн хэдий ч, 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}-${hostname}

Хэрэглэгч:

  1. тусгаарлах.level = уншсан_комmitted

Ирээдүйн хэрэглээний алдааг багасгахын тулд бид жагсаалтад орсон зарим параметрийн утгыг аль хэдийн тохируулсан хаврын тохиргоон дээр өөрийн боодолтой болгосон.

Бие даан суралцах хэд хэдэн материал энд байна.

Эх сурвалж: www.habr.com

сэтгэгдэл нэмэх