در جلسهی گذشته، کافکا را بهصورت لوکال (روی سیستم شخصی) نصب کردیم و با مفاهیم اولیهی آن آشنا شدیم.
اما از این جلسه به بعد، چون قصد داریم امکانات متنوعتر و پارامترهای اصلی کافکا را بررسی کنیم، بهتر است با یک کلاستر واقعی کافکا کار کنیم.
سادهترین و سریعترین راه برای راهاندازی چنین کلاستری، استفاده از Docker و Docker Compose است.
در این جلسه ابتدا یک نسخهی تکنودی (Single Node) از کافکا را با Docker Compose بالا میآوریم و در ادامه نسخههای حرفهایتر چندنودی را بررسی میکنیم.
در نسخههای جدید کافکا، دیگر خبری از ZooKeeper نیست.
کافکا حالا خودش مکانیزم اجماع و هماهنگی بین نودها را با استفاده از سیستمی به نام KRaft (Kafka Raft) انجام میدهد.
در مدل KRaft، هر نود در کلاستر میتواند یکی از این سه نقش را داشته باشد:
وقتی بیش از یک نود در کلاستر داریم، باید بین آنها توافق وجود داشته باشد که کدام نود رهبر (Leader) باشد.
این هماهنگی بدون یک مکانیزم اجماع ممکن نیست.
در گذشته این کار را ZooKeeper انجام میداد، اما در KRaft از الگوریتم Raft Consensus استفاده میشود.
الگوریتم Raft تضمین میکند که حتی اگر برخی از نودها از دسترس خارج شوند، باز هم کلاستر بتواند تصمیمگیری هماهنگ داشته باشد.
کافکا از Raft در چند موقعیت کلیدی استفاده میکند:
در اینجا یک فایل Docker Compose ساده برای راهاندازی یک کافکای تکنودی در حالت KRaft آورده شده است:
version: "3.9"
networks:
kafka-net:
volumes:
kafka-data:
services:
kafka:
image: apache/kafka:latest
container_name: kafka-node
networks:
- kafka-net
ports:
- "۹۰۹۲:۹۰۹۲" # EXTERNAL listener for producers/consumers
- "۹۰۹۳:۹۰۹۳" # CONTROLLER listener
environment:
# Node ID
KAFKA_NODE_ID: 1
# Roles: combined broker + controller
KAFKA_PROCESS_ROLES: broker,controller
# Listeners
KAFKA_LISTENERS: EXTERNAL://:9092,CONTROLLER://:9093
KAFKA_ADVERTISED_LISTENERS: EXTERNAL://localhost:9092
KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: EXTERNAL:PLAINTEXT,CONTROLLER:PLAINTEXT
# Quorum voters (single node)
KAFKA_CONTROLLER_QUORUM_VOTERS: 1@localhost:9093
# Topics & transactions
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
KAFKA_NUM_PARTITIONS: 3
KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0
# Log directory
KAFKA_LOG_DIRS: /var/lib/kafka/data
volumes:
- kafka-data:/var/lib/kafka/data
برای درک بهتر، بیایید تنظیمات بالا را به چند بخش تقسیم کنیم:
KAFKA_NODE_ID: شماره یکتا برای هر نود در کلاستر.KAFKA_PROCESS_ROLES: تعیین میکند که این نود broker است، controller یا هر دو.در این مثال، هر دو نقش را دارد.
در کافکا، هر Listener مشخص میکند که نود ما از طریق چه پروتکلی، روی چه آدرسی، و از چه پورتی در دسترس است.
فرمت کلی هر listener به صورت زیر است:
<NAME>://<HOST>:<PORT>
در اینجا داریم:
EXTERNAL://:9092 → برای ارتباط با Producer و Consumer (بیرون از داکر)CONTROLLER://:9093 → برای ارتباط کنترلرها در داخل کلاستر🔹 نکته مهم:
کلماتی مثل EXTERNAL یا CONTROLLER فقط برچسب (Label) هستند و برای تنظیمات امنیتی و تعیین نوع ارتباط بین نودها در سایر تنظیمات، از این برچسب ها استفاده میکنیم.
در بخش زیر تعیین میکنیم هر برچسب از چه پروتکل امنیتی استفاده کند:
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: EXTERNAL:PLAINTEXT,CONTROLLER:PLAINTEXT
در اینجا هر دو روی حالت سادهی PLAINTEXT (بدون SSL یا SASL) تنظیم شدهاند.
متغیر KAFKA_ADVERTISED_LISTENERS به سایر نودها و کلاینتها اعلام میکند که برای اتصال به این نود از چه آدرس و پورتی استفاده کنند.
برای مثال:
KAFKA_ADVERTISED_LISTENERS=EXTERNAL://localhost:9092
یعنی وقتی Producer یا Consumer بخواهد وصل شود، بداند آدرس این نود برای اتصال بیرونی localhost:9092 است. این تنظیم برای حالتی که قرار است روی سیستم خودمان به کافکای درون داکر متصل شویم مناسب است چون داکر دسکتاپ عملیات پورت فورواردینگ را برای ما انجام میدهد و زمانی که برنامه پایتون ما به localhost:9092 متصل میشود، این درخواست به کلاستر کافکا و کانتینر مربوطه ارسال خواهد اما در دنیای واقعی این آدرس باید آدرس یا یک IP باشد که برنامه ها به آن دسترسی داشته باشند.
اگر چند نود در شبکه داشتیم، معمولاً یک Listener داخلی (INTERNAL) هم تعریف میشود برای ارتباط بین خود نودها، جدا از اتصالات بیرونی.
در حالت KRaft، هر کنترلر برای تصمیمگیری در اجماع رأی میدهد.
در حالت تکنودی، فقط یک رأیدهنده داریم:
KAFKA_CONTROLLER_QUORUM_VOTERS=1@localhost:9093
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: تعداد نسخههای کپی از تاپیک offset (در حالت تکنودی، عدد ۱ است).KAFKA_LOG_DIRS: مسیر ذخیره دادهها داخل کانتینر.volumes: تضمین میکند دادهها با توقف کانتینر از بین نرود.docker compose up -ddocker exec -it kafka-node sh cd /opt/kafka/bin./kafka-topics.sh --bootstrap-server localhost:9092 --create --topic test-topic./kafka-console-producer.sh --bootstrap-server localhost:9092 --topic test-topic./kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test-topic --from-beginningdocker compose down