एका VPS वर NATS, RabbitMQ की Kafka?
एका सर्व्हरवरील queue निवडताना delivery guarantees, memory व disk खर्च, restart नंतरचे वर्तन, backlog तपासणी आणि कधी Postgres अधिक योग्य ठरते हे जाणून घ्या.
एका सर्व्हरसाठी थोडक्यात
एका VPS वरील message queue ही गतीबद्दलची नव्हे, तर delivery guarantees बद्दलची निवड आहे. एकाच box वर broker क्वचितच bottleneck ठरतो, कारण तुमचा application code, database आणि एकमेव disk यांच्यावरच आधी मर्यादा येतात. ज्या tool चे failure behaviour तुम्ही स्वीकारू शकता ते निवडा. त्यानंतर तुमच्याकडे प्रत्यक्षात असलेल्या box चे मोजमाप करा.
बहुतेक वाचकांनी विचारात घ्यावयाचे चार पर्याय पुढील क्रमाने आहेत.
- तुम्ही आधीपासून चालवत असलेला database वापरा.
SELECT ... FOR UPDATE SKIP LOCKEDसह Postgres ही कार्यक्षम job queue आहे आणि monitor करण्यासाठी नवीन process जोडत नाही. - प्रत्येक message हा acknowledge करणे आवश्यक असलेला work unit असेल, त्यावर मर्यादित वेळा retry करायचा असेल आणि त्यानंतर मानवी तपासणीसाठी एखाद्या ठिकाणी ठेवायचा असेल, तर RabbitMQ वापरा.
- तुमच्या system चे अनेक भाग ज्या messages वर प्रतिक्रिया देतात ते events असतील, तर NATS वापरा. Restart नंतर टिकून राहणे आवश्यक असलेल्या events साठी JetStream सुरू करा.
- downstream tool फक्त Kafka protocol वापरत असेल, तर Kafka वापरा. एका server वर उरलेले जवळजवळ एकमेव कारण हेच आहे.
या मार्गदर्शकाच्या उर्वरित भागात त्यामागील कारणमीमांसा दिली आहे: लहान VPS वर प्रत्येक पर्यायासाठी memory आणि disk ची किती आवश्यकता असते, box reboot झाल्यावर तो कसा वागतो आणि users ना त्याचा परिणाम जाणवण्यापूर्वी backlog दाखवणारी अचूक command कोणती.
वितरणाची हमी प्रत्यक्षात काय दर्शवते
जास्तीत जास्त एकदा याचा अर्थ broker संदेश consumer कडे सोपवतो आणि तो विसरतो. कोणताही consumer जोडलेला नसेल किंवा काम अर्ध्यावर असताना consumer बंद पडला, तर संदेश नष्ट होतो आणि त्याची कोणतीही नोंद होत नाही.
किमान एकदा याचा अर्थ काम यशस्वी झाल्यानंतर consumer acknowledgement (ack) पाठवतो. तो ack मिळेपर्यंत broker संदेश जतन करतो आणि तो पुन्हा वितरित करतो. पुन्हा वितरणामुळे तुमचे handlers idempotent असणे आवश्यक आहे: एकाच संदेशावर दोनदा प्रक्रिया झाली, तरी कार्डवर दोनदा शुल्क आकारले जाऊ नये. सुरुवातीपासून शेवटपर्यंत तंतोतंत एकदाच प्रक्रिया होण्याची हमी broker देत नाही. ती तुमच्या स्वतःच्या database मधील unique key मुळे मिळते.
Replay हा स्वतंत्र गुणधर्म आहे. संदेश acknowledged झाल्यावर queue तो टाकून देते. log तो retention window पर्यंत जतन करतो. त्यामुळे नवीन consumer सुरुवातीपासून सुरू होऊन संपूर्ण इतिहास वाचू शकतो. Kafka आणि NATS JetStream हे logs आहेत. RabbitMQ ही queue आहे. या फरकामुळे throughput पेक्षा अधिक architectures प्रभावित होतात.
Dead lettering म्हणजे सतत अपयशी ठरणाऱ्या संदेशाचे काय होते ते. ही व्यवस्था नसल्यास poison message अंतहीनपणे पुन्हा process होत राहतो. हा loop बिघाड झाल्यासारखा न दिसता व्यस्त worker सारखा दिसतो.
Postgres पासून सुरुवात करा आणि broker ने स्वतःची उपयुक्तता सिद्ध करू द्या
बहुतेक single-application workloads मध्ये दररोज काही हजार background jobs असतात. हे प्रमाण एका table मध्ये सहज हाताळता येते.
CREATE TABLE job (
id bigserial PRIMARY KEY,
payload jsonb NOT NULL,
run_after timestamptz NOT NULL DEFAULT now(),
attempts int NOT NULL DEFAULT 0
);
CREATE INDEX job_ready_idx ON job (run_after, id);एक worker transaction च्या आत एक job claim करतो.
BEGIN;
SELECT id, payload
FROM job
WHERE run_after <= now()
ORDER BY id
FOR UPDATE SKIP LOCKED
LIMIT 1;
-- run the work, then remove the row
DELETE FROM job WHERE id = $1;
COMMIT;FOR UPDATE SKIP LOCKED हाच संपूर्ण उपाय आहे. तो परत करत असलेल्या row वर lock लावतो आणि दुसऱ्या transaction ने आधीच lock केलेल्या row वगळतो. त्यामुळे दोन workers एकाच job ला claim करत नाहीत. एखादा worker crash झाल्यास Postgres त्याचा transaction abort करतो, lock release होतो आणि ती row पुढील worker ला दिसू लागते. तुम्हाला at-least-once delivery, attempts ची value वाढवून retries आणि dead letter table मिळतात. यासाठी तुम्ही आधीच भरत असलेल्या durability चाच वापर होतो. Backlog तपासण्यासाठी एकच query पुरेशी आहे: SELECT count(*) FROM job WHERE run_after <= now();
हे कुठे अयशस्वी होऊ लागते. प्रत्येक claim आणि delete ही write operation आहे. त्यामुळे job rate जास्त असल्यास मागे dead row versions साचतात आणि queue table मध्ये bloat autovacuum पेक्षा वेगाने वाढणे ही नेहमीची समस्या ठरते. Jobs दीर्घकाळ चालत असल्यास समस्या वाढते. कारण काम पूर्ण होईपर्यंत उघडा ठेवलेला transaction संपूर्ण database साठी vacuum horizon पुढे जाण्यापासून रोखतो. Polling मुळे latency वाढते. LISTEN आणि NOTIFY वापरल्यास polling दूर होते, पण writes दूर होत नाहीत. तुमच्याकडील सर्वांत व्यस्त table job table झाली असेल किंवा दुसऱ्या service ला त्याच events ची गरज असेल, तर काम database च्या बाहेर हलवा. हा निर्णय database स्वतः कसा deploy केला आहे याच्याशी संबंधित आहे. त्यामुळे broker शेजारी जोडण्यापूर्वी database Docker मध्ये चालतो की host वर हे निश्चित करा.
Redis ही दुसरी गोष्ट आहे जी तुम्ही आधीपासून चालवत असू शकता. Redis Streams मध्ये XADD आणि XREADGROUP सह consumer groups, प्रत्येक group साठी pending list आणि मृत झालेल्या consumer कडून काम परत घेण्यासाठी XAUTOCLAIM उपलब्ध असते. ते लहान आणि जलद आहे. मात्र एका server वरची महत्त्वाची मर्यादा स्पष्टपणे समजून घ्या: सामान्य appendfsync everysec setting वापरल्यास power loss मुळे सुमारे एक सेकंदाच्या writes गमावल्या जाऊ शकतात. Cache invalidation साठी हे स्वीकार्य आहे, पण payments साठी अयोग्य आहे. तुमचे application production मध्ये VPS वर SQLite भोवती तयार केलेला single process असल्यास हाच claim-and-delete pattern कार्य करतो. मात्र SQLite मध्ये SKIP LOCKED चा समतुल्य पर्याय नाही आणि प्रत्येक worker एकाच write lock वर serialise होतो.
NATS core: memory नसलेले subject routing
docker run -d --name nats \
-p 4222:4222 -p 127.0.0.1:8222:8222 \
nats:2.14 -m 8222August 2026 नुसार सध्याची server line 2.14 आहे. -m 8222 HTTP monitoring port सुरू करते. हा port default ने बंद असतो आणि त्यावर authentication नसते, त्यामुळे वर दिल्याप्रमाणे तो localhost वर bind करा.
Core NATS मध्ये संदेश जास्तीत जास्त एकदाच वितरित केला जातो आणि ते कोणतीही माहिती साठवत नाही. Publisher orders.created सारख्या subject वर संदेश पाठवतो. Filter जुळणाऱ्या प्रत्येक subscriber ला त्या संदेशाची एक प्रत मिळते. कोणताही subscriber subscribed नसेल, तर संदेश drop होतो आणि publisher ला कोणतीही error दिसत नाही. याचे कारण server ने bytes स्वीकारताच publisher चे काम पूर्ण झालेले असते. Queue group मध्ये अनेक subscribers एकच group name share करतात. अशा वेळी server प्रत्येक संदेशासाठी एक member निवडतो. संदेशांची queue साठविल्याशिवाय कामाचे वाटप करण्यासाठी ही पद्धत वापरता येते.
याचा memory footprint subscription state आणि प्रत्येक connection साठी असलेल्या write buffer इतकाच असतो. त्यामुळे तो message volume ऐवजी connection count नुसार वाढतो. Disk वर काहीही साठत नाही. Restart चे वर्तन यावरून स्पष्ट होते: in-flight messages नष्ट होतात, clients स्वतःहून reconnect करतात आणि recovery साठी प्रतीक्षा करण्याची कोणतीही पायरी नसते.
तपासण्यासाठी backlog नसतो, त्यामुळे message loss वर लक्ष ठेवा. Server client च्या socket वर ज्या वेगाने लिहितो त्यापेक्षा subscriber ज्या वेगाने socket वाचतो तो वेग कमी असेल, तर त्या client साठीचा server buffer भरतो. Write deadline पर्यंत client ने मागे पडलेले messages वाचून पूर्ण केले नसतील, तर server संपूर्ण connection बंद करतो आणि counter वाढवतो.
curl -s http://localhost:8222/varz | jq '.slow_consumers, .connections, .in_msgs, .out_msgs'सतत वाढणारे slow_consumers value messages drop होत असल्याचे दर्शवते. त्यामुळे ते एकदाच वाचण्याऐवजी त्यावर alert लावा. ज्या message चे value लवकरच कालबाह्य होते अशा वापरासाठी Core NATS योग्य आहे: metric, presence update किंवा cache invalidation, ज्याची जागा पुढील event आपोआप घेणार आहे.
NATS JetStream: त्याच प्रक्रियेत durable streams आणि replay
JetStream हे दुसरे product नाही. ते त्याच binary मधील subsystem आहे आणि एका flag ने enable करता येते.
docker run -d --name nats \
-p 4222:4222 -p 127.0.0.1:8222:8222 \
-v nats-data:/data \
nats:2.14 -js -sd /data -m 8222-sd /data store directory सेट करते. ते वगळल्यास JetStream आपला data /tmp अंतर्गत store करते. नावाप्रमाणेच ते durable नसते. CLI वापरून stream तयार करा. हा CLI nats-box image मध्ये उपलब्ध असतो.
docker run --rm -it --network host natsio/nats-box:latest \
nats stream add ORDERS \
--subjects 'orders.>' \
--storage file \
--retention limits \
--max-age 72h \
--max-bytes=1073741824 \
--discard old \
--defaultsलहान server वर येथील प्रत्येक limit आवश्यक आहे. Crash नंतर टिकणारा data --storage file मध्ये असतो; memory stream तसे टिकत नाही. --max-bytes=1073741824 stream मध्ये लिहिलेला data 1 GiB पर्यंत मर्यादित करते. ही मर्यादा byte count म्हणून लिहिली जाते. मर्यादा गाठल्यावर नवीन writes नाकारण्याऐवजी --discard old सर्वांत जुने messages काढून टाकते. ही मर्यादा न ठेवल्यास एखादा अनियंत्रित publisher disk भरू शकतो. त्या disk वर database देखील असल्यास तेही बंद पडते.
durable consumer stream मधील स्वतःची position ठेवतो आणि restart नंतरही ती कायम ठेवतो. एखादा message सतत fail होत असल्यास त्याची कायम redelivery होऊ नये म्हणून consumer वर --max-deliver सेट करा. एखाद्या message च्या deliveries संपल्यावर JetStream $JS.EVENT.ADVISORY.CONSUMER.MAX_DELIVERIES.> वर advisory publish करते. त्या subject ला subscribe करून dead letter path तयार करता येतो. RabbitMQ हे feature म्हणून देते, परंतु येथे ते तुम्हालाच implement करावे लागते.
Backlog पाहण्यासाठी stored message counts साठी nats stream report चालवा. प्रत्येक consumer साठी outstanding acknowledgements आणि unprocessed messages पाहण्यासाठी nats consumer report ORDERS चालवा. Alarm साठी unprocessed संख्या वापरा. Store directory च्या disk cost साठी du -sh वापरा. Retention limit लागू होईपर्यंत हा cost वाढत राहतो.
RabbitMQ: प्रत्येक संदेशाला acknowledge करा, अपयशी संदेश वेगळे ठेवा
docker run -d --name rabbitmq \
-p 5672:5672 -p 127.0.0.1:15672:15672 \
-v rabbitmq-data:/var/lib/rabbitmq \
rabbitmq:4-managementAugust 2026 पर्यंत सध्याची series 4.3 आहे. Port 5672 हा AMQP (advanced message queuing protocol) साठी आहे आणि 15672 हा management interface साठी आहे. Interface localhost वरच ठेवा आणि SSH tunnel द्वारे त्याचा वापर करा.
x-queue-type argument quorum वर सेट करून queues declare करा; default अजूनही classic आहे. Quorum queues नेहमी durable असतात आणि इतर कोणतीही कृती करण्यापूर्वी data disk वर लिहितात. त्यामुळे एका node वर durable आणि transient पर्यायांच्या अनेक संयोजनांऐवजी एकच स्पष्ट वर्तन मिळते. Dead letter target policy वापरून सेट करा.
docker exec rabbitmq rabbitmqctl set_policy DLX ".*" \
'{"dead-letter-exchange":"my-dlx", "dead-letter-routing-key":"my-routing-key"}' \
--apply-to queues --priority 7Message चार कारणांमुळे dead letter केला जातो: consumer ने basic.reject किंवा basic.nack सह reject केले आणि requeue false वर सेट केले; त्याचा per-message TTL (time to live) संपला; queue ने length limit ओलांडली; किंवा त्याने quorum queue delivery limit ओलांडली. RabbitMQ 4.0 पासून ही limit default ने 20 आहे. त्यामुळे handler ने exception टाकून nack केल्यास message वीस वेळा retry होतो आणि नंतर loop होण्याऐवजी dead letter exchange कडे पाठवला जातो.
लहान VPS वर RabbitMQ मध्ये Memory मुळे अनपेक्षित समस्या येतात. उपलब्ध RAM पैकी 0.6 हा default high watermark आहे. Node ही मर्यादा ओलांडल्यावर RabbitMQ publish करणारे प्रत्येक connection block करते. तुमच्या application ला error मिळत नाही. तिला असा publish मिळतो जो कधीच return होत नाही. त्यामुळे तुमच्या code मध्ये ते hang झाल्यासारखे दिसते. Startup log मध्ये node ने मोजलेली संख्या दिसते:
Memory high watermark set to 1024 MiB (1073741824 bytes) of 8192 MiB (8589934592 bytes) totalFree space default ने 50 MB पेक्षा कमी झाल्यावर disk alarm publishers ना याच प्रकारे block करते. Quorum queues यावर स्वतःची memory आवश्यकता जोडतात. Documentation नुसार प्रत्येक message साठी in-memory metadata ला किमान 32 bytes राखणे अपेक्षित आहे. हे सुमारे 30,000 messages मागे 1 MB होते. तसेच effective write-ahead log size च्या किमान तिप्पट RAM ठेवण्याची शिफारस आहे. WAL limit default ने 512 MiB आहे. त्यामुळे या शिफारसीनुसारच 1.5 GB RAM आवश्यक होते. 2 GB server वर default पुरेल अशी अपेक्षा न ठेवता rabbitmq.conf मध्ये ही limit कमी करा.
raft.wal_max_size_bytes = 64000000
vm_memory_high_watermark.relative = 0.5Backlog दोन संख्यांनी दर्शवला जातो. त्या दोन्ही संख्या कोणते failure झाले आहे ते सांगतात.
docker exec rabbitmq rabbitmqctl list_queues name messages messages_ready messages_unacknowledgedmessages_ready हा consumer ची वाट पाहणारा message count आहे. messages_unacknowledged हा deliver झालेला पण ack न केलेला message count आहे. Ready count स्थिर असताना unacknowledged count वाढत असेल, तर तुमच्या workers ने jobs स्वीकारल्या पण त्या पूर्ण करणे थांबवले आहे. ही समस्या केवळ मागे पडलेल्या queue पेक्षा वेगळी आहे.
एका बॉक्सवर Kafka, आणि ते कधी अव्यवहार्य ठरते
KAFKA_CLUSTER_ID="$(bin/kafka-storage.sh random-uuid)"
bin/kafka-storage.sh format --standalone -t $KAFKA_CLUSTER_ID -c config/server.properties
bin/kafka-server-start.sh config/server.propertiesही Kafka 4.3.1 साठीची quickstart आहे. ऑगस्ट 2026 पर्यंतची ही आवृत्ती KRaft mode मध्ये चालते. KRaft म्हणजे Kafka Raft; Kafka 4.0 मध्ये ZooKeeper ची जागा घेणारा हा अंगभूत controller आहे. Container साठीचा समतुल्य पर्याय apache/kafka:4.3.1 आहे.
तुम्ही स्वतः export KAFKA_HEAP_OPTS="-Xmx1G -Xms1G" सेट केलेले नसल्यास start script ते सेट करते. त्यामुळे एकही message साठवण्यापूर्वी broker 1 GB Java heap राखून ठेवतो. तसेच page cache साठी यापेक्षा अधिक मोकळी RAM अपेक्षित असते. 2 GB VPS वर उरलेल्या RAM साठी तुमचे application आणि JVM यांच्यात स्पर्धा होते.
Retention हा पुढचा धक्का असतो. log.retention.hours चे default मूल्य 168 आहे, म्हणजे सात दिवस. log.retention.bytes चे default मूल्य -1 आहे, म्हणजे आकाराची कोणतीही मर्यादा नाही. प्रत्येक consumer ने messages वाचले आहेत किंवा नाही, याची पर्वा न करता Kafka संपूर्ण कालावधीभर messages ठेवते. Kafka वापरण्याचे हेच प्रमुख कारण आहे. पण एका छोट्या disk वर हीच गोष्ट failure mode ठरू शकते. त्यामुळे हे लक्षात येण्यापूर्वी प्रत्येक topic साठी byte limit सेट करा.
आता स्पष्ट सांगायचे तर, single broker म्हणजे replication factor 1. त्यामुळे acks=all एका disk वरील एका fsync पर्यंतच मर्यादित राहते. तुम्हाला एका machine ची durability मिळते; त्यासाठी JVM broker आणि controller चालवण्याचा operating cost द्यावा लागतो. तुमच्याकडे नसलेल्या अनेक brokers मध्ये partitions मुळे parallelism मिळते. Replication, rack awareness आणि fleet मधील इतर सुविधा निष्क्रिय राहतात. त्याच machine वर JetStream कमी memory वापरून तितकेच durable replay देते. तरीही येथे Kafka निवडण्याची दोन कारणे असू शकतात: downstream tool फक्त Kafka protocol वापरते, जसे Debezium सह change data capture किंवा analytics loader; किंवा production topology ची लहान आवृत्ती तयार करून पाहायची आहे. भविष्यात cluster वाढवण्याचे नियोजन म्हणजे अधिक machines खरेदी करण्याचे नियोजन. तोपर्यंत हीच देवाणघेवाण single node वर k3s चालवण्यासारखी आहे: एका node ची reliability मिळवण्यासाठी cluster complexity स्वीकारावी लागते.
Kafka मधील backlog ला consumer lag म्हणतात.
bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 --describe --group my-groupLAG column वाचा. प्रत्येक partition साठी ते LOG-END-OFFSET मधून CURRENT-OFFSET वजा केल्यावर मिळते. इतर partitions स्थिर असताना एका partition वरील lag वाढत असेल, तर key चे वितरण असमान असल्याचे सूचित होते. समान key असलेले सर्व messages त्याच partition मध्ये जातात आणि ते एकच consumer हाताळतो.
रीबूट झाल्यावर काय होते
Core NATS मधील उड्डाणावस्थेतील सर्व माहिती नष्ट होते आणि सेवा त्वरित पुन्हा सुरू होते, कारण पुनर्प्राप्त करण्यासाठी काहीही नसते. JetStream streams आणि consumer positions store directory मधून पुन्हा लोड करते. त्यामुळे consumers ज्या offset वर होते तिथून पुढे सुरू होतात. RabbitMQ quorum queues डिस्कवरून पुनर्प्राप्त करते. मात्र classic transient queues आणि persistent delivery mode शिवाय प्रकाशित केलेला कोणताही message नष्ट होतो. Kafka startup वेळी त्याचे log segments पुन्हा वाचते. अस्वच्छ shutdown नंतर broker connection स्वीकारण्यापूर्वी ही recovery scan लहान डिस्कवर काही मिनिटे चालू शकते.
दोन गोष्टी एकदाच निश्चित करणे उपयुक्त ठरते. Container ला restart policy (restart: unless-stopped) द्या किंवा systemd unit enable करा. त्यामुळे kernel upgrade नंतर reboot झाल्यावर broker तुमच्या हस्तक्षेपाशिवाय पुन्हा सुरू होईल. त्यानंतर startup order हाताळा. तुमच्या application पेक्षा broker वीस सेकंद उशिरा ready झाल्यास तो पहिल्या connections नाकारेल. काही client libraries retry करण्याऐवजी बंद होतात. broker ready होईपर्यंत dependent service ला थांबवणारे Compose healthchecks वापरून application ला broker वर अवलंबून ठेवा.
तुमच्या VPS वरील खर्च, उद्धृत आकड्यांऐवजी प्रत्यक्ष मोजलेला
प्रकाशित throughput चे आकडे तुमच्याकडे नसलेल्या hardware वर मोजलेले असतात. साधारणपणे हे local NVMe असलेले multi-core server असते. त्यामुळे त्यांना कमाल मर्यादा समजा आणि तुमच्या box वर मोजमाप करा.
docker stats --no-stream
free -m
sudo du -sh /var/lib/docker/volumes/*/_dataही मोजमापे broker idle असताना चालवा. त्यानंतर तुमच्या प्रत्यक्ष traffic अंतर्गत पुन्हा चालवा. या दोन मोजमापांमधील फरकावरून broker तुमच्या application सोबत चालू शकतो की नाही हे ठरते. अंदाजे throughput floor साठी कोणाच्यातरी blog post ऐवजी प्रत्येक project चा स्वतःचा load generator वापरा: NATS साठी nats bench pub test --msgs 100000 --clients 2, Kafka साठी bin/kafka-producer-perf-test.sh आणि RabbitMQ साठी PerfTest. त्याच VPS वर generator चालवल्यास broker आणि generator या दोघांचे एकत्रित मोजमाप होते. अहवालात हा आकडा सांगताना ते स्पष्ट केले, तर ही पद्धत योग्य आहे.
या सर्वांसाठी एकच कमाल मर्यादा लागू होते. येथे प्रत्येक durable option fsync पूर्ण होण्याची प्रतीक्षा करते. त्यामुळे network-attached storage असलेल्या VPS मध्ये disk ही मर्यादा ठरवते. Broker बदलल्याने ही मर्यादा बदलणार नाही.
तीन workload आणि प्रत्येकाला आवश्यक असलेली message queue
- एका web application साठी background jobs, जसे की email पाठवणे, images चा आकार बदलणे किंवा webhooks वितरित करणे. सुरुवात Postgres आणि
SKIP LOCKEDने करा. प्रत्येक message साठी ack, delivery limit आणि dead letter queue हवी असेल, तसेच हे logic स्वतः लिहिल्याशिवाय dead letter queue तपासता यावी असे वाटत असेल, किंवा database मधील job table सर्वाधिक व्यस्त table झाली असेल, तर quorum queues असलेल्या RabbitMQ कडे जा. - अनेक internal services ज्या events वर प्रतिक्रिया देतात आणि हरवलेला message लवकरच नवीन message ने बदलला जातो, अशा परिस्थितीसाठी Core NATS वापरा. Routing scheme म्हणून subjects वापरा आणि कामाचे वाटप आवश्यक असेल तेथे queue groups वापरा. रीबूटनंतर टिकून राहणे आवश्यक असलेल्या मर्यादित subjects संचासाठी JetStream stream जोडा आणि उर्वरित messages memory मध्ये ठेवा.
- Consumers सुरुवातीपासून वाचतात असा event log, audit trail साठी, read model पुन्हा तयार करण्यासाठी किंवा नंतर analytics ला data पुरवण्यासाठी. File storage आणि स्पष्ट byte cap असलेले JetStream वापरा. Downstream tool ला Kafka protocol आवश्यक असेल तेव्हाच Kafka निवडा आणि या compatibility ची किंमत म्हणून JVM heap स्वीकारा.
Single server वर चुकीची निवड केल्याची किंमत throughput नसते. पहाटे 3 वाजता recovery करताना messages अजून उपलब्ध आहेत का, हे तपासण्याची वेळ आली की खरी अडचण समजते. त्यामुळे त्यानुसार निवड करा.
FAQ
मी 2 GB VPS वर Kafka चालवू शकतो का?
ते सुरू होईल, पण उपलब्ध संसाधने अत्यंत मर्यादित राहतील. तुम्ही bin/kafka-server-start.sh बदलले नसल्यास ते KAFKA_HEAP_OPTS="-Xmx1G -Xms1G" सेट करते. त्यामुळे कोणताही संदेश साठवण्यापूर्वीच JVM 1 GB मेमरी घेते. याशिवाय Kafka ला page cache साठी मोकळी मेमरी आवश्यक असते. त्याच सर्व्हरवर तुमचे अॅप्लिकेशन आणि database चालू केल्यास प्रणाली swap वापरू लागेल. तुम्हाला replication factor 1 देखील मिळतो. याचा अर्थ acks=all एका disk वर एक fsync इतकेच असते. त्यामुळे Kafka चा operating cost येतो, पण त्याचे durability model मिळत नाही. त्याच hardware वर NATS JetStream खूप कमी मेमरीमध्ये durable replay देते.
मी आधीच Postgres चालवत असल्यास message queue आवश्यक आहे का?
बहुतेक वेळा नाही. Transaction मध्ये SELECT ... FOR UPDATE SKIP LOCKED सह job table वाचल्यास at-least-once delivery, सुरक्षित concurrent workers, retries आणि dead letter table मिळतात. यासाठी monitor करण्यासाठी अतिरिक्त सेवा आवश्यक नसते आणि तुम्ही आधीच घेत असलेले backups वापरता येतात. वेगळ्या queue कडे जाण्याची कारणे विशिष्ट असतात: queue table वरील write load सर्वाधिक होतो आणि autovacuum मागे पडते, दीर्घकाळ चालणारी jobs transactions उघडी ठेवतात आणि संपूर्ण database साठी vacuum अडवतात, किंवा दुसऱ्या सेवेला त्याच events स्वतंत्रपणे consume करण्याची आवश्यकता असते.
Background jobs साठी NATS JetStream वापरावे की RabbitMQ?
प्रत्येक message साठी acknowledgement, delivery limit आणि dead letter routing अंगभूत स्वरूपात हवे असल्यास RabbitMQ वापरा. Quorum queues नेहमी durable असतात. RabbitMQ 4.0 पासून delivery limit चे default मूल्य 20 आहे. Policy मुळे मर्यादा संपलेल्या messages ना dead letter exchange कडे पाठवता येते; तेथून तुम्ही ते drain आणि inspect करू शकता. त्याच events चे replay नंतर इतर consumers ना आवश्यक असल्यास JetStream वापरा. Stream मध्ये acknowledgement नंतरही messages राहतात, तर queue मध्ये ते राहत नाहीत. JetStream मध्ये तुम्ही --max-deliver सेट करता आणि $JS.EVENT.ADVISORY.CONSUMER.MAX_DELIVERIES.> advisory वरून dead letter path स्वतः तयार करता.
माझे consumers किती मागे आहेत हे कसे समजेल?
प्रत्येक broker साठी यासाठी एक command आहे. RabbitMQ मध्ये rabbitmqctl list_queues name messages messages_ready messages_unacknowledged consumer ची वाट पाहणारे work आणि deliver झालेले पण ack न झालेले work वेगळे दाखवते. JetStream मध्ये nats consumer report <stream> प्रत्येक consumer साठी unprocessed messages आणि outstanding acknowledgements दाखवते. Kafka मध्ये kafka-consumer-groups.sh --bootstrap-server localhost:9092 --describe --group <group> प्रत्येक partition साठी LAG column दाखवते. Core NATS मध्ये read करण्यासाठी backlog नसतो, कारण ते काहीही store करत नाही. त्यामुळे त्याऐवजी http://localhost:8222/varz वरील slow_consumers counter monitor करा. Consumer मागे पडल्यामुळे server ने बंद केलेल्या connections ची संख्या हा counter दाखवतो. याचा अर्थ message loss आहे.