Hướng dẫn

Cách chạy tác vụ nền trong ứng dụng web: hàng đợi, bộ lập lịch và cron

Để chạy tác vụ nền trong ứng dụng web, trước tiên hãy chia công việc thành hai loại. Tác vụ được kích hoạt (gửi email chào mừng, xử lý một tệp tải lên) có thể được lưu vào một hàng đợi tác vụ, thường là một bảng trong cơ sở dữ liệu, và được một worker xử lý với khả năng thử lại. Tác vụ theo lịch (báo cáo hằng đêm, nhắc nhở mỗi 15 phút) cần một thứ gì đó kích hoạt theo thời gian biểu: tính năng cron của host, hoặc một bộ lập lịch bên ngoài gọi một endpoint được bảo vệ trong ứng dụng của bạn. Luôn đảm bảo tác vụ an toàn khi chạy hai lần, ghi nhận các lỗi, và không bao giờ dựa vào bộ hẹn giờ bên trong một máy chủ có thể ngủ hoặc khởi động lại.

Hướng dẫn này giải thích các lựa chọn, khi nào mỗi lựa chọn phù hợp, và cách thiết lập chúng với công cụ xây dựng ứng dụng bằng AI, kể cả trên các host tự co giãn về không.

Tác vụ nền bao gồm những gì

Bất cứ thứ gì chậm, không đáng tin cậy, hoặc không cần thiết cho phản hồi tức thời của người dùng:

  • Gửi email, thông báo và biên lai
  • Thay đổi kích thước ảnh, chuyển mã video, tạo PDF
  • Gọi các API bên thứ ba chậm, bao gồm cả mô hình AI cho các tác vụ dài
  • Nhập hoặc đồng bộ dữ liệu từ một hệ thống khác
  • Dọn dẹp định kỳ hằng đêm, báo cáo và nhắc nhở

Làm việc này ngay trong yêu cầu sẽ khiến trang chậm và dễ hỏng: nếu nhà cung cấp email ngừng hoạt động, việc đăng ký của người dùng sẽ thất bại. Chuyển nó sang nền nghĩa là người dùng nhận phản hồi tức thì và tác vụ có thể được thử lại.

Các lựa chọn

Lựa chọnCách hoạt độngƯu điểmNhược điểm
Chạy và quên ngay trong cùng tiến trìnhPhản hồi, rồi tiếp tục công việc trên máy chủKhông cần thiết lậpMất nếu máy chủ dừng; không có thử lại
Bộ hẹn giờ trong tiến trình (setInterval, setTimeout)Một bộ hẹn giờ trong máy chủ đang chạyRất đơn giảnKhông chạy khi ngủ; trùng lặp khi có nhiều bản sao
Hàng đợi trên cơ sở dữ liệuTác vụ được lưu thành các hàng; một worker nhận và chạy chúngDùng cơ sở dữ liệu bạn đã có; bền vững; dễ kiểm traBạn phải tự xây dựng cơ chế thử lại và khóa; cần thứ gì đó để chạy worker
Hàng đợi chuyên dụng (dựa trên Redis hoặc được quản lý)Một dịch vụ hàng đợi cùng các workerTính năng thử lại và lập lịch trưởng thànhThêm một dịch vụ để vận hành và trả tiền
Dịch vụ tác vụ hoặc workflow được host sẵnBên thứ ba gọi các endpoint của bạn với khả năng thử lại và lịch chạyViệc lập lịch và thử lại được xử lý cho bạnPhụ thuộc nhà cung cấp; thêm một tài khoản và khóa
Bộ lập lịch bên ngoài gọi một endpointMột bộ hẹn giờ ở nơi khác gửi yêu cầu HTTP theo lịchHoạt động trên mọi host, kể cả scale-to-zeroKhoảng thời gian tối thiểu và độ trễ; phải bảo vệ endpoint
Cron tích hợp sẵn của hostNền tảng chạy một lệnh theo lịchĐơn giản ở nơi có sẵnKhông phải host nào cũng cung cấp

