วิธีหยุดชั่วคราวและควบคุมคิวใน Laravel ทีละขั้นตอน

การปรับปรุงครั้งล่าสุด: 5 2025 ธันวาคม
  • Laravel นำเสนอ API คิวแบบรวมที่มีไดรเวอร์หลายตัว (ฐานข้อมูล, Redis, SQS…) และการแยกระหว่างการเชื่อมต่อและคิวเชิงตรรกะ
  • งานเหล่านี้ช่วยให้สามารถย้ายงานหนักๆ ไปที่พื้นหลังได้ โดยรองรับการทำโมเดลแบบอนุกรม มิดเดิลแวร์ งานครั้งเดียว การเข้ารหัส ชุดงาน และสตริง
  • คนงานได้รับการจัดการด้วยคิว:งาน หัวหน้างาน และคำสั่งเช่นคิว:หยุดชั่วคราว/คิว:ดำเนินการต่อ ซึ่งควบคุมการลองใหม่ การหมดเวลา และลำดับความสำคัญ
  • มีระบบนิเวศที่สมบูรณ์สำหรับความล้มเหลว การตรวจสอบ และการทดสอบ (failed_jobs, queue:retry, queue:monitor, Queue::fake) ที่ทำให้คิวเชื่อถือได้ในการผลิต

การจัดการคิวใน Laravel

การทำงานกับคิวใน Laravelแทบจะเป็นสิ่งที่จำเป็นในโปรเจ็กต์ที่จริงจังทุกโปรเจ็กต์ ไม่ว่าจะเป็นการส่งอีเมล การประมวลผลไฟล์ CSV การสร้างไฟล์ PDF การปรับขนาดรูปภาพ การเรียกใช้ API ภายนอก... หากทำทั้งหมดนี้ในคำขอ HTTP หลัก เว็บไซต์จะทำงานช้าลง เกิดข้อผิดพลาด 500 และผู้ใช้ก็จะพบแต่หน้าจอว่างเปล่าอย่างสิ้นหวัง

ข่าวดีก็คือ Laravel มีโครงสร้างพื้นฐานการจัดคิวที่มีประสิทธิภาพและยืดหยุ่นซึ่งช่วยให้คุณสามารถมอบหมายงานหนักให้กับกระบวนการทำงานเบื้องหลัง จัดการลำดับความสำคัญ จัดกลุ่มเป็นชุด ตรวจสอบสถานะการทำงาน ลองใหม่เมื่อล้มเหลว และแม้กระทั่งหยุดการทำงานของกระบวนการเหล่านั้นชั่วคราวเพื่อการบำรุงรักษา มาดูกันอย่างละเอียด (และไม่พลาดสิ่งใด) ว่าจะใช้ประโยชน์จากมันให้ได้มากที่สุดได้อย่างไร รวมถึงวิธีการหยุดชั่วคราว เริ่มใหม่ และควบคุมพฤติกรรมของมันในสภาพแวดล้อมการใช้งานจริง

แนวคิดพื้นฐาน: การเชื่อมต่อ คิว และไดรเวอร์

ใน Laravel ก่อนที่จะหยุดอะไรก็ตาม คุณต้องเข้าใจความแตกต่างระหว่าง การเชื่อมต่อคิวและคิวเอง. ใน config/queue.php คุณมีอาร์เรย์ connections ซึ่งคุณกำหนดแบ็กเอนด์แต่ละรายการ: ฐานข้อมูล, redis, beanstalkd, sqs, ซิงค์, null, failover, rabbitmq (หากคุณเพิ่มมันเข้าไป) ฯลฯ

