කෆ්කා යථාර්ථයක් වූ ආකාරය

කෆ්කා යථාර්ථයක් වූ ආකාරය

හෙලෝ, හබ්ර්!

මම තමන්ගේම දැනුම්දීමේ මධ්‍යස්ථානයක් සංවර්ධනය කරන Tinkoff කණ්ඩායමේ වැඩ කරමි. මම වැඩිපුරම ජාවා වල දියුණු කරන්නේ Spring boot භාවිතයෙන් සහ ව්‍යාපෘතියක පැන නගින විවිධ තාක්ෂණික ගැටළු නිරාකරණය කරයි.

අපගේ ක්ෂුද්‍ර සේවා බොහොමයක් පණිවිඩ තැරැව්කරුවෙකු හරහා අසමමුහුර්තව එකිනෙකා සමඟ සන්නිවේදනය කරයි. මීට පෙර, අපි IBM MQ තැරැව්කරුවෙකු ලෙස භාවිතා කළෙමු, එය තවදුරටත් බර සමඟ සාර්ථකව කටයුතු කළ නොහැකි නමුත් ඒ සමඟම ඉහළ බෙදාහැරීමේ සහතිකයක් තිබුණි.

ආදේශකයක් ලෙස, අපට Apache Kafka පිරිනමන ලදී, එය ඉහළ පරිමාණ කිරීමේ හැකියාවක් ඇත, නමුත්, අවාසනාවකට, විවිධ අවස්ථා සඳහා වින්‍යාස කිරීම සඳහා තනි පුද්ගල ප්‍රවේශයක් අවශ්‍ය වේ. මීට අමතරව, පෙරනිමියෙන් Kafka හි ක්‍රියා කරන අවම වශයෙන් එක් වරක් බෙදා හැරීමේ යාන්ත්‍රණය කොටුවෙන් පිටත අවශ්‍ය මට්ටමේ අනුකූලතාව පවත්වා ගැනීමට ඉඩ නොදේ. මීලඟට, මම 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

ඔබට Kafka සමඟ යෙදුමක JMX භාවිතා කිරීමට අවශ්‍ය නම්, මෙය ගැටළුවක් විය හැක. මෙම අවස්ථාව සඳහා, යෙදුම් නාමයේ සංයෝජනයක් සහ, උදාහරණයක් ලෙස, මාතෘකා නාමය client.id අගය ලෙස භාවිතා කිරීම වඩාත් සුදුසුය. අපගේ වින්‍යාසයේ ප්‍රති result ලය විධාන ප්‍රතිදානයේ දැකිය හැකිය කෆ්කා-පාරිභෝගික කණ්ඩායම් Confluent වෙතින් උපයෝගිතා වලින්:

කෆ්කා යථාර්ථයක් වූ ආකාරය

දැන් අපි සහතික කළ පණිවිඩ බෙදාහැරීමේ අවස්ථාව දෙස බලමු. කෆ්කා නිෂ්පාදකයාට පරාමිතියක් ඇත ඇක්ස්, පොකුරු නායකයාට සාර්ථකව ලියා ඇති පණිවිඩය සලකා බැලීමට කොපමණ පිළිගැනීම්වලින් පසුව වින්‍යාස කිරීමට ඔබට ඉඩ සලසයි. මෙම පරාමිතිය පහත අගයන් ගත හැක:

  • 0 - පිළිගැනීම සලකා බලනු නොලැබේ.
  • 1 යනු පෙරනිමි පරාමිතියයි, පිළිගැනීමට අවශ්‍ය වන්නේ අනුරූ 1ක් පමණි.
  • −1 — සියලුම සමමුහුර්ත අනුරූ වලින් පිළිගැනීම අවශ්‍ය වේ (පොකුරු සැකසුම min.insync.replicas).

ලැයිස්තුගත කර ඇති අගයන්ගෙන් පැහැදිලි වන්නේ −1 ට සමාන ඇක්ස් පණිවිඩය නැති නොවන බවට ශක්තිමත්ම සහතිකයක් ලබා දෙන බවයි.

අප දන්නා පරිදි, බෙදා හරින ලද පද්ධති විශ්වාස කළ නොහැකි ය. තාවකාලික දෝෂ වලින් ආරක්ෂා වීමට, Kafka නිෂ්පාදකයා විකල්පය සපයයි නැවත උත්සාහ කරයි, එය තුළ නැවත යැවීමේ උත්සාහයන් ගණන සැකසීමට ඔබට ඉඩ සලසයි delivery.timeout.ms. නැවත උත්සාහ කිරීමේ පරාමිතියට Integer.MAX_VALUE (2147483647) හි පෙරනිමි අගයක් ඇති බැවින්, delivery.timeout.ms පමණක් වෙනස් කිරීමෙන් පණිවිඩ නැවත උත්සාහ කිරීම් ගණන සකස් කළ හැක.

අපි හරියටම වරක් බෙදා හැරීම කරා ගමන් කරමින් සිටිමු