Không có một câu trả lời duy nhất đúng. Một ứng dụng nhỏ thường chỉ cần một hàng đợi trên cơ sở dữ liệu cộng với một bộ lập lịch bên ngoài.

Vì sao các host tự co giãn về không thay đổi bức tranh

Nhiều host hiện đại đưa ứng dụng của bạn vào trạng thái ngủ khi không ai dùng và đánh thức nó ở yêu cầu tiếp theo. Điều đó tiết kiệm tiền, nhưng một máy chủ đang ngủ không chạy mã: bộ hẹn giờ không kích hoạt và worker không thăm dò. Trên các host này, công việc theo lịch phải bắt đầu bằng một yêu cầu đến, và nguồn yêu cầu dễ nhất là một bộ lập lịch bên ngoài. Mỗi lần gọi sẽ đánh thức ứng dụng (và thường là cơ sở dữ liệu của nó), nên gọi mỗi phút tốn kém hơn gọi mỗi 15 phút. Hãy chọn lịch chậm nhất vẫn đáp ứng được nhu cầu.

Mẫu 1: hàng đợi tác vụ trên cơ sở dữ liệu

Đối với tác vụ được kích hoạt:

  1. Tạo một bảng jobs: type, payload (JSON), status (pending, running, done, failed), attempts, run_after, last_error, các dấu thời gian.
  2. Khi có sự kiện xảy ra, chèn một hàng job trong cùng một transaction với thay đổi đã gây ra nó, để chúng cùng thành công hoặc cùng thất bại.
  3. Một worker lấy các tác vụ đến hạn, đánh dấu running, thực hiện công việc và đánh dấu done.
  4. Khi thất bại, tăng attempts, đặt run_after muộn hơn (ví dụ 1, 5, rồi 30 phút) và lưu lỗi. Sau số lần tối đa, đánh dấu failed và cảnh báo ai đó.

Nếu có nhiều hơn một worker có thể chạy cùng lúc, các tác vụ phải được nhận một cách an toàn. Trên Postgres, SELECT ... FOR UPDATE SKIP LOCKED cho phép mỗi worker nhận các hàng khác nhau mà không xung đột.

Cái gì chạy worker? Trên một máy chủ luôn bật, là một vòng lặp trong một tiến trình riêng. Trên host tự co giãn về không, endpoint theo lịch trong Mẫu 2 có thể xử lý một lô tác vụ đến hạn ở mỗi lần gọi.

Mẫu 2: bộ lập lịch bên ngoài gọi ứng dụng của bạn

Đối với tác vụ theo lịch:

  1. Thêm một endpoint như POST /api/cron/send-reminders.
  2. Bảo vệ nó: yêu cầu một token bí mật trong header, được lưu như một bí mật ở cả hai phía, và từ chối mọi thứ khác.
  3. Làm cho nó idempotent: chạy hai lần trong cùng một phút không được gửi hai lời nhắc. Ghi lại những gì đã được gửi.
  4. Giữ mỗi lần gọi ngắn: xử lý một lô (ví dụ 100 mục) và để lần gọi tiếp theo xử lý phần còn lại.
  5. Hướng một bộ lập lịch vào endpoint đó.

Các lựa chọn bộ lập lịch:

  • Workflow theo lịch của GitHub Actions. Miễn phí trong giới hạn sử dụng của GitHub. Tính đến tháng 9 năm 2026, tài liệu của GitHub nói rằng khoảng thời gian ngắn nhất là mỗi 5 phút, các lần chạy có thể bị trễ vào lúc bận (đặc biệt là đầu mỗi giờ), lịch mặc định dùng UTC, và các workflow theo lịch trong một kho lưu trữ công khai sẽ bị tắt sau 60 ngày không có hoạt động trong kho lưu trữ.
  • Dịch vụ cron được host sẵn. Có nhiều dịch vụ mà công việc duy nhất là gọi một URL theo lịch. Hãy kiểm tra độ tin cậy, khoảng thời gian tối thiểu và cảnh báo trước khi phụ thuộc vào một dịch vụ.
  • Bộ lập lịch của nhà cung cấp đám mây. Nếu bạn đã dùng một nhà cung cấp đám mây lớn, họ sẽ có một bộ lập lịch được quản lý có thể gọi một endpoint HTTPS.
  • Dịch vụ tác vụ hoặc workflow được host sẵn. Các dịch vụ này kết hợp lập lịch, hàng đợi và thử lại, và gọi các endpoint của bạn cho từng bước. Hãy so sánh giá và giới hạn trên trang của từng nhà cung cấp.