การเชื่อมต่อแต่ละครั้งสามารถมีได้หลาย คิวเชิงตรรกะ (ชื่อเช่น default, emails, high, low, importsคุณสมบัติ queue การเชื่อมต่อแต่ละครั้งจะระบุว่าคิวเริ่มต้นใดที่งานจะไปหากไม่ได้ระบุอื่นไว้ onQueue()ด้วยวิธีนี้คุณสามารถทำสิ่งต่างๆ เช่น:

  • คิวด่วน สำหรับอีเมล์หรือธุรกรรมสั้นๆ
  • ความสำคัญต่ำอีกประการหนึ่ง สำหรับงานที่ยาวนานเช่นการประมวลผลวิดีโอหรือรายงานขนาดใหญ่
  • คิวแบ่งตามประเภทงาน: imports, notificaciones, reportesฯลฯ

เมื่อคุณเปิดตัวเวิร์กเกอร์ด้วย php artisan queue:workโดยค่าเริ่มต้นจะฟังคิวที่ระบุเป็น ค่าเริ่มต้น บนการเชื่อมต่อที่เลือก หากต้องการจัดลำดับความสำคัญ คุณสามารถส่งคิวที่คั่นด้วยเครื่องหมายจุลภาคหลายรายการได้:

php artisan queue:work redis --queue=high,default,low

ด้วยวิธีนี้ พนักงานจะประมวลผลงานที่มีความสำคัญสูง ก่อน จากนั้นจึงประมวลผลงานระดับเริ่มต้นและสุดท้ายจึงประมวล ผลงาน ระดับต่ำซึ่งเป็นสิ่งสำคัญอย่างยิ่งเมื่อระบบมีภาระงานมาก และคุณไม่ต้องการให้รายงานที่ใช้เวลา 30 นาทีไปบดบังอีเมลที่มีความสำคัญสูง

ไดรเวอร์คิวและข้อกำหนดเบื้องต้น

Laravel มี API ที่เป็นมาตรฐานสำหรับตัวจัดการคิว หลายตัว แต่ละตัวก็มีคุณสมบัติและส่วนประกอบเฉพาะของตัวเอง การเลือกตัวจัดการคิวที่เหมาะสมเป็นสิ่งสำคัญอย่างยิ่งก่อนที่จะพูดถึงการหยุดการทำงานของเวิร์กเกอร์

ฐานข้อมูลไดรเวอร์

คนขับ ฐานข้อมูล มันเก็บงานไว้ในตาราง SQL (โดยปกติ jobsตั้งค่าได้ง่ายและเหมาะอย่างยิ่งสำหรับโปรเจ็กต์ขนาดเล็กหรือสภาพแวดล้อมการพัฒนาที่คุณไม่ต้องการยุ่งยากกับ Redis หรือ SQS

ขั้นตอนพื้นฐาน:

  • สร้างการโยกย้าย: php artisan queue:table (หรือในเวอร์ชันใหม่กว่านั้นก็มาเป็น create_jobs_table ค่าเริ่มต้น).
  • ดำเนินการย้ายข้อมูล: php artisan migrate.
  • การกำหนดค่า QUEUE_CONNECTION=ฐานข้อมูล ใน .env และยืนยันใน config/queue.php นี้ 'default' => env('QUEUE_CONNECTION','database').

มันสะดวกและมีความเสถียรเพียงพอ แต่หากมีคิวจำนวนมากและปริมาณการใช้งานสูง มันอาจกลายเป็นคอขวดได้ เนื่องจากทุกอย่างต้องผ่านฐานข้อมูลเชิงสัมพันธ์เดียวกัน

ไดร์เวอร์ เรดิส

ไดรเวอร์Redisเป็นเครื่องมือมาตรฐานที่ใช้กันอย่างแพร่หลายในระบบการผลิต มันทำงานเร็ว รองรับคุณสมบัติขั้นสูง (การล็อก การจำกัดอัตรา การล็อกแบบอะตอมิก Horizon ฯลฯ) และปรับขนาดได้ดีมาก

จุดสำคัญ:

  • คุณต้องกำหนดค่าการเชื่อมต่อ Redis ใน config/database.php.
  • ตัวเลือก serializer y compression จาก Redis พวกเขาเข้ากันไม่ได้ พร้อมพนักงานขับรถคิว
  • ถ้าคุณใช้ คลัสเตอร์ Redisชื่อคิวต้องมีแฮชแท็ก เช่น {default}เพื่อให้คีย์ทั้งหมดในคิวนั้นตกอยู่ในช่องเดียวกัน
  • ตัวเลือก block_for มันช่วยให้คนงานสามารถบล็อคได้ในขณะที่รองานเป็นเวลาสองสามวินาที แทนที่จะทำการโพลอย่างต่อเนื่อง: ประหยัดซีพียู และลดการสอบถามไปยังเซิร์ฟเวอร์ Redis

ตัวอย่างเช่น:

'redis' => ,

หากคุณใส่ block_for = 0คนงานจะถูกบล็อกอย่างไม่มีกำหนดจนกว่าจะมีงานว่าง ซึ่งเป็นสิ่งที่ต้องคำนึงถึงหากคุณต้องการให้คนงานตอบสนองต่อสัญญาณต่างๆ อย่างรวดเร็ว เช่น SIGTERM หรือคำสั่งหยุดชั่วคราว

ไดรเวอร์อื่นๆ: SQS, Beanstalkd, null, failover…

นอกเหนือจากฐานข้อมูลและ Redis แล้ว Laravel ยังรองรับระบบอื่นๆ อีกด้วย:

  • อเมซอน SQSจัดการคิวบน AWS พร้อมรองรับ FIFOกลุ่มข้อความ การลบข้อมูลซ้ำซ้อน และการตั้งค่าการมองเห็นขั้นสูง ต้องใช้ SDK aws/aws-sdk-php.
  • ถั่วฝักยาวรวดเร็วและง่ายมากโดยใช้แพ็คเกจ pda/pheanstalk.
  • ซิงค์: ดำเนินการตามภารกิจ ทันที ในกระบวนการเดียวกัน มีประโยชน์ในการพัฒนาหรือทดสอบ แต่ในการผลิตก็แทบจะเหมือนกับไม่ต้องใช้คิวเลย
  • โมฆะ: ยกเลิกงานทันทีที่ "ส่งออก" ใช้เพื่อปิดใช้งานระบบคิวโดยสมบูรณ์
  • ล้มเหลววิธีนี้ช่วยให้คุณกำหนดค่าการเชื่อมต่อได้หลายรายการ และหากการเชื่อมต่อหลักล้มเหลว Laravel จะพยายามส่งงานไปยังการเชื่อมต่อถัดไปในรายการ เหมาะสำหรับสภาพแวดล้อมที่ ความพร้อมใช้งานสูง เป็นสิ่งสำคัญ
  Electron JS: ทุกสิ่งที่คุณจำเป็นต้องรู้

ในส่วนของการหยุดและเริ่มการทำงานของเวิร์กเกอร์นั้น ตรรกะแทบจะเหมือนกันไม่ว่าจะเป็นไดรเวอร์ใดก็ตาม เพราะมันถูกจัดการจากคำสั่ง Artisan และ คลาส Workerไม่ใช่จากแบ็กเอนด์ของคิว

การสร้างงานและการสร้างโมเดลแบบอนุกรม

Un การสัมภาษณ์ ใน Laravel มันเป็นเพียงคลาสที่ห่อหุ้มงานที่ต้องดำเนินการในคิว โดยทั่วไปจะสร้างขึ้นด้วย Artisan และบันทึกไว้ใน app/Jobs.

เพื่อสร้างอันหนึ่ง:

php artisan make:job ProcessPodcast

คลาสที่สร้างขึ้น ดำเนินการ ShouldQueue และโดยปกติจะใช้ลักษณะ Dispatchable, InteractsWithQueue, Queueable y SerializesModelsหัวใจอยู่ที่วิธีการ handle()ซึ่งเป็นสิ่งที่คนงานทำเมื่องานมาถึง

คุณสมบัติที่ทรงพลังอย่างยิ่งอย่างหนึ่งคือการแปลงโมเดล Eloquent เป็นรูปแบบที่สามารถจัดเก็บและอ้างอิงได้โดยอัตโนมัติหากคุณยอมรับโมเดลในตัวสร้าง Job นั้น Laravel จะไม่เพิ่มอ็อบเจ็กต์ทั้งหมดลงในคิว แต่จะเพิ่มเฉพาะตัวระบุเท่านั้น เมื่อ Job ถูกประมวลผล ระบบจะสร้างโมเดลขึ้นใหม่จากฐานข้อมูลพร้อมกับโหลดความสัมพันธ์ต่างๆ

ตัวอย่างทั่วไป (ในรูปแบบซูโดโค้ด เพื่อหลีกเลี่ยงการทำซ้ำคำต่อคำ):

  • ผู้สร้างได้รับ พอดแคสต์ พอดแคสต์.
  • ลักษณะนิสัย SerializesModels มีหน้าที่รับผิดชอบในการบันทึก ID
  • En handle(AudioProcessor $processor) คุณทำหน้าที่หนักๆ (เช่น การประมวลผลเสียง)

หากคุณไม่ต้องการให้ความสัมพันธ์ในโมเดลเป็นแบบอนุกรม (เพื่อให้เพย์โหลดไม่ใหญ่มาก) คุณสามารถใช้ $model->withoutRelations() หรือใน PHP 8 แอตทริบิวต์ # บนทรัพย์สินที่ได้รับการส่งเสริมของผู้สร้าง

การฉีดการอ้างอิงในวิธีการจัดการ

ข้อดีอีกอย่างก็คือคุณสามารถ ฉีดบริการลงในวิธีการจัดการโดยตรง (ราวกับว่าเป็นตัวควบคุม) เนื่องจาก Laravel ยังใช้คอนเทนเนอร์บริการในงานด้วย ตัวอย่างเช่น คุณสามารถร้องขอ AudioProcessorไคลเอนต์ HTTP, ที่เก็บข้อมูล ฯลฯ และกรอบงานจะดูแลการแก้ไขปัญหาเหล่านี้

หากคุณต้องการการควบคุมที่ละเอียดเป็นพิเศษของสิ่งที่เรียกว่า handleคุณสามารถใช้ Container::bindMethod() ในผู้ให้บริการและกำหนดตรรกะการฉีดด้วยตัวเอง แต่ในกรณีส่วนใหญ่ไม่จำเป็นต้องทำให้สิ่งต่างๆ ซับซ้อนมากนัก

งานมิดเดิลแวร์

เช่นเดียวกับเส้นทางที่มีมิดเดิลแวร์ จ็อบส์ก็สามารถมีได้เช่นกัน มิดเดิลแวร์เฉพาะ ที่รันก่อนและหลังงาน ซึ่งจะช่วยลดความซ้ำซ้อนของโค้ดในเมธอดได้อย่างมาก handle() และมีประโยชน์อย่างยิ่งสำหรับ:

  • การจำกัดอัตรา กับ Redis
  • หลีกเลี่ยง คาบเกี่ยวกัน ของงานที่สัมผัสกับทรัพยากรเดียวกัน
  • ข้อยกเว้นปกติ สำหรับ API ที่ไม่เสถียร
  • การข้ามงานภายใต้เงื่อนไขบางประการ (Skip มิดเดิลแวร์)

มิดเดิลแวร์มักจะถูกวางไว้ใน app/Jobs/Middleware และถูกส่งกลับจากวิธีการ middleware() จากงาน ตัวอย่างแนวคิด:

public function middleware(): array { return ;

ประเภทงานพิเศษ: ไม่ซ้ำกัน เข้ารหัส และล็อค

Laravel ช่วยให้คุณสามารถทำเครื่องหมายงานบางอย่างได้ ไม่เหมือนใคร เพื่อให้แน่ใจว่าไม่มีอินสแตนซ์ที่เหมือนกันสองอินสแตนซ์ถูกจัดคิวพร้อมกัน วิธีนี้ทำได้โดยการใช้อินเทอร์เฟซ ShouldBeUnique o ShouldBeUniqueUntilProcessingและรองรับการกำหนดคีย์ uniqueId() และเวลา uniqueFor.

เหมาะอย่างยิ่งสำหรับสิ่งต่างๆ เช่น:

  • คำนวณดัชนีการค้นหาผลิตภัณฑ์ใหม่: เพียงครั้งเดียวต่อผลิตภัณฑ์ จนกว่าจะเสร็จสิ้น
  • การซิงโครไนซ์กับบริการภายนอกที่ไม่อนุญาตให้มีการร้องขอพร้อมกันสำหรับทรัพยากรเดียวกัน

ด้านล่าง Laravel ใช้ ล็อคอะตอม ของแคช (Redis, memcached, ฐานข้อมูล ฯลฯ) คุณยังสามารถเลือกไดรเวอร์แคชสำหรับล็อคนั้นได้ด้วย uniqueVia().

นอกจากนี้ยังมีอินเทอร์เฟซ ShouldBeEncryptedโดยที่คุณระบุว่างานเสร็จสมบูรณ์แล้ว กรอกรหัสของคุณก่อนเข้าคิวมีประโยชน์มากเมื่อส่งข้อมูลที่ละเอียดอ่อนและคุณไม่ต้องการให้ข้อมูลเดินทางในรูปแบบข้อความธรรมดาผ่าน Redis, SQS หรือฐานข้อมูล

การจัดส่ง การล่าช้า และการดำเนินการงานในโหมดที่แตกต่างกัน

เมื่อคุณกำหนดงานของคุณแล้ว ให้เริ่มต้นงานด้วย Job::dispatch() จากตัวควบคุม ตัวรับฟังเหตุการณ์ คำสั่ง Artisan หรือแม้แต่การปิด พารามิเตอร์ที่คุณส่งไป dispatch พวกเขาตรงไปหาผู้สร้างโยบ

รูปแบบที่น่าสนใจ:

  • dispatchIf() y dispatchUnless() เพื่อปรับสภาพการจัดส่งให้เป็นบรรทัดเดียว
  • delay() เพื่อป้องกันไม่ให้งานดำเนินการได้จนกว่าจะถึงวันที่/เวลาที่กำหนด
  • dispatchAfterResponse() o afterResponse() en dispatch() การปิดซึ่งจะเลื่อนการดำเนินการจนกว่าจะส่งการตอบสนอง HTTP แต่ภายในกระบวนการ PHP เดียวกัน
  • dispatchSync() ในการรันงานแบบซิงโครนัส (โดยไม่ผ่านคิว) แต่ใช้คลาสเดียวกันซ้ำ
  • การเชื่อมต่อพิเศษเช่น deferred o background เพื่อดำเนินการหลังจากการตอบสนองในกระบวนการเดียวกันหรือในกระบวนการ PHP ใหม่

สุดท้ายคุณสามารถระบุการเชื่อมต่อและคิวด้วยวิธีการแบบเชื่อมโยงได้ onConnection() y onQueue()ไม่ว่าจะเป็นเมื่อจัดส่งหรือภายในตัวสร้างงาน

การควบคุมละเอียด: การลองใหม่ การถอยกลับ การหมดเวลา และการจัดการข้อผิดพลาด

ส่วนสำคัญของการทำงานกับคิวใน Laravel คือการตัดสินใจว่าจะลองดำเนินการงานซ้ำกี่ครั้งจะรอเวลานานเท่าใดระหว่างการลองแต่ละครั้ง และเมื่อใดจึงจะถือว่างานนั้นล้มเหลว

  นักพัฒนา Front-end คืออะไร และพวกเขาทำอะไร?

ตัวเลือกที่มีจำหน่าย:

  • --tries en queue:work เพื่อกำหนดจำนวนสูงสุดของความพยายามสำหรับงานทั้งหมดของพนักงานนั้น (ยกเว้นว่างานจะกำหนดของตัวเอง) $tries o tries()).
  • $tries หรือวิธีการ tries() ในคลาสงานสำหรับการควบคุมแต่ละงาน
  • retryUntil() ที่จะพูดว่า: “ลองใหม่อีกครั้งเท่าที่คุณอยากลอง จนกระทั่งถึงเวลานั้น หลังจากนั้นก็ล้มเหลว” ถ้ามันตรงกับ tries, สั่งการ retryUntil.
  • $maxExceptions เพื่อตัดออกเมื่อปัญหาเกิดจากข้อยกเว้นที่ไม่ได้รับการจัดการซ้ำๆ
  • $timeout o --timeout เพื่อระบุว่างานสามารถทำงานได้กี่วินาทีก่อนที่เวิร์กเกอร์จะหยุดกระบวนการย่อย
  • $failOnTimeout เพื่อทำเครื่องหมายงานว่าล้มเหลวในกรณีที่หมดเวลา
  • $backoff วิธีการ backoff() เพื่อกำหนดระยะเวลาในการรอระหว่างการลองใหม่อีกครั้ง แม้ว่าจะมีค่าเลขชี้กำลังก็ตาม

หากงานโยนข้อยกเว้นที่ไม่ถูกจับได้ Laravel จะ... ปล่อยกลับเข้าหางอีกครั้ง จนกว่าจะหมดความพยายามที่ตั้งค่าไว้ คุณสามารถควบคุมสิ่งนี้ด้วยตนเองได้ด้วย release($segundos) o fail($exception) เมื่อคุณต้องการทำเครื่องหมายงานว่าล้มเหลวโดยเจตนา

งานที่ล้มเหลว ตารางงานที่ล้มเหลว และการตัดแต่ง

เมื่องานหมดความพยายามของเขาแล้ว เขาจะได้รับการพิจารณา งานล้มเหลว และ Laravel จะแทรกมันเข้าไปในตาราง failed_jobs (หรือใน DynamoDB หากคุณกำหนดค่าไว้แบบนั้น) ตารางดังกล่าวจะจัดเก็บ UUID การเชื่อมต่อ คิว เพย์โหลดงาน และข้อยกเว้นที่เกิดขึ้น

คำสั่งที่เป็นประโยชน์:

  • php artisan queue:failed เพื่อแสดงรายการที่ล้มเหลว
  • php artisan queue:retry <id|all> เพื่อลองมันอีกครั้ง
  • php artisan queue:forget <id> ที่จะลบอันหนึ่ง
  • php artisan queue:flush เพื่อลบทั้งหมด (พร้อมตัวเลือกเป็นชั่วโมงในเวอร์ชันใหม่กว่า)
  • php artisan queue:prune-failed --hours=48 เพื่อทำการตัดแต่งบันทึกเก่าโดยอัตโนมัติ

ในงานคุณสามารถกำหนดวิธีการได้ failed(Throwable $exception) สำหรับการล้างข้อมูลเพิ่มเติม: แจ้งให้ผู้ใช้ทราบ ย้อนกลับการดำเนินการบางส่วน เขียนบันทึกเฉพาะ ฯลฯ โปรดทราบว่ามีการสร้างอินสแตนซ์ใหม่ของงานเพื่อเรียก failed()ดังนั้นอย่าพึ่งพึ่งการเปลี่ยนแปลงทรัพย์สินที่เกิดขึ้น handle().

การแบ่งงานเป็นชุด: การแบ่งงานเป็นชุดและรวมเข้าด้วยกันด้วยสตริง

เมื่อคุณต้องการเริ่มงานที่เกี่ยวข้องกันหลายร้อยหรือหลายพันรายการ (ตัวอย่างเช่น การนำเข้าไฟล์ CSV ขนาดใหญ่เป็นส่วนๆ การประมวลผลไฟล์เป็นชุด การทำความสะอาดข้อมูล ฯลฯ) ขอแนะนำให้ใช้ ฟังก์ชันการประมวลผลแบบกลุ่มของ Laravel

การไหลพื้นฐาน:

  • สร้างตาราง job_batches กับ php artisan queue:batches-table && php artisan migrate.
  • ทำเครื่องหมายงานที่จะเป็นส่วนหนึ่งของชุดด้วยคุณลักษณะ Batchable.
  • ใช้ Bus::batch() เพื่อส่งชุดงานพร้อมการโทรกลับ then, catch y finally.
  • เข้าถึงชุดงานจากแต่ละงานด้วย $this->batch() และตรวจสอบว่ามันถูกยกเลิกหรือไม่
  • ความเป็นไปได้ในการเพิ่มงานเพิ่มเติมให้กับชุดงานที่กำลังดำเนินอยู่ด้วย $this->batch()->add().

การประมวลผลแบบกลุ่ม (Batch) ผสานรวมกับการประมวลผลแบบต่อเนื่อง (Chain) ได้อย่างลงตัว:คุณสามารถสร้างการประมวลผลแบบต่อเนื่องภายในกลุ่ม หรือใช้กลุ่มเป็นส่วนประกอบของการประมวลผลแบบต่อเนื่องที่ใหญ่กว่าได้ ซึ่งมีประโยชน์อย่างยิ่งเมื่อคุณต้องการให้การประมวลผลแบบต่อเนื่องหลายๆ อย่างทำงาน "พร้อมกัน" และเรียกใช้งานบางอย่างเมื่อการประมวลผลทั้งหมดเสร็จสมบูรณ์

การดำเนินการของพนักงาน ลำดับความสำคัญ และการปรับใช้

ความมหัศจรรย์ของคิวเกิดขึ้นเพราะคุณมี คนงานหนึ่งคนหรือมากกว่า เรียกใช้คำสั่ง queue:work (o queue:listen(แม้ว่าอย่างหลังจะมีประสิทธิภาพน้อยกว่าก็ตาม) กระบวนการเหล่านี้เป็นเดมอนที่ทำงานยาวนานซึ่งคอยฟังคิวที่เกี่ยวข้อง

ตัวเลือกหลักของ queue:work:

  • Conexion: php artisan queue:work redis, queue:work databaseฯลฯ
  • โคลาส: --queue=high,default,low การจัดลำดับความสำคัญ
  • -สิบเอ็ด: ประมวลผลงานเดียวและออก
  • –งานสูงสุด: ประมวลผลงาน X และยุติ (เพื่อรีสตาร์ทเวิร์กเกอร์เป็นระยะและเพิ่มหน่วยความจำ)
  • –เวลาสูงสุด:ประมวลผลเป็นเวลา N วินาทีแล้วออก
  • -นอน: วินาทีแห่งการรอคอยเมื่อไม่มีงานว่าง
  • หยุดเมื่อว่าง: ล้างคิวและปิดอย่างเรียบร้อย (เหมาะอย่างยิ่งในสภาพแวดล้อม Docker หรืองานครั้งเดียว)
  • –หมดเวลา: วินาทีของการหมดเวลาต่องาน ดังที่เราได้กล่าวไว้ก่อนหน้านี้
  • -บังคับ: เพื่อประมวลผลงานแม้ว่าแอปจะอยู่ในโหมดการบำรุงรักษาก็ตาม

เนื่องจากกระบวนการเหล่านี้ใช้เวลานาน ในสภาพแวดล้อมการใช้งานจริง จึงมักใช้ โปรแกรมตรวจสอบกระบวนการเช่น Supervisor (บน Linux) เพื่อเริ่มการทำงานของ X worker เริ่มใหม่หากเกิดข้อผิดพลาด และจัดการบันทึกต่างๆ บล็อกการกำหนดค่า Supervisor ทั่วไปสำหรับ Laravel จะกำหนดดังนี้:

  • คำสั่ง ที่มีการ php artisan queue:work ... คอนกรีต.
  • ตัวเลข เพื่อระบุจำนวนคนงานที่จะเปิดตัวพร้อมกัน
  • เส้นทางบันทึก ผู้ใช้ การรีสตาร์ทอัตโนมัติ ฯลฯ

การหยุดชั่วคราวและการเริ่มคิวใหม่ใน Laravel

มาดูกันว่าอะไรคือสิ่งที่สำคัญในการบำรุงรักษา: วิธีการหยุดการทำงานของคิวชั่วคราวโดยไม่หยุดการทำงานอย่างกะทันหันและไม่ทิ้งงานไว้ให้ไม่เสร็จ Laravel มีกลไกหลายอย่าง ทั้งแบบใหม่และแบบดั้งเดิม เพื่อควบคุมเรื่องนี้

หยุดชั่วคราว: คิว: หยุดชั่วคราวและขัดจังหวะสัญญาณ

ในเวอร์ชันล่าสุด Laravel ได้เพิ่มคำสั่งเฉพาะเพื่อหยุดและเริ่มการทำงานของเวิร์กเกอร์อีกครั้ง:

  • php artisan queue:pause: บอกให้ระบบหยุดรับงานใหม่ แต่ปล่อยให้งานที่กำลังดำเนินการอยู่ทำต่อจนเสร็จ
  • php artisan queue:continue:กลับมาดำเนินการงานใหม่ต่อจากจุดที่ค้างไว้
  การคำนวณค่า Variance Inflation Factor (VIF) ในภาษา C# และการออกแบบซอฟต์แวร์

คำสั่งเหล่านี้ทำงานโดยการส่งสัญญาณไปยังเวิร์กเกอร์ผ่านกลไกการแคชที่ Laravel ใช้ภายใน นั่นเป็นเหตุผลว่าทำไมการตั้งค่าไดรเวอร์แคช (memcached, redis, ฐานข้อมูล, ไฟล์ ฯลฯ) ให้ถูกต้องจึงมีความสำคัญ แม้ว่าคิวแคชจริงของคุณจะเป็นอย่างอื่นก็ตาม

ข้อสำคัญ: การหยุดคิวหรือตัวประมวลผลชั่วคราวไม่ได้เป็นการยกเลิกหรือลบงานที่อยู่ในคิวอยู่แล้วแต่เป็นการป้องกันไม่ให้มีการลบงานเพิ่มเติมออกจากคิวในระหว่างที่การหยุดชั่วคราวนั้นมีผลอยู่

การสำรวจการหยุดชะงักและผลกระทบต่อประสิทธิภาพการทำงาน

ทุกครั้งที่ worker ทำงานเสร็จสิ้น Laravel จะตรวจสอบแคชเพื่อหา สัญญาณ รีสตาร์ท หยุดชั่วคราว หรือดำเนินการต่อ การตรวจ สอบ นี้มีค่าใช้จ่ายน้อยมาก แต่ก็มีอยู่ หากคุณให้ความสำคัญกับประสิทธิภาพเป็นอย่างมากและรู้ว่าคุณไม่จำเป็นต้องหยุดชั่วคราวหรือรีสตาร์ท worker จากคำสั่ง คุณสามารถปิดการตรวจสอบนี้ได้โดยการเรียกใช้:

Queue::withoutInterruptionPolling();

หรือแม้กระทั่งปรับคุณสมบัติคงที่ของ Illuminate\Queue\Worker เพื่อปิดการใช้งานการสัมผัสเฉพาะ (รีสตาร์ทได้, หยุดชั่วคราวได้อย่างไรก็ตามหากคุณทำสิ่งนี้แล้วลองใช้ queue:pause o queue:restartคนงาน พวกเขาจะไม่พบเป็นการตัดสินใจด้านการออกแบบที่ควรพิจารณาอย่างรอบคอบ

หยุดชั่วคราวด้วยตนเองด้วย Supervisor หรือ Docker

นอกเหนือจากคำสั่งของ Laravel เองแล้วในสภาพแวดล้อมการใช้งานจริง กระบวนการต่างๆ มักจะถูก "หยุดชั่วคราว" โดยอ้อม:

  • การหยุดโปรแกรมใน Supervisor (supervisorctl stop laravel-worker:*) ซึ่งจะฆ่าหรือหยุดคนงาน
  • การใช้ หยุดเมื่อว่าง ในการปรับใช้เพื่อให้คนงานทำสิ่งที่อยู่ในคิวให้เสร็จก่อนแล้วจึงปิดระบบ
  • ใน Docker ให้คอนเทนเนอร์ประมวลผลด้วย --stop-when-empty แล้วมันก็ดับไป

ความแตกต่างกับ queue:pause เมื่อหยุดกระบวนการทั้งหมดแล้ว คุณจะหยุดการประมวลผลงานจนกว่าคนงานจะเริ่มต้นใหม่ การหยุดชั่วคราวภายใน คุณสามารถเก็บกระบวนการไว้ในหน่วยความจำโดยรอคำสั่ง continueซึ่งมีประโยชน์สำหรับการปรับใช้ย้อนกลับอย่างรวดเร็วหรือช่วงการบำรุงรักษาที่สั้น

ธุรกรรมฐานข้อมูลและ after_commit

ข้อผิดพลาดคลาสสิก: การส่งงาน ภายใน ธุรกรรมฐานข้อมูล หากคุณไม่ระมัดระวัง ตัวประมวลผลอาจดำเนินการงานนั้นก่อนที่จะมีการยืนยันการเปลี่ยนแปลง และโมเดลหรือข้อมูลที่คุณคาดหวังอาจยังไม่ปรากฏในฐานข้อมูล

เพื่อหลีกเลี่ยงการเต้นรำนี้ คุณมีสองทางเลือก:

  • กระตุ้น 'after_commit' => true ในการกำหนดค่าการเชื่อมต่อคิว ดังนั้น งานใดๆ ที่จัดส่งภายในธุรกรรมจะถูกเลื่อนออกไปภายในจนกว่าจะได้รับการยืนยัน
  • ใช้วิธีการแบบต่องาน afterCommit() o beforeCommit() เมื่อทำการจัดส่ง ให้บังคับให้มีการทำงานเฉพาะในงานที่กำหนดเท่านั้น

หากธุรกรรมถูกยกเลิก งานที่ถูกส่งไปในระหว่างธุรกรรมนั้นจะถูกทิ้งโดยไม่เข้าสู่คิว ซึ่งเป็นสิ่งที่โดยทั่วไปแล้วต้องการเพื่อรักษาความสม่ำเสมอ

การติดตาม การทำความสะอาดคิว และการทดสอบ

เมื่อคุณตั้งค่าและใช้งานระบบคิวได้อย่างจริงจังแล้ว การแค่ส่งงานออกไปแล้วปล่อยทิ้งไว้โดยไม่สนใจนั้นไม่เพียงพอ คุณควรตรวจสอบและทดสอบการทำงานของทุกอย่างอย่างสม่ำเสมอ

เครื่องมือและคำสั่งที่เป็นประโยชน์:

  • queue:clear เพื่อล้างคิวที่ระบุ (SQS, Redis, ฐานข้อมูล)
  • queue:monitor เพื่อตรวจสอบจำนวนงานในคิวบางรายการและทริกเกอร์เหตุการณ์ QueueBusy หากเกินเกณฑ์ที่กำหนด
  • กิจกรรมงาน ในขณะที่ Queue::before, Queue::after, Queue::looping y Queue::failing เพื่อเชื่อมโยงตรรกะที่กำหนดเอง (บันทึก เมตริก การย้อนกลับ ฯลฯ)
  • ของปลอมในการทดสอบ การใช้ Queue::fake() y Bus::fake() เพื่อตรวจยืนยันว่างาน สตริง หรือชุดงานได้รับการส่งไปแล้วโดยไม่ได้ดำเนินการจริง

ในการทดสอบ คุณสามารถระบุสิ่งต่างๆ เช่น"งานนี้ถูกจัดคิวไว้ X ครั้ง" "ชุดงานเหล่านี้ถูกส่งไปตามลำดับนี้" หรือ "ไม่มีงานใดถูกจัดคิวไว้โดยเฉพาะ" ซึ่งช่วยเพิ่มความปลอดภัยในกระบวนการทำงานที่ซับซ้อนได้มาก

ด้วยระบบนิเวศน์ทั้งหมดนี้—ไดรเวอร์เช่น Redis หรือ SQS งานที่ได้รับการออกแบบอย่างดี มิดเดิลแวร์สำหรับการปรับแต่ง ชุดข้อมูล โซ่ การกำหนดค่าการลองใหม่ พนักงานที่จัดการโดยหัวหน้างาน และคำสั่งเช่น queue:pause y queue:continueLaravel ช่วยให้คุณสามารถควบคุมการประมวลผลพื้นหลังได้ในระดับมิลลิเมตร ตั้งแต่การส่งอีเมลทั่วไปไปจนถึงสถาปัตยกรรมคิวแบบกระจายพร้อมระบบเฟลโอเวอร์ ช่วยให้มั่นใจได้ว่าแอปพลิเคชันของคุณยังคงตอบสนองได้อย่างรวดเร็วที่เลเยอร์ HTTP ในขณะที่งานหนักกำลังดำเนินการอยู่ด้านล่าง โดยไม่บล็อกผู้ใช้

เฟรมเวิร์ก Laravel
บทความที่เกี่ยวข้อง:
กรอบงาน Laravel อันทรงพลัง