ข้ามไปยังเนื้อหาหลัก
คู่มือระบบ เนื้อหาผ่านการตรวจสอบแล้ว

การใช้ Queues: Background Processing

บทความนี้กล่าวถึงการใช้ Queues เพื่อประมวลผลงานที่ใช้เวลานานใน Background ของเว็บแอปพลิเคชัน เพื่อหลีกเลี่ยงการทำให้ User Experience แย่ลง โดยแนะนำให้ใช้ Messag...

การใช้ Queues: Background Processing

ในโลกของการพัฒนาเว็บแอปพลิเคชัน เรามักจะต้องจัดการกับงานที่ใช้เวลานาน (time-consuming tasks) เช่น การส่งอีเมลจำนวนมาก, การประมวลผลภาพ, หรือการสร้างรายงานที่ซับซ้อน หากเราประมวลผลงานเหล่านี้ใน request cycle ปกติ ผู้ใช้งานจะต้องรอจนกว่างานจะเสร็จสิ้น ซึ่งอาจทำให้ประสบการณ์การใช้งานไม่ดีนัก ทางออกที่ดีคือการใช้ Queues เพื่อประมวลผลงานเหล่านี้ใน Background

Queues คืออะไร

Queue คือโครงสร้างข้อมูลที่เก็บรายการงาน (jobs) ที่ต้องประมวลผล โดยมีหลักการทำงานแบบ FIFO (First-In, First-Out) นั่นคือ งานที่ถูกเพิ่มเข้าไปใน Queue ก่อน จะถูกประมวลผลก่อน

Background Processing คือการประมวลผลงานต่างๆ นอกเหนือจาก request cycle หลักของเว็บแอปพลิเคชัน ซึ่งช่วยให้เว็บแอปพลิเคชันสามารถตอบสนองต่อผู้ใช้งานได้อย่างรวดเร็ว โดยไม่ต้องรอให้งานที่ใช้เวลานานเสร็จสิ้น

Trade-offs: การใช้ Queues มีข้อดีคือปรับปรุง User Experience และเพิ่ม Scalability แต่ก็เพิ่มความซับซ้อนในการจัดการระบบ และต้องมีระบบ Monitor เพื่อตรวจสอบสถานะของ Queue และ jobs ต่างๆ

การใช้ Message Queue (e.g., Redis Queue)

Message Queue เป็นซอฟต์แวร์ที่ทำหน้าที่เป็นตัวกลางในการรับส่งข้อความ (messages) ระหว่างส่วนต่างๆ ของระบบ โดย Queue คือหนึ่งในรูปแบบการใช้งาน Message Queue ที่ได้รับความนิยม

มี Message Queue หลายตัวให้เลือกใช้ เช่น RabbitMQ, Beanstalkd, และ Redis Queue ในบทความนี้ เราจะเน้นไปที่ Redis Queue เนื่องจาก Redis เป็น in-memory data store ที่รวดเร็วและใช้งานง่าย

Redis Queue (RQ) เป็นไลบรารี Python ที่ช่วยให้เราสามารถใช้งาน Redis เป็น Message Queue ได้อย่างง่ายดาย สำหรับ PHP เราสามารถใช้ไลบรารีเช่น php-resque หรือ Queue เพื่อทำงานกับ Redis Queue

ตัวอย่างการใช้งาน php-resque:

  1. ติดตั้ง php-resque:
    ใช้ Composer เพื่อติดตั้งไลบรารี:
    composer require chrisboulton/php-resque
  2. กำหนดค่าการเชื่อมต่อ Redis:
    สร้างไฟล์ config.php เพื่อกำหนดค่าการเชื่อมต่อ Redis:
    <?php
    
      return [
          'host' => '127.0.0.1',
          'port' => 6379,
          'database' => 0,
      ];
  3. สร้าง Worker:
    สร้างไฟล์ worker.php เพื่อเริ่มต้น Worker ที่จะคอยรับงานจาก Queue:
    <?php
    
      require __DIR__ . '/vendor/autoload.php';
    
      $config = require __DIR__ . '/config.php';
    
      Resque::setBackend(
          $config['host'] . ':' . $config['port'],
          $config['database']
      );
    
      $interval = 5; // Check for new jobs every 5 seconds
      $queue = '*'; // Process all queues
    
      $worker = new Resque_Worker([$queue]);
      $worker->work($interval);
  4. สร้าง Job Class:
    สร้าง Class ที่จะทำหน้าที่ประมวลผลงาน (Job) เช่น SendEmailJob.php:
    <?php
    
      class SendEmailJob
      {
          public function perform()
          {
              // Simulate sending an email
              $email = $this->args['email'];
              $subject = $this->args['subject'];
              $message = $this->args['message'];
    
              // In a real application, you would use a mail library
              // to send the email.
              echo "Sending email to: {$email} with subject: {$subject}\n";
              sleep(2); // Simulate email sending delay
              echo "Email sent successfully!\n";
          }
      }
  5. Enqueue Job:
    Enqueue Job ไปยัง Queue เมื่อต้องการส่งอีเมล:
    <?php
    
      require __DIR__ . '/vendor/autoload.php';
    
      $config = require __DIR__ . '/config.php';
    
      Resque::setBackend(
          $config['host'] . ':' . $config['port'],
          $config['database']
      );
    
      $args = [
          'email' => 'test@example.com',
          'subject' => 'Welcome!',
          'message' => 'Welcome to our website!'
      ];
    
      $jobId = Resque::enqueue('default', 'SendEmailJob', $args);
    
      echo "Enqueued job with ID: {$jobId}\n";
  6. รัน Worker:
    เปิด terminal และรัน Worker:
    php worker.php
  7. Enqueue Job (ใน Web Application):
    เมื่อผู้ใช้ทำการลงทะเบียนในเว็บแอปพลิเคชันของคุณ คุณสามารถ Enqueue Job เพื่อส่งอีเมลต้อนรับได้:
    <?php
    
      // ... (Registration Logic) ...
    
      $args = [
          'email' => $user->email,
          'subject' => 'Welcome!',
          'message' => 'Welcome to our website!'
      ];
    
      Resque::enqueue('default', 'SendEmailJob', $args);
    
      // ... (Redirect the user) ...

การ Process Jobs ใน Background

เมื่อ Job ถูก Enqueue ไปยัง Queue แล้ว Worker จะทำการดึง Job มาประมวลผลใน Background กระบวนการนี้จะเกิดขึ้นโดยอัตโนมัติ โดยที่เราไม่ต้องเขียน Code เพิ่มเติม

การจัดการ Errors: สิ่งสำคัญคือการจัดการ Errors ที่อาจเกิดขึ้นในระหว่างการประมวลผล Job เราสามารถใช้ Try-Catch Blocks เพื่อดักจับ Exceptions และทำการ Logging เพื่อตรวจสอบปัญหาที่เกิดขึ้น

class SendEmailJob
{
    public function perform()
    {
        try {
            // ... (Email Sending Logic) ...
        } catch (Exception $e) {
            // Log the error
            error_log("Error sending email: " . $e->getMessage());

            // Optionally, retry the job
            // Resque::enqueue('default', 'SendEmailJob', $this->args);
        }
    }
}

การ Retry Jobs: ในกรณีที่ Job ล้มเหลว เราสามารถ Retry Job ได้ โดยการ Enqueue Job กลับไปยัง Queue อีกครั้ง อย่างไรก็ตาม เราควรจำกัดจำนวนครั้งในการ Retry เพื่อป้องกันไม่ให้เกิด Infinite Loop

การ Monitor Queues: เราควรมีระบบ Monitor เพื่อตรวจสอบสถานะของ Queue และ Jobs ต่างๆ เพื่อให้เราสามารถแก้ไขปัญหาได้อย่างรวดเร็ว

แนวปฏิบัติที่ดี:

  • Keep Jobs Small: พยายามทำให้ Jobs มีขนาดเล็กและใช้เวลาน้อย เพื่อลดโอกาสที่ Job จะล้มเหลว และเพิ่ม Throughput ของ Queue
  • Idempotent Jobs: ทำให้ Jobs เป็น Idempotent นั่นคือ การรัน Job ซ้ำๆ จะให้ผลลัพธ์เหมือนเดิมเสมอ ซึ่งจะช่วยป้องกันปัญหาที่อาจเกิดขึ้นจากการ Retry Jobs
  • Logging: ทำการ Logging ข้อมูลที่เกี่ยวข้องกับ Jobs เพื่อช่วยในการ Debugging และ Monitoring
  • Error Handling: จัดการ Errors ที่อาจเกิดขึ้นในระหว่างการประมวลผล Job อย่างเหมาะสม

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

Office.in.th Custom Service

ต้องการพัฒนาระบบหรือปรับแต่งจากโครงสร้างนี้?

Office.in.th รับพัฒนาและออกแบบ Enterprise Web Application, API Integration และระบบบริหารงานภาครัฐ/เอกชน พร้อมการสนับสนุนระยะยาว

ดูบริการรับพัฒนาซอฟต์แวร์