Mẫu 3: để nhà cung cấp làm việc đó

Đôi khi tác vụ nền tốt nhất là không có tác vụ nào:

  • Thanh toán. Stripe thử lại các khoản thanh toán đăng ký thất bại và gửi webhook; bạn phản ứng thay vì thăm dò. Xem webhook là gì.
  • Email. Các nhà cung cấp xếp hàng và thử lại việc gửi khi bạn đã chuyển tin nhắn cho họ.
  • Công việc AI hàng loạt. OpenAI và Anthropic cung cấp các batch API cho các yêu cầu không gấp mà bạn gửi và thu thập kết quả sau.

Prompt để đưa cho công cụ xây dựng AI của bạn

Cho một hàng đợi:

Thêm một hàng đợi tác vụ nền dùng một bảng jobs trong cơ sở dữ liệu của chúng ta (type, payload JSON, status, attempts, run_after, last_error). Khi người dùng đăng ký, chèn một tác vụ send_welcome_email trong cùng transaction thay vì gửi trực tiếp. Thêm một hàm processJobs(limit) nhận các tác vụ đến hạn bằng SELECT ... FOR UPDATE SKIP LOCKED, chạy chúng, và thử lại các lần thất bại sau 1, 5 và 30 phút, đánh dấu failed sau 4 lần thử.

Cho một kích hoạt theo lịch:

Thêm POST /api/cron/tick được bảo vệ bằng bearer token từ bí mật CRON_SECRET; từ chối mọi yêu cầu không có nó. Mỗi lần gọi chạy processJobs(100) và gửi các nhắc nhở đặt lịch đến hạn trong 24 giờ tới mà chưa được gửi, ghi lại các nhắc nhở đã gửi để không gì được gửi hai lần. Trả về một bản tóm tắt JSON về những gì đã chạy. Sau đó viết một workflow GitHub Actions gọi endpoint này mỗi 15 phút, đọc URL và token từ repository secrets.

Những sai lầm thường gặp

  • Dựa vào setInterval. Nó âm thầm dừng khi máy chủ ngủ hoặc khởi động lại, và chạy chồng lên nhau khi hai bản sao cùng chạy.
  • Một endpoint cron không được bảo vệ. Bất kỳ ai tìm thấy nó đều có thể kích hoạt các tác vụ của bạn, hoặc làm tăng hóa đơn email của bạn.
  • Tác vụ không idempotent. Việc thử lại và các lần gọi bộ lập lịch trùng lặp chắc chắn sẽ xảy ra. Hãy thiết kế để xử lý điều đó.
  • Không thấy được lỗi. Một tác vụ thất bại âm thầm suốt một tuần còn tệ hơn một tác vụ thất bại ồn ào. Ghi lại lỗi và cảnh báo khi lỗi lặp lại.
  • Chạy dài trong một yêu cầu. Yêu cầu sẽ hết thời gian chờ. Hãy xử lý theo lô.
  • Lập lịch quá thường xuyên. Mỗi lần gọi trên host tự co giãn về không sẽ đánh thức và tính phí cho ứng dụng. Hãy khớp khoảng thời gian với nhu cầu thực tế.
  • Múi giờ. "9 giờ sáng" có ý nghĩa khác nhau với bộ lập lịch của bạn (thường là UTC) và với người dùng. Lưu thời gian dưới dạng UTC và chuyển đổi theo từng người dùng.
  • Bí mật trong tệp workflow. Giữ token trong kho bí mật của bộ lập lịch. Xem cách giữ an toàn cho khóa API.

