# Efektivní zpracování zpráv Kafka v Node.js: konzumenti, rebalancování a škálování
Správná implementace konzumentů Kafka v Node.js vyžaduje porozumění nejen základnímu API, ale i architektonickým vlastnostem distribuované fronty. Chyby v nastavení partitionů, strategii čtení nebo správě offsetů vedou k ztrátě zpráv, nadměrným rebalancům a snížení propustnosti. V tomto článku rozebíráme klíčové aspekty tvorby spolehlivých a výkonných konzumentů s využitím KafkaJS.
Partitiony jako základ škálování
Škálování spotřeby zpráv z Kafka-topiku je omezeno počtem partitionů. Bez ohledu na počet spuštěných instancí nemůže být ve skupině aktivních konzumentů více než partitionů v topiku. Formule je jednoduchá: N_konsyumerov ≤ N_partitsiy. Překročení tohoto poměru způsobí, že část instancí zůstane bez přiřazení a bude nečinná, což vytváří zbytečnou zátěž na koordinátora skupiny.
Volba počtu počátečních partitionů je strategické rozhodnutí. I když Kafka umožňuje zvyšovat počet partitionů za běhu, narušuje to záruku pořadí zpráv podle klíče: nové zprávy se stejným klíčem se mohou dostat do jiné partition než předchozí. Pro flexibilitu doporučujeme vybrat číslo s mnoha dělitele (např. 24), aby bylo zajištěno rovnoměrné rozložení při jakémkoli počtu konzumentů od 1 do 24.
Důležité je pamatovat: celkový počet partitionů v celém clusteru by neměl překročit 200 000. Proto u málo zatížených topiků není nadměrné členění vhodné.
Paralelní zpracování a volba replik
I při přítomnosti více partitionů je u jednoho konzumenta zpracování výchozí řadové. Pro využití paralelismu uvnitř instance se používá volba partitionsConsumedConcurrently:
consumer.run({
partitionsConsumedConcurrently: 3,
eachMessage: async ({ topic, partition, message }) => {
// processing
},
});
Tímto způsobem se záruka pořadí zachovává v rámci jedné partition, ale ne mezi nimi. To umožňuje bezpečně zvyšovat propustnost bez narušení logiky zpracování.
Pro geograficky distribuované clustery je kritická síťová latence. Výchozí konzumenti čtou data z leader-repliky, která zároveň obsluhuje zápis. To vytváří úzké hrdlo. Řešením je rack-aware replikace. Na brokech se nastavuje parametr broker.rack, v klientovi se uvádí rackId:
const consumer = kafka.consumer({
groupId: 'user-service',
rackId: 'sibir_tomsk'
});
Kafka pak směruje požadavky k replice ve stejné „rackové doméně“, čímž minimalizuje latenci. Malé zpoždění replikace je většinou přijatelné, protože Kafka není určena pro striktní real-time.
Správa offsetů a počáteční čtení
Nové konzument-skupiny se setkávají s běžnou chybou: nevidí historická data. Důvod je chování parametru auto.offset.reset, který je výchozí nastaven na latest. To znamená, že při absenci commitovaného offsetu v __consumer_offsets konzument začne číst z konce partition.
Alternativou je earliest, ale její použití bez kontroly je riskantní: zpracování víceleté historie může přetížit službu a závislé systémy. Bezpečnější přístup:
- Použít
fromBeginning: truepři přihlášení, pokud je potřebná úplná historie:
await consumer.subscribe({ topic: 'user_events', fromBeginning: true });
Tato volba platí pouze při prvním připojení. Po prvním commitu offsetu Kafka ignoruje fromBeginning.
- Pro bodové obnovení – ručně nastavit offset přes CLI nebo UI nástroje (KafkaUI, Kadeck) po zastavení konzumenta.
Taková kontrola zabraňuje náhodnému přepsání offsetů a zajišťuje integritu zpracování.
Strategie rebalancování a jejich pasti
Rebalancování je proces přerozdělování partitionů při změně složení skupiny. KafkaJS podporuje pouze strategii Eager, při níž všichni konzumenti zastaví zpracování („stop-the-world“), dokončí aktuální úlohy, commitnou offsety a čekají na přiřazení nových partitionů.
Časté rebalancování snižuje dostupnost a zvyšuje latenci. Hlavní příčiny:
- Smíšená funkcionalita v jednom procesu – HTTP server, úlohy na pozadí a konzument v jedné instanci. Jakákoli fatální chyba mimo zpracování zpráv způsobí pád celého procesu a spustí rebalancování.
- Nesprávné timeouty – hodnoty
sessionTimeoutaheartbeatIntervalmusí být sladěné. Typické pravidlo:heartbeatInterval ≤ sessionTimeout / 3. - Dlouhé zpracování zpráv – pokud zpracování jedné zprávy překročí
rebalanceTimeout, konzument je vyloučen ze skupiny.
Pro diagnostiku je užitečné přihlásit se k události REBALANCING:
consumer.on(consumer.events.REBALANCING, ({ payload }) => {
console.log('Rebalancing started for group:', payload.groupId);
});
To umožňuje sbírat metriky a odhalovat anomální frekvence rebalancování.
Ačkoli Kafka 2.3+ nabízí Static Membership a CooperativeStickyAssignor pro zmírnění těchto problémů, KafkaJS je zatím nepodporuje. Proto jsou architektonická opatření jedinou cestou k stabilitě.
Co je důležité
- Počet partitionů určuje horní limit horizontálního škálování konzumentů.
- Paralelní zpracování (
partitionsConsumedConcurrently) zrychluje zpracování bez ztráty pořadí uvnitř partition. - Čtení z lokální repliky (
rackId) snižuje síťovou latenci v geo-distribuovaných prostředích. - Nové konzument-skupiny výchozí přeskakují historii – použijte
fromBeginningnebo ruční nastavení offsetů. - Izolujte konzumenty od ostatních komponent aplikace, aby se vyhnuli neopodstatněným rebalancům.
— Editorial Team
Zatím žádné komentáře.