ලැයිස්තුගත සැකසුම් අපගේ නිෂ්පාදකයාට ඉහළ වගකීමක් සහිතව පණිවිඩ යැවීමට ඉඩ සලසයි. කෆ්කා මාතෘකාවකට පණිවිඩයක එක් පිටපතක් පමණක් ලියා ඇති බව සහතික කර ගන්නේ කෙසේද යන්න ගැන අපි දැන් කතා කරමු? සරලම අවස්ථාවක, මෙය සිදු කිරීම සඳහා, ඔබ නිෂ්පාදකයා මත පරාමිතිය සැකසිය යුතුය enable.deempotence ඇත්තට. Idempotency සහතික කරන්නේ එක් මාතෘකාවක නිශ්චිත කොටසකට එක් පණිවිඩයක් පමණක් ලියා ඇති බවයි. idempotency සක්‍රීය කිරීම සඳහා පූර්ව කොන්දේසිය වන්නේ අගයන් ය acks = සියල්ල, නැවත උත්සාහ කරන්න > 0, max.in.flight.requests.per.connection ≤ 5. මෙම පරාමිතීන් සංවර්ධකයා විසින් නියම කර නොමැති නම්, ඉහත අගයන් ස්වයංක්‍රීයව සැකසෙනු ඇත.

idempotency වින්‍යාස කර ඇති විට, සෑම අවස්ථාවකම එකම පණිවිඩ එකම කොටස් වලින් අවසන් වන බව සහතික කිරීම අවශ්‍ය වේ. partitioner.class යතුර සහ පරාමිතිය නිෂ්පාදකයා ලෙස සැකසීමෙන් මෙය කළ හැක. යතුරෙන් පටන් ගනිමු. එක් එක් ඉදිරිපත් කිරීම සඳහා එය සමාන විය යුතුය. මුල් පෝස්ටුවෙන් ඕනෑම ව්‍යාපාරික හැඳුනුම්පතක් භාවිතා කිරීමෙන් මෙය පහසුවෙන් ලබා ගත හැක. partitioner.class පරාමිතියට පෙරනිමි අගයක් ඇත - DefaultPartitioner. මෙම කොටස් කිරීමේ උපාය මාර්ගය සමඟ, පෙරනිමියෙන් අපි මෙසේ ක්රියා කරමු:

  • පණිවිඩය යැවීමේදී කොටස පැහැදිලිව සඳහන් කර ඇත්නම්, අපි එය භාවිතා කරමු.
  • කොටස නියම කර නොමැති නමුත් යතුර සඳහන් කර ඇත්නම්, යතුරේ හැෂ් මඟින් කොටස තෝරන්න.
  • කොටස සහ යතුර නිශ්චිතව දක්වා නොමැති නම්, කොටස් එකින් එක තෝරන්න (රවුන්ඩ් රොබින්).

එසේම, යතුරක් භාවිතා කිරීම සහ පරාමිතියක් සහිත idempotent යැවීම max.in.flight.requests.per.connection = 1 පාරිභෝගිකයා මත ඔබට විධිමත් පණිවිඩ සැකසීම ලබා දෙයි. ප්‍රවේශ පාලනය ඔබේ පොකුරේ වින්‍යාස කර ඇත්නම්, එවිට ඔබට මාතෘකාවක් සඳහා දුර්වල ලෙස ලිවීමට අයිතිවාසිකම් අවශ්‍ය බව මතක තබා ගැනීම වටී.

හදිසියේ ඔබට යතුර මගින් idempotent යැවීමේ හැකියාවන් නොමැති නම් හෝ නිෂ්පාදකයාගේ පැත්තේ තර්කනය විවිධ කොටස් අතර දත්ත අනුකූලතාවක් පවත්වා ගැනීමට අවශ්‍ය නම්, එවිට ගනුදෙනු ගලවා ගැනීමට පැමිණෙනු ඇත. ඊට අමතරව, දාම ගනුදෙනුවක් භාවිතා කරමින්, ඔබට Kafka හි වාර්තාවක් කොන්දේසි සහිතව සමමුහුර්ත කළ හැකිය, උදාහරණයක් ලෙස, දත්ත ගබඩාවේ වාර්තාවක් සමඟ. නිෂ්පාදකයාට ගනුදෙනු යැවීම සබල කිරීමට, එය දුර්වල විය යුතු අතර අතිරේකව සැකසිය යුතුය Transactional.id. ඔබේ Kafka පොකුරට ප්‍රවේශ පාලනය වින්‍යාස කර තිබේ නම්, idempotent වාර්තාවක් වැනි ගනුදෙනු වාර්තාවකට, Transactional.id හි ගබඩා කර ඇති අගය භාවිතයෙන් වෙස් මුහුණක් මඟින් ලබා දිය හැකි ලිවීමේ අවසර අවශ්‍ය වනු ඇත.

