Giải Pháp Triển Khai Cơ Chế Tương Tự Crontab Trong Skynet - nói dối e blog

Giải Pháp Triển Khai Cơ Chế Tương Tự Crontab Trong Skynet

Có nhiều người từng thắc mắc tại sao hệ thống định thời của skynet không đồng bộ với thời gian hệ thống. Câu trả lời của tôi là: skynet cố ý thiết kế cơ chế đếm thời gian nội bộ theo nguyên tắc “tăng đơn điệu” (monotonic). Chính nhờ nguyên tắc này mà hệ thống có thể tránh được nhiều vấn đề phức tạp phát sinh từ việc thời gian hệ thống thay đổi đột ngột.

Vậy làm thế nào để xây dựng một cơ chế nhiệm vụ định kỳ tương tự crontab, vừa có thể phản ứng linh hoạt với sự điều chỉnh thời gian hệ thống? Câu trả lời là: Đây là yêu cầu thuộc tầng nghiệp vụ, bạn hoàn toàn có thể tự thiết kế theo nhu cầu cụ thể. Tùy vào tần suất định kỳ, khối lượng công việc, bạn có thể lựa chọn nhiều phương án triển khai khác nhau. Tuy nhiên, điểm chung là bạn cần xây dựng một dịch vụ tùy chỉnh trong skynet có khả năng kích hoạt thông điệp theo thời gian quy định, mà không phụ thuộc hoàn toàn vào cơ chế định thời nội bộ của skynet.

Giải pháp đơn giản cho số lượng nhiệm vụ hạn chế

Bạn có thể xây dựng một dịch vụ quản lý nhiệm vụ với cấu trúc dữ liệu dạng bảng không theo thứ tự, lưu trữ các cặp thông tin: thời điểm kích hoạt - tên nhiệm vụ. Ví dụ: “Lấy thưởng lúc 21h” hoặc “Gửi báo cáo ngày lúc 0h”. Các nhiệm vụ này được đăng ký từ nhiều nơi khác nhau trong hệ thống, và tên nhiệm vụ có thể là một chuỗi ký tự bất kỳ.

Ưu điểm của việc đính kèm thời gian trong thông báo là giúp bên nhận tự động xử lý các trường hợp trùng lặp. Ví dụ: nếu có sự cố mạng làm gián đoạn xử lý, khi hệ thống khôi phục, bên nhận có thể kiểm tra thời gian trong thông báo để quyết định có xử lý lại hay không.

Quy trình vận hành

  1. Đăng ký nhiệm vụ: Bộ quản lý nhiệm vụ gửi yêu cầu đăng ký đến dịch vụ định kỳ, cung cấp thời điểm và tên nhiệm vụ.
  2. Theo dõi sự kiện: Các module xử lý nhiệm vụ đăng ký theo dõi (subscribe) các chuỗi thông báo tương ứng.
  3. Kích hoạt theo thời gian: Khi đến thời điểm quy định, dịch vụ sẽ phát đi thông báo chứa tên nhiệm vụ và thời gian thực thi.

Cơ chế kỹ thuật

Dịch vụ này có thể tận dụng hàm skynet.timeout để kích hoạt các sự kiện. Mỗi khi có nhiệm vụ mới được đăng ký, hệ thống sẽ so sánh thời gian kích hoạt với các nhiệm vụ hiện có. Nếu phát hiện nhiệm vụ gần nhất trong tương lai, hệ thống sẽ thiết lập một callback mới thông qua skynet.timeout.

Khi nhận tín hiệu timeout, dịch vụ sẽ:

  • Kiểm tra xem nhiệm vụ gần nhất đã đến thời điểm kích hoạt chưa
  • Gửi thông báo tương ứng nếu điều kiện thỏa mãn
  • Tìm kiếm nhiệm vụ tiếp theo gần nhất để thiết lập timeout mới

Giải thuật này có độ phức tạp O(n), nhưng lại cực kỳ đơn giản để triển khai. Trong thực tế, số lượng nhiệm vụ định kỳ thường không quá lớn, nên phương pháp này hoàn toàn khả thi.

Đồng bộ với thời gian hệ thống

Skynet cung cấp hai hàm tiện ích:

  • skynet.now(): Trả về thời gian trôi qua kể từ khi tiến trình khởi động (theo đơn vị giây)
  • skynet.starttime(): Trả về thời điểm tiến trình khởi động theo giờ UTC

Để đồng bộ với thời gian hệ thống, bạn có thể:

  1. Ghi nhận thời điểm khởi động thực tế thông qua skynet.starttime()
  2. Tính toán thời gian hiện tại bằng công thức: skynet.starttime() + skynet.now()
  3. Sử dụng giá trị này làm mốc thời gian chuẩn để so sánh với thời điểm kích hoạt của các nhiệm vụ

Hỗ trợ kích hoạt từ bên ngoài

Dịch vụ có thể được mở rộng để chấp nhận lệnh kích hoạt từ bên ngoài thông qua:

  • Kết nối socket TCP/UDP
  • Giao thức HTTP RESTful

Điều này cho phép bạn tận dụng hệ thống crontab của hệ điều hành để gửi lệnh đến tiến trình skynet theo lịch trình định sẵn. Ví dụ:

1
2
# Ví dụ crontab hệ thống
0 21 * * * curl 

Lưu ý quan trọng

Trước đây, skynet sử dụng CLOCK_MONOTONIC_RAW - loại đồng hồ không bị ảnh hưởng bởi điều chỉnh NTP. Tuy nhiên, điều này dẫn đến hiện tượng lệch thời gian kéo dài khi tiến trình chạy trong nhiều tuần/tháng. Giải pháp đã được cập nhật vào ngày 18 tháng 11: chuyển sang sử dụng CLOCK_MONOTONIC, vừa đảm bảo tính liên tục của thời gian, vừa cho phép đồng bộ hóa với thời gian mạng thông qua NTP.

Lợi ích của giải pháp

  • Tối ưu hóa tài nguyên: Tránh việc phải xây dựng lại một hệ thống crontab hoàn chỉnh với ngôn ngữ DSL phức tạp
  • Tính linh hoạt: Hỗ trợ cả cơ chế định kỳ nội bộ và kích hoạt từ bên ngoài
  • Khả năng mở rộng: Dễ dàng tích hợp với các hệ thống giám sát và điều phối tác vụ hiện có

  • [Tại sao đồng hồ hệ thống Ubuntu
0%