+3

Đừng bao giờ Hardcode tên Kafka Topic: Bí mật "sống còn" đằng sau file .env.example

Chào anh em cộng đồng Viblo!

Trong các bài viết trước về Kafka, để code ngắn gọn và dễ hiểu, mình thường viết thẳng tên Topic vào hàm như thế này: Kafka::publishOn('order-events').

Nhưng nếu trong code Production của công ty mà bạn gõ dòng này, khả năng cao là bạn sẽ bị Tech Lead "gõ đầu" ngay lập tức trong buổi Review Code, kèm theo lời nhắn: "Mang tên Topic vứt ra file .env và cập nhật .env.example ngay cho anh!".

Tại sao một cái tên Topic bé tí lại phải làm phức tạp hóa lên như vậy? Rút cuộc ném nó vào file .env.example để làm cái quái gì? Hôm nay chúng ta sẽ bóc trần tư duy quản lý môi trường (Environment Management) của các dự án lớn nhé. Lên xe!

1. Nỗi đau thực tế: Khi Hardcode gây ra "Thảm họa đa vũ trụ"

Giả sử bạn hardcode tên topic là order-events trong source code.

Kịch bản 1: Dev cắn lộn nhau

Công ty bạn không có tiền cấp cho mỗi Dev một cụm Kafka riêng, nên tất cả 5 Dev trong team dùng chung một con Kafka Broker trên server ảo (Shared Dev Environment).

  • Dev A (Hiếu) đang test chức năng tạo đơn hàng, bắn 10 message vào order-events.
  • Dev B (Nam) đang test chức năng tính điểm thưởng, bật Consumer lên lắng nghe order-events.
  • Bùm! Nam đọc nhầm sạch message của Hiếu. Hiếu bật Consumer lên thì thấy message không cánh mà bay. Hai anh em chửi nhau um sùm vì tưởng code của đối phương bị bug!

Kịch bản 2: Bê bối Staging và Production

Code của bạn được đẩy lên môi trường Staging để QC test, và sau đó lên Production. Vô tình, DevOps cấu hình sai mạng, làm cho môi trường Staging trỏ nhầm vào Kafka của Production. Vì tên topic đã bị hardcode cứng là order-events, dữ liệu test của QC (khách hàng "Nguyen Van A Mua Test") bay thẳng vào hệ thống Production, trừ kho thật, giao hàng thật! Thảm họa!

2. Lột xác: Tách biệt môi trường với .env

Để giải quyết vấn đề trên, nguyên tắc bất di bất dịch của Microservices là: Tên Topic phải thay đổi theo môi trường (Dynamic Naming).

Thay vì gõ cứng tên Topic, chúng ta đưa nó vào file .env:

# Môi trường Local của Hiếu
KAFKA_TOPIC_ORDER_EVENTS=dev_hieu_order_events
# Môi trường Local của Nam
KAFKA_TOPIC_ORDER_EVENTS=dev_nam_order_events
# Môi trường Production
KAFKA_TOPIC_ORDER_EVENTS=prod_order_events

Nhờ có tiền tố (prefix) dev_hieu_, prod_... các cụm Kafka dù có dùng chung một Broker đi nữa thì dữ liệu của ai vẫn nằm ở nhà người nấy, tuyệt đối không bao giờ có chuyện Consumer của Nam đọc nhầm tin nhắn của Hiếu!

3. Tại sao lại là .env.example? (Nhân vật chính)

Bạn vứt tên topic vào .env là xong việc của bạn. Nhưng ngày hôm sau, một nhân sự mới vào công ty. Cậu ấy pull code từ Github về, chạy composer install, và làm thao tác quen thuộc: cp .env.example .env.

Nhưng ôi thôi, cậu ấy chạy app lên và nhận một đống lỗi: Topic not configured. Tại sao? Vì file .env không bao giờ được push lên Git (để bảo mật), và bạn đã quên cập nhật file .env.example!

Vai trò thực sự của .env.example:

  1. Nó là Bản thiết kế hạ tầng (Infrastructure Blueprint): Nó nói cho toàn bộ team, DevOps, và CI/CD biết rằng: "Ê, cái project này để chạy được thì cần phải cung cấp một cái Kafka Topic cho sự kiện Order đấy nhé!".
  2. Định hướng giá trị mặc định: Thay vì để trống, bạn định hướng luôn cách đặt tên cho team.
# Trích xuất từ file .env.example
KAFKA_BROKERS=localhost:9092
KAFKA_TOPIC_ORDER_EVENTS=your_name_order_events
  1. Tự động hóa CI/CD: Khi CI/CD (như Jenkins, Github Actions) build app trên server ảo để chạy Unit Test, nó sẽ tự động đọc file .env.example để biết cần phải gán những biến môi trường (Environment Variables) nào vào container. Thiếu file này, test tự động sẽ gãy!

4. Tuyệt chiêu "Hạng nặng" trong Laravel

Việc ném cấu hình vào .env là chuẩn, nhưng nếu bạn gọi env('KAFKA_TOPIC_ORDER_EVENTS')rải rác khắp nơi trong Controller hay Job thì bạn lại mắc thêm một sai lầm chết người nữa (Laravel không khuyến khích dùng hàm env() ngoài các file config, vì khi chạy lệnh php artisan config:cache nó sẽ return null).

Cách làm chuẩn Senior:

Bước 1: Cấu hình ở .env.env.example

KAFKA_TOPIC_ORDER_EVENTS=hieu_order_events

Bước 2: Nạp vào config/kafka.php

(Tạo file nếu chưa có)

return [
    'topics' => [
        'order_events' => env('KAFKA_TOPIC_ORDER_EVENTS', 'default_order_events'),
    ],
];

Bước 3: Code gọi qua hàm config()

$topic = config('kafka.topics.order_events');

Kafka::publishOn($topic)
    ->withMessage($message)
    ->send();

Thậm chí, ở các công ty lớn, thay vì bắt Dev tự khai báo từng cái tên topic rườm rà, người ta quy ước chỉ truyền cái Prefix ở .env thôi: APP_ENV_PREFIX=dev_hieu_ Sau đó trong code sẽ tự động nối chuỗi: $topic = config('app.env_prefix') . 'order_events'; Cực kỳ nhàn và không bao giờ lo xung đột!

Lời kết

Việc config Topic Name vào .env.example không phải là một thao tác thừa thãi hay làm khó nhau. Nó là Bản hợp đồng giao tiếp giữa bạn, các đồng nghiệp khác, đội ngũ DevOps và chính hệ thống vận hành.

Bất cứ khi nào bạn tích hợp một dịch vụ bên ngoài (Kafka, Redis, API Third-party, Bucket S3), hãy tạo thói quen: Đưa tham số vào .env, và lập tức copy nó sang .env.example làm tài liệu. Chỉ một hành động nhỏ này thôi cũng đủ để đánh giá bạn có phải là một lập trình viên có tư duy làm việc nhóm (Teamwork) tốt hay không.

Dự án hiện tại của anh em có hay bị "ăn hành" vì thành viên team quên push key vào .env.example không? Chia sẻ những pha debug mù mắt dưới phần bình luận nhé!

Chúc anh em code xịn, môi trường nào cũng chạy mượt!


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í