วิธีรันงานเบื้องหลังในเว็บแอป: คิว ตัวจัดตาราง และ cron
หากต้องการรันงานเบื้องหลังในเว็บแอป ให้แบ่งงานออกเป็นสองประเภทก่อน งานที่ถูกกระตุ้น (ส่งอีเมลต้อนรับ ประมวลผลการอัปโหลด) สามารถบันทึกลง คิวงาน ซึ่งมักเป็นตารางในฐานข้อมูล แล้วให้ worker จัดการพร้อมลองใหม่ได้ ส่วน งานตามกำหนดเวลา (รายงานประจำคืน การเตือนทุก 15 นาที) ต้องใช้บางอย่างที่ทำงานตามตารางเวลา ได้แก่ ฟีเจอร์ cron ของโฮสต์ หรือ ตัวจัดตารางภายนอก ที่เรียกเอนด์พอยต์ที่ปกป้องไว้ในแอปของคุณ ควรทำให้งานปลอดภัยเมื่อรันซ้ำ บันทึกความล้มเหลว และไม่พึ่งตัวจับเวลาภายในเซิร์ฟเวอร์ที่อาจหลับหรือรีสตาร์ท
คู่มือนี้อธิบายตัวเลือก เมื่อไรแต่ละอย่างเหมาะสม และวิธีตั้งค่าด้วยเครื่องมือสร้างแอป AI รวมถึงบนโฮสต์ที่ปรับขนาดเป็นศูนย์
งานเบื้องหลังคืออะไร
สิ่งใดก็ตามที่ช้า ไม่น่าเชื่อถือ หรือไม่จำเป็นต่อการตอบสนองทันทีของผู้ใช้:
- ส่งอีเมล การแจ้งเตือน และใบเสร็จ
- ย่อขนาดรูปภาพ แปลงวิดีโอ สร้าง PDF
- เรียก API ภายนอกที่ช้า รวมถึงโมเดล AI สำหรับงานที่ใช้เวลานาน
- นำเข้าหรือซิงก์ข้อมูลจากระบบอื่น
- ทำความสะอาด รายงาน และการเตือนประจำคืน
การทำสิ่งนี้ภายในคำขอทำให้หน้าช้าและเปราะบาง หากผู้ให้บริการอีเมลล่ม การสมัครสมาชิกของผู้ใช้ก็ล้มเหลวไปด้วย การย้ายไปเบื้องหลังทำให้ผู้ใช้ได้รับการตอบสนองทันที และงานลองใหม่ได้
ตัวเลือก
| ตัวเลือก | การทำงาน | ข้อดี | ข้อเสีย |
|---|---|---|---|
| Fire-and-forget ในโปรเซสเดียวกัน | ตอบกลับ แล้วทำงานต่อในเซิร์ฟเวอร์ | ไม่ต้องตั้งค่า | หายหากเซิร์ฟเวอร์หยุด ไม่มีการลองใหม่ |
ตัวจับเวลาในโปรเซส (setInterval, setTimeout) | ตัวจับเวลาในเซิร์ฟเวอร์ที่กำลังทำงาน | ง่ายมาก | ไม่ทำงานขณะหลับ ซ้ำกันเมื่อมีหลายสำเนา |
| คิวบนฐานข้อมูล | งานถูกบันทึกเป็นแถว worker รับและรัน | ใช้ฐานข้อมูลที่มีอยู่ ทนทาน ตรวจสอบง่าย | คุณต้องสร้างการลองใหม่และการล็อกเอง ต้องมีสิ่งที่รัน worker |
| คิวเฉพาะ (ใช้ Redis หรือแบบจัดการ) | บริการคิวกับ worker | ฟีเจอร์การลองใหม่และการตั้งเวลาที่สมบูรณ์ | มีบริการอีกตัวที่ต้องรันและจ่ายเงิน |
| บริการงานหรือเวิร์กโฟลว์แบบโฮสต์ | บุคคลที่สามเรียกเอนด์พอยต์ของคุณพร้อมการลองใหม่และตาราง | จัดการการตั้งเวลาและการลองใหม่ให้ | พึ่งพาผู้ขาย มีบัญชีและคีย์อีกชุด |
| ตัวจัดตารางภายนอกที่เรียกเอนด์พอยต์ | ตัวจับเวลาที่อื่นส่งคำขอ HTTP ตามตาราง | ทำงานได้กับทุกโฮสต์ รวมถึงแบบปรับขนาดเป็นศูนย์ | มีช่วงเวลาขั้นต่ำและความล่าช้า ต้องปกป้องเอนด์พอยต์ |
| cron ในตัวของโฮสต์ | แพลตฟอร์มรันคำสั่งตามตาราง | ง่ายในที่ที่มี | โฮสต์ไม่ได้มีทุกแบบ |
ไม่มีคำตอบเดียวที่ถูกต้องเสมอไป แอปขนาดเล็กมักต้องการแค่คิวบนฐานข้อมูลบวกกับตัวจัดตารางภายนอก
ทำไมโฮสต์ที่ปรับขนาดเป็นศูนย์จึงเปลี่ยนภาพ
โฮสต์สมัยใหม่หลายแห่งทำให้แอปของคุณหลับเมื่อไม่มีใครใช้ และปลุกเมื่อมีคำขอถัดไป ซึ่งช่วยประหยัดเงิน แต่เซิร์ฟเวอร์ที่หลับไม่รันโค้ดใด ๆ ตัวจับเวลาไม่ทำงานและ worker ไม่ตรวจคิว บนโฮสต์เหล่านี้ งานตามกำหนดเวลาต้อง เริ่มจากคำขอที่เข้ามา และแหล่งที่ง่ายที่สุดของคำขอนั้นคือตัวจัดตารางภายนอก การเรียกแต่ละครั้งปลุกแอป (และมักปลุกฐานข้อมูล) ดังนั้นการเรียกทุกนาทีจะเปลืองกว่าทุก 15 นาที เลือกตารางที่ช้าที่สุดที่ยังตอบโจทย์ความต้องการ
รูปแบบที่ 1: คิวงานบนฐานข้อมูล
สำหรับงานที่ถูกกระตุ้น:
- สร้างตาราง
jobs: ประเภท, payload (JSON), สถานะ (pending,running,done,failed), จำนวนครั้งที่พยายาม, run_after, last_error และเวลา - เมื่อมีเหตุการณ์เกิดขึ้น ให้ แทรกแถวงาน ในธุรกรรมเดียวกันกับการเปลี่ยนแปลงที่ก่อให้เกิดงานนั้น เพื่อให้สำเร็จหรือล้มเหลวด้วยกัน
- worker หยิบงานที่ถึงกำหนด ทำเครื่องหมายเป็น
runningทำงาน แล้วทำเครื่องหมายเป็นdone - เมื่อล้มเหลว เพิ่ม
attemptsตั้งrun_afterให้ช้าลง (เช่น 1, 5 แล้ว 30 นาที) และเก็บข้อผิดพลาดไว้ เมื่อเกินจำนวนสูงสุดให้ทำเครื่องหมายเป็นfailedและแจ้งเตือนใครสักคน
หาก worker หลายตัวอาจทำงานพร้อมกัน งานต้องถูกจับไว้อย่างปลอดภัย บน Postgres SELECT ... FOR UPDATE SKIP LOCKED ช่วยให้แต่ละ worker จับแถวต่างกันโดยไม่ชนกัน
อะไรเป็นตัวรัน worker? บนเซิร์ฟเวอร์ที่ทำงานตลอดเวลา คือลูปในโปรเซสแยก บนโฮสต์ที่ปรับขนาดเป็นศูนย์ เอนด์พอยต์ตามกำหนดเวลาในรูปแบบที่ 2 สามารถประมวลผลงานที่ถึงกำหนดเป็นชุดในแต่ละการเรียกได้
รูปแบบที่ 2: ตัวจัดตารางภายนอกเรียกแอปของคุณ
สำหรับงานตามกำหนดเวลา:
- เพิ่มเอนด์พอยต์ เช่น
POST /api/cron/send-reminders - ปกป้องมัน: ต้องมีโทเค็นลับในเฮดเดอร์ เก็บเป็นความลับทั้งสองฝั่ง และปฏิเสธทุกอย่างที่ไม่ตรง
- ทำให้เป็น idempotent: การรันสองครั้งในนาทีเดียวกันต้องไม่ส่งการเตือนสองครั้ง บันทึกสิ่งที่ส่งไปแล้ว
- ทำให้แต่ละการเรียก สั้น: ประมวลผลเป็นชุด (เช่น 100 รายการ) แล้วให้การเรียกถัดไปรับส่วนที่เหลือ
- ชี้ตัวจัดตารางไปยังเอนด์พอยต์นั้น
ตัวเลือกตัวจัดตาราง:
- เวิร์กโฟลว์ตามกำหนดเวลาของ GitHub Actions ฟรีภายในขีดจำกัดการใช้งานของ GitHub ตามเอกสารของ GitHub ณ เดือนกันยายน 2026 ช่วงเวลาที่สั้นที่สุดคือทุก 5 นาที การรันอาจล่าช้าในช่วงที่มีการใช้งานหนาแน่น (โดยเฉพาะตอนต้นชั่วโมง) ตารางใช้เวลา UTC เป็นค่าเริ่มต้น และเวิร์กโฟลว์ตามกำหนดเวลาในรีโพสิทอรีสาธารณะจะถูกปิดหลัง 60 วันที่ไม่มีกิจกรรมในรีโพสิทอรี
- บริการ cron แบบโฮสต์ มีบริการจำนวนมากที่งานเดียวคือเรียก URL ตามตาราง ตรวจความน่าเชื่อถือ ช่วงเวลาขั้นต่ำ และการแจ้งเตือนก่อนพึ่งพามัน
- ตัวจัดตารางของผู้ให้บริการคลาวด์ หากคุณใช้ผู้ให้บริการคลาวด์รายใหญ่อยู่แล้ว จะมีตัวจัดตารางแบบจัดการที่เรียก HTTPS เอนด์พอยต์ได้
- บริการงานหรือเวิร์กโฟลว์แบบโฮสต์ รวมการตั้งเวลา คิว และการลองใหม่ไว้ด้วยกัน และเรียกเอนด์พอยต์ของคุณสำหรับแต่ละขั้นตอน เปรียบเทียบราคาและขีดจำกัดบนเว็บไซต์ของผู้ขายแต่ละราย
รูปแบบที่ 3: ให้ผู้ให้บริการทำแทน
บางครั้งงานเบื้องหลังที่ดีที่สุดคือไม่มีเลย:
- การชำระเงิน Stripe ลองเรียกเก็บเงินที่ล้มเหลวของการสมัครสมาชิกใหม่และส่ง webhook คุณตอบสนองแทนการ polling ดูwebhook คืออะไร
- อีเมล ผู้ให้บริการจัดคิวและลองส่งใหม่หลังจากคุณส่งข้อความไปแล้ว
- งาน AI จำนวนมาก OpenAI และ Anthropic มี batch API สำหรับคำขอที่ไม่เร่งด่วน ซึ่งคุณส่งไปแล้วไปเก็บผลภายหลัง
พรอมต์ที่ให้เครื่องมือสร้างแอป AI
สำหรับคิว:
เพิ่มคิวงานเบื้องหลังโดยใช้ตาราง jobs ในฐานข้อมูลของเรา (ประเภท, payload JSON, สถานะ, attempts, run_after, last_error) เมื่อผู้ใช้สมัคร ให้แทรกงาน send_welcome_email ในธุรกรรมเดียวกันแทนการส่งทันที เพิ่มฟังก์ชัน processJobs(limit) ที่จับงานที่ถึงกำหนดด้วย SELECT ... FOR UPDATE SKIP LOCKED รันงาน และลองใหม่ข้อผิดพลาดหลัง 1, 5 และ 30 นาที ทำเครื่องหมายเป็น failed หลังพยายาม 4 ครั้ง
สำหรับทริกเกอร์ตามกำหนดเวลา:
เพิ่ม POST /api/cron/tick ที่ปกป้องด้วย bearer token จากความลับ CRON_SECRET ปฏิเสธคำขอที่ไม่มีโทเค็น แต่ละการเรียกรัน processJobs(100) และส่งการเตือนการจองที่ถึงกำหนดภายใน 24 ชั่วโมงข้างหน้าที่ยังไม่ได้ส่ง บันทึกการเตือนที่ส่งแล้วเพื่อไม่ให้ส่งซ้ำ คืนค่าสรุปเป็น JSON ของสิ่งที่รัน แล้วเขียนเวิร์กโฟลว์ GitHub Actions ที่เรียกเอนด์พอยต์นี้ทุก 15 นาที โดยอ่าน URL และโทเค็นจาก repository secrets
ความผิดพลาดที่พบบ่อย
- พึ่ง
setIntervalมันหยุดไปอย่างเงียบ ๆ เมื่อเซิร์ฟเวอร์หลับหรือรีสตาร์ท และทำงานซ้ำเมื่อมีสองสำเนาทำงาน - เอนด์พอยต์ cron ที่ไม่มีการป้องกัน ใครก็ตามที่พบมันสามารถทริกเกอร์งานของคุณ หรือค่าอีเมลของคุณได้
- งานที่ไม่ idempotent การลองใหม่และการเรียกตัวจัดตารางซ้ำจะเกิดขึ้นแน่นอน ออกแบบให้รองรับ
- ไม่มีการมองเห็นความล้มเหลว งานที่ล้มเหลวอย่างเงียบ ๆ หนึ่งสัปดาห์แย่กว่างานที่ล้มเหลวอย่างเด่นชัด บันทึกข้อผิดพลาดและแจ้งเตือนเมื่อล้มเหลวซ้ำ
- การรันยาวในคำขอเดียว คำขอหมดเวลาได้ ให้ประมวลผลเป็นชุด
- ตั้งเวลาถี่เกินไป การเรียกทุกครั้งบนโฮสต์ที่ปรับขนาดเป็นศูนย์ปลุกและคิดเงินแอป เลือกช่วงเวลาให้ตรงกับความต้องการจริง
- เขตเวลา “9 โมงเช้า” หมายถึงสิ่งต่างกันสำหรับตัวจัดตาราง (มักเป็น UTC) และผู้ใช้ของคุณ เก็บเวลาเป็น UTC และแปลงตามผู้ใช้
- ความลับในไฟล์เวิร์กโฟลว์ เก็บโทเค็นไว้ในที่เก็บความลับของตัวจัดตาราง ดูวิธีเก็บคีย์ API ให้ปลอดภัย
รายการตรวจสอบ
- งานที่ช้าถูกย้ายออกจากคำขอของผู้ใช้
- งานถูกเก็บอย่างทนทาน ไม่ได้อยู่แค่ในหน่วยความจำ
- มีการลองใหม่พร้อมระยะเวลาที่เพิ่มขึ้นและจำนวนสูงสุด
- ทุกงานปลอดภัยเมื่อรันสองครั้ง
- เอนด์พอยต์ตามกำหนดเวลาถูกปกป้องด้วยโทเค็นลับ
- การรันแต่ละครั้งประมวลผลชุดที่มีขอบเขต
- งานที่ล้มเหลวมองเห็นได้ พร้อมการแจ้งเตือน
- เลือกช่วงเวลาตามตารางโดยคำนึงถึงค่าใช้จ่ายโฮสติ้ง
- เก็บเวลาเป็น UTC
งานเบื้องหลังใน Mythex
เอกสารของ Mythex ไม่ได้อธิบายงานตามกำหนดเวลาหรือ cron และแอปที่เผยแพร่รวมถึงฐานข้อมูลจะหลับเมื่อว่างและตื่นเมื่อมีคำขอถัดไป (ดูขีดจำกัดการโฮสต์) ดังนั้นอย่าพึ่งตัวจับเวลาในแอปของคุณ วิธีที่ได้ผลคือแนวทางด้านบน: ขอให้เอเจนต์สร้างตารางงานและเอนด์พอยต์ที่มีโทเค็นป้องกัน แล้วชี้ตัวจัดตารางภายนอกไปยัง URL ที่เผยแพร่แล้วของคุณ เก็บโทเค็นเป็นความลับของโปรเจกต์ และจำไว้ว่าการปลุกแต่ละครั้งใช้เครดิตตามเวลาที่แอปและฐานข้อมูลตื่นอยู่ ดังนั้นเลือกช่วงเวลาที่เหมาะสม หากแอปของคุณต้องการแบ็กเอนด์ API สำหรับเรื่องนี้ สูตร REST API backend เป็นจุดเริ่มต้นที่ดี และวิธีสร้าง REST API อธิบายการออกแบบเอนด์พอยต์ หากสิ่งที่เป็นหัวใจของผลิตภัณฑ์คือเวิร์กเกอร์หรือบอทที่ทำงานตลอดเวลา โฮสต์ที่สร้างสำหรับโปรเซสถาวรอาจเหมาะกับคุณกว่า
คำถาม
งานเบื้องหลังคืออะไร
งานเบื้องหลังคืองานที่แอปทำนอกคำขอที่ผู้ใช้กำลังรออยู่ เช่น ส่งอีเมล ย่อขนาดรูปภาพ สร้างรายงาน หรือซิงก์ข้อมูล ผู้ใช้ได้รับการตอบสนองที่รวดเร็ว ส่วนงานทำงานแยกต่างหากและลองใหม่ได้หากล้มเหลว
ถ้าโฮสต์ของฉันไม่มี cron ฉันจะรันงานตามกำหนดเวลาได้อย่างไร
เพิ่มเอนด์พอยต์ที่ปกป้องไว้ซึ่งทำงานนั้น แล้วให้ตัวจัดตารางภายนอกเรียกมันตามเวลาที่กำหนด ตัวเลือกได้แก่ เวิร์กโฟลว์ GitHub Actions ที่ตั้งเวลา บริการ cron แบบโฮสต์ หรือตัวจัดตารางของผู้ให้บริการคลาวด์ ปกป้องเอนด์พอยต์ด้วยโทเค็นลับ
ฉันใช้ setInterval หรือ setTimeout สำหรับงานตามกำหนดเวลาได้หรือไม่
ใช้ได้เฉพาะงานเล็ก ๆ ที่ไม่สำคัญบนเซิร์ฟเวอร์ที่ทำงานตลอดเวลา หากเซิร์ฟเวอร์รีสตาร์ท ปรับขนาดเป็นศูนย์ หรือรันหลายสำเนา ตัวจับเวลาจะหายหรือทำงานซ้ำ ให้เก็บงานตามกำหนดเวลาไว้ในฐานข้อมูลหรือใช้ตัวจัดตาราง
Mythex รองรับ cron jobs หรือไม่
เอกสารของ Mythex ไม่ได้อธิบายงานตามกำหนดเวลาหรือ cron และแอปที่เผยแพร่จะหลับเมื่อว่าง วิธีที่เชื่อถือได้คือให้ตัวจัดตารางภายนอกเรียกเอนด์พอยต์ที่ปกป้องไว้ในแอปของคุณ ซึ่งจะปลุกแอปและรันงาน