විධිමත් ලෙස, යෙදුම් නාමය වැනි ඕනෑම තන්තුවක් ගනුදෙනු හඳුනාගැනීමක් ලෙස භාවිතා කළ හැක. නමුත් ඔබ එකම යෙදවුමක අවස්ථා කිහිපයක් එකම Transal.id සමඟ දියත් කළහොත්, පළමු දියත් කළ අවස්ථාව දෝෂයකින් නවත්වනු ඇත, මන්ද Kafka එය 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.

මෙම ගැටළුව විසඳීම සඳහා, අපි පරිසර විචල්‍යයන්ගෙන් ලබා ගන්නා සත්කාරක නාමයේ ස්වරූපයෙන් යෙදුම් නාමයට උපසර්ගයක් එක් කරන්නෙමු.

නිෂ්පාදකයා වින්‍යාස කර ඇත, නමුත් Kafka හි ගනුදෙනු පමණක් පණිවිඩයේ විෂය පථය පාලනය කරයි. ගනුදෙනු තත්ත්වය කුමක් වුවත්, පණිවිඩය වහාම මාතෘකාවට යයි, නමුත් අතිරේක පද්ධති ගුණාංග ඇත.

එවැනි පණිවිඩ පාරිභෝගිකයා විසින් කලින් කියවීම වැළැක්වීම සඳහා, එය පරාමිතිය සැකසීමට අවශ්ය වේ හුදකලා මට්ටම කියවීමට_ කැපවූ අගයට. එවැනි පාරිභෝගිකයෙකුට පෙර පරිදිම ගණුදෙනු නොවන පණිවිඩ කියවීමට හැකි වනු ඇත, සහ ගණුදෙනු පණිවිඩ කියවිය හැක්කේ කැපවීමෙන් පසුව පමණි.
ඔබ කලින් ලැයිස්තුගත කර ඇති සියලුම සැකසුම් සකසා ඇත්නම්, ඔබ හරියටම වරක් බෙදාහැරීම වින්‍යාස කර ඇත. සුභ පැතුම්!

නමුත් තවත් එක් සූක්ෂ්මතාවයක් තිබේ. අපි ඉහත වින්‍යාස කළ Transactional.id, ඇත්ත වශයෙන්ම ගනුදෙනු උපසර්ගයයි. ගනුදෙනු කළමණාකරු මත, එයට අනුක්‍රමික අංකයක් එකතු වේ. ලැබුණු හැඳුනුම්කාරකය නිකුත් කරනු ලැබේ Transactional.id.expiration.ms, එය Kafka පොකුරක් මත වින්‍යාස කර ඇති අතර "දින 7" පෙරනිමි අගයක් ඇත. මෙම කාලය තුළ යෙදුමට කිසිදු පණිවිඩයක් ලැබී නොමැති නම්, ඔබ ඊළඟ ගනුදෙනු යැවීම උත්සාහ කරන විට ඔබට ලැබෙනු ඇත වලංගු නොවනPidMappingException. ගනුදෙනු සම්බන්ධීකාරක ඊළඟ ගනුදෙනුව සඳහා නව අනුක්‍රමික අංකයක් නිකුත් කරනු ඇත. කෙසේ වෙතත්, InvalidPidMappingException නිවැරදිව හසුරුවන්නේ නැතිනම් පණිවිඩය නැති විය හැක.

ප්රතිඵල වෙනුවට

ඔබට පෙනෙන පරිදි, කෆ්කා වෙත පණිවිඩ යැවීම පමණක් ප්රමාණවත් නොවේ. ඔබ පරාමිති සංයෝජනයක් තෝරා ගත යුතු අතර ඉක්මන් වෙනස්කම් කිරීමට සූදානම් විය යුතුය. මෙම ලිපියෙන්, මම හරියටම වරක් බෙදා හැරීමේ සැකසුම සවිස්තරාත්මකව පෙන්වීමට උත්සාහ කළ අතර අපට හමු වූ client.id සහ ගනුදෙනු. පහත දැක්වෙන්නේ නිෂ්පාදක සහ පාරිභෝගික සැකසුම් වල සාරාංශයකි.

නිෂ්පාදකයා:

  1. acks = සියල්ල
  2. නැවත උත්සාහ කරයි > 0
  3. enable.idempotence = ඇත්ත
  4. max.in.flight.requests.per.connection ≤ 5 (පිළිවෙලින් යැවීම සඳහා 1)
  5. Transactional.id = ${application-name}-${hostname}

පාරිභෝගික:

  1. isolation.level = read_committed

අනාගත යෙදුම්වල දෝෂ අවම කිරීම සඳහා, අපි වසන්ත වින්‍යාසය හරහා අපගේම දවටනයක් සාදා ඇත, එහිදී ලැයිස්තුගත කර ඇති සමහර පරාමිතීන් සඳහා අගයන් දැනටමත් සකසා ඇත.

ස්වයං අධ්‍යයනය සඳහා ද්‍රව්‍ය කිහිපයක් මෙන්න:

මූලාශ්රය: www.habr.com

අදහස් එක් කරන්න