0

Series Docker & Beanstalkd cho Laravel #1: Kiến tạo Hàng đợi Chuyên trách (Dedicated Queue) siêu nhẹ

1. Nỗi đau mất Job và Tư duy tự build Image (Chuẩn Senior)

Nếu bạn lên Docker Hub tìm kiếm beanstalkd, bạn sẽ ngạc nhiên vì không có Image Official (Chính chủ) nào cả. Hầu hết các bản hướng dẫn trên mạng sẽ bảo bạn kéo các Image trôi nổi (như schickling/beanstalkd). Việc dùng Image không rõ nguồn gốc trên môi trường Production là một rủi ro bảo mật nghiêm trọng.

Chuẩn Senior: Chúng ta sẽ không dùng Image trôi nổi. Chúng ta sẽ dùng Image alpine (hệ điều hành siêu nhẹ của Linux, được bảo chứng an toàn) và tự cài Beanstalkd trực tiếp vào đó thông qua file docker-compose.yml. Đồng thời, bắt buộc phải bật tính năng Binlog để không bị mất Job khi Server khởi động lại.

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

Hãy mở file docker-compose.yml và thêm Service Beanstalkd vào hạ tầng của bạn:

version: '3.8'

services:
  # ... (các service khác như nginx, php, mysql)

  # Hàng đợi chuyên trách Beanstalkd
  beanstalkd:
    image: alpine:3.18
    container_name: afc_beanstalkd
    # Chạy lệnh cài đặt Beanstalkd và khởi động ngay lập tức
    command: >
      sh -c "apk add --no-cache beanstalkd && 
             beanstalkd -p 11300 -u nobody -b /var/lib/beanstalkd -f 60000 -s 10485760"
    ports:
      - "11300:11300"
    volumes:
      # Map Volume để bảo vệ dữ liệu Binlog (Chống mất Job khi restart container)
      - beanstalkd_data:/var/lib/beanstalkd
    networks:
      - afc_network
    restart: unless-stopped

volumes:
  beanstalkd_data:
    driver: local

networks:
  afc_network:
    driver: bridge

Giải phẫu các tham số sinh tử trong dòng lệnh Command:

  • -p 11300: Mở cổng chuẩn của Beanstalkd.
  • -u nobody: Chạy tiến trình bằng user nobody (không có quyền root) để tối đa hóa bảo mật. Nếu Hacker chiếm quyền được Beanstalkd, chúng cũng không thể phá hoại hệ điều hành.
  • -b /var/lib/beanstalkd: Cực kỳ quan trọng. Bật tính năng Binlog và trỏ vào thư mục lưu trữ. Mọi Job đẩy vào RAM sẽ lập tức được ghi thêm một bản sao xuống ổ cứng. Container sập? Khởi động lại, Beanstalkd sẽ tự đọc file binlog và phục hồi lại toàn bộ Job đang dang dở.
  • -f 60000: Ép Beanstalkd đồng bộ dữ liệu từ RAM xuống ổ cứng vật lý (fsync) mỗi 60.000 mili-giây (1 phút) để giảm tải Disk I/O.
  • -s 10485760: Giới hạn kích thước file binlog ở mức 10MB, tự động chia nhỏ file (rotate) để ổ cứng không bị phân mảnh.

3. Trang bị Driver giao tiếp cho Laravel

Container Beanstalkd đã chạy ngầm và chờ đợi. Giờ là lúc cấu hình Laravel.

Mặc định, Laravel không kèm sẵn bộ thư viện để nói chuyện với Beanstalkd. Bạn phải cài đặt package pda/pheanstalk – đây là Driver chuẩn được Laravel khuyên dùng.

Mở Terminal của Container PHP-FPM lên và chạy lệnh:

composer require pda/pheanstalk

4. Định tuyến Queue sang Beanstalkd

Tiếp theo, chúng ta chỉ định cho Laravel biết: "Từ nay trở đi, mọi Job hãy ném vào Beanstalkd thay vì Redis hay Database".

Mở file .env và cập nhật các biến môi trường:

# Đổi driver của Queue sang Beanstalkd
QUEUE_CONNECTION=beanstalkd

# Định nghĩa thông tin kết nối
BEANSTALKD_HOST=beanstalkd # Tên container trong mạng Docker
BEANSTALKD_PORT=11300
BEANSTALKD_QUEUE=default

Tiếp tục mở file config/queue.php để xem qua cấu hình lõi mà Laravel đã chu đáo chuẩn bị sẵn cho chúng ta:

'beanstalkd' => [
            'driver' => 'beanstalkd',
            'host' => env('BEANSTALKD_HOST', 'localhost'),
            'queue' => env('BEANSTALKD_QUEUE', 'default'),
            'retry_after' => (int) env('BEANSTALKD_RETRY_AFTER', 90),
            'block_for' => 0,
            'after_commit' => false,
        ],

Lưu ý cho Senior: Cái tham số 'retry_after' => 90 có ý nghĩa sống còn. Nó quy định thời gian (Time-To-Run / TTR). Nghĩa là, khi một Worker (Công nhân) nhận Job "Đồng bộ vé Hitachi", nó có 90 giây để hoàn thành. Nếu sau 90 giây mà Worker này chưa báo cáo kết quả (có thể do lỗi mạng, bị treo rớt mạng), Beanstalkd sẽ tự động lấy cái Job đó ném lại vào hàng đợi để cho một Worker khác xử lý!

Tổng kết Bài 1

Bằng việc tự định nghĩa khởi chạy qua Alpine Linux và thiết lập các cờ (flags) tối ưu Binlog, chúng ta đã đúc thành công một "nhà máy" Beanstalkd hoàn toàn độc lập, an toàn và bền bỉ (Persistence). Không cần chia sẻ RAM với Redis, không cồng kềnh như Kafka, hệ thống của bạn giờ đây đã có một người vận chuyển Background Job nhẹ như lông hồng.

Ở Bài 2, bạn muốn chúng ta đi sâu vào cách Quản lý Vòng đời (Lifecycle) của một Job trong Beanstalkd (Ready, Reserved, Delayed, Buried) bằng code thực tế, hay muốn thiết lập một Giao diện Dashboard (như Beanstalkd Console) trong Docker để trực quan hóa việc giám sát các ống Tube (Hàng đợi) đang nghẽn?


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.