Danh sách kiểm tra

  • Công việc chậm đã được chuyển ra khỏi yêu cầu của người dùng
  • Tác vụ được lưu bền vững, không chỉ trong bộ nhớ
  • Thử lại với độ trễ tăng dần và có giới hạn tối đa
  • Mọi tác vụ an toàn khi chạy hai lần
  • Endpoint theo lịch được bảo vệ bằng token bí mật
  • Mỗi lần chạy xử lý một lô có giới hạn
  • Các tác vụ thất bại có thể thấy được, kèm cảnh báo
  • Khoảng thời gian lập lịch được chọn có tính đến chi phí hosting
  • Thời gian được lưu theo UTC

Tác vụ nền trong Mythex

Tài liệu của Mythex không mô tả tác vụ theo lịch hay cron, và các ứng dụng đã xuất bản cùng cơ sở dữ liệu của chúng sẽ ngủ khi nhàn rỗi và thức dậy ở yêu cầu tiếp theo (xem Giới hạn hosting). Vì vậy đừng dựa vào bộ hẹn giờ bên trong ứng dụng của bạn. Cách hoạt động là cách đã nêu ở trên: yêu cầu agent tạo một bảng jobs và một endpoint được bảo vệ bằng token, rồi hướng một bộ lập lịch bên ngoài vào URL đã xuất bản của bạn. Lưu token dưới dạng bí mật của dự án, và nhớ rằng mỗi lần đánh thức sẽ tiêu credit cho khoảng thời gian ứng dụng và cơ sở dữ liệu thức, nên hãy chọn khoảng thời gian hợp lý. Nếu ứng dụng của bạn cần một backend API cho việc này, công thức REST API backend là điểm khởi đầu, và cách xây dựng REST API đề cập đến việc thiết kế các endpoint. Nếu các worker hoặc bot chạy liên tục là cốt lõi của sản phẩm, một host được xây dựng cho các tiến trình bền bỉ có thể phù hợp hơn.

Câu hỏi thường gặp

Tác vụ nền là gì?

Tác vụ nền là công việc ứng dụng của bạn thực hiện bên ngoài yêu cầu mà người dùng đang chờ, chẳng hạn như gửi email, thay đổi kích thước ảnh, tạo báo cáo hoặc đồng bộ dữ liệu. Người dùng nhận được phản hồi nhanh, còn tác vụ chạy riêng và có thể thử lại nếu thất bại.

Làm sao chạy một tác vụ theo lịch nếu host của tôi không có cron?

Thêm một endpoint được bảo vệ để thực hiện công việc, rồi để một bộ lập lịch bên ngoài gọi nó theo thời gian biểu. Các lựa chọn gồm một workflow GitHub Actions theo lịch, một dịch vụ cron được host sẵn, hoặc bộ lập lịch của nhà cung cấp đám mây của bạn. Bảo vệ endpoint bằng một token bí mật.

Tôi có thể dùng setInterval hoặc setTimeout cho tác vụ theo lịch không?

Chỉ dành cho các tác vụ nhỏ, không quan trọng trên một máy chủ luôn chạy. Nếu máy chủ khởi động lại, tự co giãn về không hoặc chạy nhiều bản sao, các bộ hẹn giờ sẽ bị mất hoặc chạy nhiều hơn một lần. Hãy lưu công việc theo lịch trong cơ sở dữ liệu hoặc dùng một bộ lập lịch thay thế.

Mythex có hỗ trợ cron job không?

Tài liệu của Mythex không mô tả tác vụ theo lịch hay cron, và các ứng dụng đã xuất bản sẽ ngủ khi nhàn rỗi. Cách đáng tin cậy là một bộ lập lịch bên ngoài gọi một endpoint được bảo vệ trong ứng dụng của bạn, điều này đánh thức ứng dụng và chạy công việc.

Mythex · Pricing · Xây dựng mọi thứ với AI · Mẫu website và ứng dụng · So sánh Mythex · Thuật ngữ xây dựng ứng dụng bằng AI · Công cụ miễn phí để xây dựng ứng dụng bằng AI · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو 简体中文 繁體中文(香港) 繁體中文(台灣)