0

Series Docker & Kafka cho Laravel #1: Kiến trúc KRaft Hiện đại và Cài đặt "Lõi Giao tiếp"

1. Chuẩn Senior: Nói Không với Zookeeper (Chế độ KRaft)

Những bài hướng dẫn cũ trên mạng thường yêu cầu bạn phải dựng 2 container: Một cái cho Zookeeper (để quản lý cụm) và một cái cho Kafka. Điều này làm tăng gấp đôi độ phức tạp cấu hình và ngốn thêm RAM vô ích.

Từ phiên bản 3.3, Kafka đã chính thức tuyên bố Zookeeper là "di sản quá khứ" và giới thiệu chế độ KRaft (Kafka Raft), cho phép Kafka tự quản lý chính nó trong một container duy nhất. Đây là chuẩn mực DevOps hiện tại.

2. Thiết kế bản vẽ Docker Compose cho Kafka KRaft

Tại thư mục chứa file docker-compose.yml của hệ thống, hãy bổ sung Service Kafka dựa trên image của Bitnami (nhà cung cấp Image cực kỳ tối ưu cho môi trường Container):

version: '3.8'

services:
  # Trái tim trung chuyển luồng sự kiện
  kafka:
    image: bitnami/kafka:3.5
    container_name: afc_kafka
    restart: unless-stopped
    ports:
      # Port 9092 dùng để Laravel kết nối vào gửi/nhận dữ liệu
      - "9092:9092"
    environment:
      # 1. BẬT CHẾ ĐỘ KRAFT (Bỏ qua Zookeeper)
      - KAFKA_CFG_NODE_ID=1
      - KAFKA_CFG_PROCESS_ROLES=controller,broker
      - KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=1@kafka:9093
      
      # 2. CẤU HÌNH GIAO TIẾP MẠNG
      # Mở 2 luồng: Một cho Controller quản lý nội bộ, Một cho Client bên ngoài (như Laravel) kết nối
      - KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093
      - KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT
      - KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
      
      # Địa chỉ mà Kafka báo cho Laravel biết để kết nối tới
      # Nếu Laravel chạy cùng mạng Docker, dùng tên container 'kafka'. Nếu test từ host, dùng 'localhost'
      - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://kafka:9092
      
      # 3. TỐI ƯU HÓA LƯU TRỮ
      # Xóa log sự kiện sau 7 ngày (tránh đầy ổ cứng) thay vì lưu vĩnh viễn
      - KAFKA_CFG_LOG_RETENTION_HOURS=168
    volumes:
      # Map Volume để đảm bảo Kafka không quên dữ liệu khi restart
      - kafka_data:/bitnami/kafka
    networks:
      - afc_network

volumes:
  kafka_data:
    driver: local

networks:
  afc_network:
    driver: bridge

Chạy docker-compose up -d. Kafka sẽ mất khoảng 10 giây để bầu cử (elect) Leader theo thuật toán Raft và sẵn sàng hoạt động.

3. Cấy "Động cơ C" (librdkafka) vào lõi PHP-FPM

Tương tự như PhpRedis ở bài trước, để Laravel nói chuyện được với Kafka với tốc độ hàng triệu message/giây mà không làm cháy CPU, nó cần một thư viện được viết bằng ngôn ngữ C. Đó là librdkafka.

Hãy mở file Dockerfile của Container PHP-FPM lên và bổ sung các lệnh cài đặt extension này:

# Sử dụng base image PHP
FROM php:8.2-fpm

# 1. Cài đặt các thư viện lõi của hệ điều hành, đặc biệt là librdkafka-dev
RUN apt-get update && apt-get install -y \
    git \
    unzip \
    librdkafka-dev \
    # ... (các thư viện khác)

# 2. Dùng PECL để biên dịch và cài extension rdkafka cho PHP
RUN pecl install rdkafka \
    && docker-php-ext-enable rdkafka

# ... (các bước copy code và phân quyền)

Sau đó, chạy lại lệnh docker-compose build app để Docker đúc lại một container PHP mới được vũ trang đầy đủ.

4. Tích hợp Package Kafka cho Laravel

Với PHP Extension đã sẵn sàng, chúng ta vào bên trong Container của Laravel và cài đặt một package đóng vai trò làm cầu nối (Wrapper).

Thay vì phải tự viết các vòng lặp While vô tận rất dễ rò rỉ bộ nhớ (Memory Leak), cộng đồng Laravel hiện tại sử dụng gói mateusjunges/laravel-kafka cực kỳ xịn sò. Nó tích hợp sâu vào hệ sinh thái của Laravel (hỗ trợ config, artisan command, serialization).

# Cài đặt package
composer require mateusjunges/laravel-kafka

Xuất file cấu hình để tiện tinh chỉnh:

php artisan vendor:publish --tag=laravel-kafka-config

Cuối cùng, mở file .env ra và khai báo địa chỉ của Kafka Broker:

# Trỏ về tên container của Kafka trong mạng Docker
KAFKA_BROKERS=kafka:9092

Tổng kết Bài 1

Chúng ta đã trải thảm đỏ thành công cho hệ thống Hướng sự kiện (Event-Driven). Kafka KRaft Mode đang chạy ổn định, tiết kiệm tài nguyên. PHP đã được độ thêm lõi C (rdkafka) để tối ưu tốc độ, và Laravel đã có bộ thư viện chuẩn bị sẵn sàng.

Ở Bài 2, bạn muốn chúng ta trực tiếp viết code đóng vai Producer (Bắn sự kiện "Hành khách quẹt thẻ" vào mạng lưới) và xây dựng một Consumer (Worker chạy ngầm liên tục 24/7 để hứng sự kiện, xử lý trừ tiền và đồng bộ đối tác một cách an toàn mà không bị rò rỉ RAM)?


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí