การจัดการธุรกิจที่ช้า

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

แผนการที่หนึ่ง ใช้ข้อความคิว

อ้างอิง redis คิว stomp คิว

ข้อดี

สามารถรับมือกับคำขอการจัดการธุรกิจจำนวนมากอย่างรวดเร็ว

ข้อเสีย

ไม่สามารถส่งผลลัพธ์กลับไปยังไคลเอนต์ได้โดยตรง หากต้องการส่งผลลัพธ์จะต้องใช้บริการอื่นร่วม เช่น การใช้ webman/push เพื่อส่งผลลัพธ์การจัดการ

แผนการที่สอง เพิ่มพอร์ต HTTP

เพิ่มพอร์ต HTTP สำหรับจัดการคำขอที่ช้า คำขอที่ช้าจะเข้ามายังกลุ่มกระบวนการเฉพาะผ่านการเข้าถึงพอร์ตนี้ หลังจากที่จัดการเสร็จแล้วจะส่งผลลัพธ์กลับไปยังไคลเอนต์โดยตรง

ข้อดี

สามารถส่งข้อมูลกลับไปยังไคลเอนต์ได้โดยตรง

ข้อเสีย

ไม่สามารถรับมือกับคำขอจำนวนมหาศาลที่เกิดขึ้นอย่างกระทันหัน

ขั้นตอนการดำเนินการ

เพิ่มการตั้งค่าดังต่อไปนี้ใน config/process.php

return [
    // ... การตั้งค่าอื่นถูกละเว้น ...

    'task' => [
        'handler' => \Webman\App::class,
        'listen' => 'http://0.0.0.0:8686',
        'count' => 8, // จำนวนกระบวนการ
        'user' => '',
        'group' => '',
        'reusePort' => true,
        'constructor' => [
            'requestClass' => \support\Request::class, // การตั้งค่า request class
            'logger' => \support\Log::channel('default'), // ตัวอย่างบันทึก
            'appPath' => app_path(), // ตำแหน่งของโฟลเดอร์ app
            'publicPath' => public_path() // ตำแหน่งของโฟลเดอร์ public
        ]
    ]
];

ด้วยวิธีนี้ อินเทอร์เฟซที่ช้าจะสามารถใช้กลุ่มกระบวนการที่ http://127.0.0.1:8686/ โดยไม่กระทบต่อการจัดการธุรกิจของกระบวนการอื่น

เพื่อให้ส่วนหน้ารู้สึกไม่แตกต่างในการเข้าถึงพอร์ต สามารถเพิ่มพร็อกซี่ไปยังพอร์ต 8686 ใน nginx สมมุติว่าคำขอสำหรับอินเทอร์เฟซที่ช้าทั้งหมดเริ่มต้นด้วย /tast การตั้งค่า nginx ทั้งหมดจะมีลักษณะดังนี้:

upstream webman {
    server 127.0.0.1:8787;
    keepalive 10240;
}

# เพิ่ม upstream สำหรับ 8686
upstream task {
   server 127.0.0.1:8686;
   keepalive 10240;
}

server {
  server_name webman.com;
  listen 80;
  access_log off;
  root /path/webman/public;

  # คำขอที่เริ่มต้นด้วย /tast จะไปที่พอร์ต 8686 โปรดเปลี่ยน /tast เป็นคำนำหน้าที่คุณต้องการตามสถานการณ์จริง
  location /tast {
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header Host $host;
      proxy_http_version 1.1;
      proxy_set_header Connection "";
      proxy_pass http://task;
  }

  # คำขออื่น ๆ จะไปที่พอร์ต 8787 เดิม
  location / {
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header Host $host;
      proxy_http_version 1.1;
      proxy_set_header Connection "";
      if (!-f $request_filename){
          proxy_pass http://webman;
      }
  }
}

เมื่อไคลเอนต์เข้าถึง โดเมน.com/tast/xxx จะส่งไปยังพอร์ต 8686 โดยเฉพาะ โดยไม่กระทบต่อการจัดการคำขอที่พอร์ต 8787

แผนการที่สาม ใช้ http chunked ส่งข้อมูลแบบอะซิงโครนัสทีละส่วน

ข้อดี

สามารถส่งข้อมูลกลับไปยังไคลเอนต์ได้โดยตรง

ติดตั้ง workerman/http-client

composer require workerman/http-client

app/controller/IndexController.php

<?php
namespace app\controller;

use support\Request;
use support\Response;
use Workerman\Protocols\Http\Chunk;

class IndexController
{
    public function index(Request $request)
    {
        $connection = $request->connection;
        $http = new \Workerman\Http\Client();
        $http->get('https://example.com/', function ($response) use ($connection) {
            $connection->send(new Chunk($response->getBody()));
            $connection->send(new Chunk('')); // ส่ง chunk ว่างเพื่อบ่งบอกว่าการตอบกลับสิ้นสุด
        });
        // ส่ง HTTP header ก่อน และส่งข้อมูลที่เหลือผ่านการส่งแบบอะซิงโครนัส
        return response()->withHeaders([
            "Transfer-Encoding" => "chunked",
        ]);
    }
}

提示
ในตัวอย่างนี้ใช้ workerman/http-client สำหรับการดึงผลลัพธ์ HTTP แบบอะซิงโครนัสและส่งข้อมูลคืน นอกจากนี้ยังสามารถใช้ไคลเอนต์อะซิงโครนัสอื่น ๆ เช่น AsyncTcpConnection ได้ด้วย