เซิร์ฟเวอร์ประสิทธิภาพสูงด้วย Swoole
ให้บริการการเชื่อมต่อหลายพันรายการด้วย Swoole ที่ทำงานบนคอร์รูทีน
เซิร์ฟเวอร์ประสิทธิภาพสูงด้วย Swoole เป็นบทเรียน PHP Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน PHP Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส PHP Academy มีบทเรียนทั้งหมด 4 บทเรียน
Swoole คืออะไร
Swoole (และส่วนแยกสาขาอย่าง OpenSwoole) คือส่วนขยายภาษา C ที่เปลี่ยน PHP ให้เป็นรันไทม์ประสิทธิภาพสูง ซึ่งขับเคลื่อนด้วยโครูทีนและเหตุการณ์ แทนที่ PHP-FPM จะสร้างกระบวนการใหม่สำหรับแต่ละคำขอ เซิร์ฟเวอร์ Swoole จะ เริ่มต้นแอปของคุณเพียงครั้งเดียว และคงแอปไว้ในหน่วยความจำ เพื่อให้กลุ่มเวิร์กเกอร์ที่ทำงานต่อเนื่องรับคำขอ โดยมีโครูทีนในตัว ผลลัพธ์คือปริมาณงานเพิ่มขึ้นหลายเท่าตัว และรองรับการทำงานพร้อมกันภายในคำขอเดียวโดยตรง
เซิร์ฟเวอร์ HTTP ที่ทำงานต่อเนื่อง
ตัวอย่างคลาสสิกคือเซิร์ฟเวอร์ HTTP แบบเต็มรูปแบบในสคริปต์หนึ่งไฟล์ เซิร์ฟเวอร์จะรับฟังคำขอ ส่งคำขอแต่ละรายการไปยังเวิร์กเกอร์ และไม่เริ่มต้นเฟรมเวิร์กใหม่อีก โปรดทราบว่าต้องใช้ ext-swoole — ไม่สามารถทำงานบน PHP CLI มาตรฐานได้
<?php
$server = new Swoole\Http\Server('0.0.0.0', 9501);
$server->set(['worker_num' => 4]);
$server->on('request', function ($request, $response) {
$response->header('Content-Type', 'application/json');
$response->end(json_encode(['hello' => $request->server['request_uri']]));
});
echo "listening on :9501\n";
$server->start();โครูทีน ไม่ใช่คอลแบ็ก
คุณสมบัติเด่นของ Swoole คือ โครูทีน: คุณสามารถเขียนโค้ดแบบลำดับที่ดูเหมือนบล็อกได้ โดยรันไทม์จะจัดตารางการทำงานแบบร่วมมือกัน Coroutine\run() จะเปิดบริบทโครูทีน ส่วน go() จะเปิดใช้โครูทีนใหม่ โครูทีนแต่ละตัวมีสแตกของตนเองเช่นเดียวกับไฟเบอร์ แต่ Swoole จะจัดตารางให้โดยอัตโนมัติ ณ จุดรับส่งข้อมูล
<?php
use Swoole\Coroutine as Co;
Co\run(function () {
go(function () { Co::sleep(1); echo "A done\n"; });
go(function () { Co::sleep(1); echo "B done\n"; });
// Both sleep concurrently -> total ~1s, not 2s
});ฟังก์ชันแบบบล็อกที่ถูกดักจับ
กลไกที่ทำให้โครูทีนใช้งานได้สะดวกคือ ฮุกของรันไทม์ Swoole จะเขียนการเรียกแบบบล็อกใหม่อย่างโปร่งใส — PDO, Redis, curl, sleep, file_get_contents — ให้เป็นเวอร์ชันที่ไม่บล็อกและรองรับโครูทีน การเรียกใช้ $pdo->query() ตามปกติจะคืนการควบคุมให้โครูทีน แทนที่จะทำให้เวิร์กเกอร์หยุดนิ่ง
<?php
use Swoole\Runtime;
use Swoole\Coroutine as Co;
Runtime::enableCoroutine(SWOOLE_HOOK_ALL); // hook PDO, curl, sleep, etc.
Co\run(function () {
go(function () { sleep(1); echo "task 1\n"; }); // sleep() is now async!
go(function () { sleep(1); echo "task 2\n"; });
}); // finishes in ~1s because sleep was hookedการรับส่งข้อมูลพร้อมกันด้วย WaitGroup
สำหรับการกระจายงานออกไปและรอรวมผล Swoole มี WaitGroup (คล้ายกับ sync.WaitGroup ของ Go) ให้เปิดใช้โครูทีน เรียก add() สำหรับแต่ละงาน เรียก done() เมื่องานเสร็จ และเรียก wait() เพื่อบล็อกจนกว่างานทั้งหมดจะเสร็จสิ้น — พร้อมกัน
<?php
use Swoole\Coroutine as Co;
use Swoole\Coroutine\WaitGroup;
Co\run(function () {
$wg = new WaitGroup();
$results = [];
foreach (['eu', 'us', 'asia'] as $region) {
$wg->add();
go(function () use ($wg, $region, &$results) {
Co::sleep(0.5); // simulated API call
$results[$region] = "ok-$region";
$wg->done();
});
}
$wg->wait(); // all three ran in parallel (~0.5s)
var_dump($results);
});ช่องทางสำหรับการสื่อสาร
โครูทีนประสานงานกันผ่าน ช่องทาง — คิวที่มีชนิดข้อมูลและขนาดจำกัด ซึ่งจะระงับผู้ผลิตเมื่อเต็ม และระงับผู้บริโภคเมื่อว่างเปล่า นี่คือการส่งข้อความรูปแบบ CSP ซึ่งหลีกเลี่ยงการใช้ล็อกสำหรับสถานะที่ใช้ร่วมกันโดยสิ้นเชิง
<?php
use Swoole\Coroutine as Co;
use Swoole\Coroutine\Channel;
Co\run(function () {
$chan = new Channel(2);
go(function () use ($chan) {
foreach (range(1, 3) as $n) $chan->push($n);
$chan->push(null); // sentinel
});
go(function () use ($chan) {
while (($v = $chan->pop()) !== null) echo "got $v\n";
});
});การใช้กลุ่มการเชื่อมต่อ
เซิร์ฟเวอร์ที่ทำงานต่อเนื่องไม่ควรเปิดการเชื่อมต่อฐานข้อมูลใหม่สำหรับทุกคำขอ Swoole มี กลุ่มการเชื่อมต่อที่ปลอดภัยสำหรับโครูทีน ทำให้เวิร์กเกอร์ใช้ชุดการเชื่อมต่อจำนวนคงที่ร่วมกันได้ระหว่างโครูทีนหลายพันตัวที่ทำงานพร้อมกัน และขจัดการเปิดปิดการเชื่อมต่อที่ไม่จำเป็น
<?php
use Swoole\Database\PDOConfig;
use Swoole\Database\PDOPool;
use Swoole\Coroutine as Co;
Co\run(function () {
$pool = new PDOPool((new PDOConfig())
->withHost('127.0.0.1')->withDbname('app')
->withUsername('u')->withPassword('p'), 8);
go(function () use ($pool) {
$pdo = $pool->get(); // borrow
$row = $pdo->query('SELECT NOW()')->fetch();
$pool->put($pdo); // return to pool
var_dump($row);
});
});การรั่วไหลของสถานะ: กับดักหน่วยความจำถาวร
เนื่องจากกระบวนการทำงานต่อเนื่องข้ามคำขอ สถานะส่วนกลางและสถานะคงที่จะยังคงอยู่ แคชแบบคงที่ที่เติบโตไม่จำกัด ซิงเกิลตันที่เก็บข้อมูลเฉพาะคำขอ หรือธุรกรรมฐานข้อมูลที่รั่วไหล จะทำให้คำขอภายหลังเสียหายและใช้หน่วยความจำจนหมด กฎสำคัญคือ หลีกเลี่ยงการเก็บข้อมูลเฉพาะคำขอไว้ในสถานะแบบคงที่หรือซิงเกิลตัน รีเซ็ตบริบทสำหรับแต่ละคำขอ และตั้งค่า max_request เพื่อให้เวิร์กเกอร์เริ่มต้นใหม่เป็นระยะ
<?php
$server = new Swoole\Http\Server('0.0.0.0', 9501);
$server->set([
'worker_num' => 8,
'max_request' => 10000, // recycle a worker after N requests to bound leaks
]);
// Never store $request data in a static property between requests!บริบทเฉพาะโครูทีน
เนื่องจากเวิร์กเกอร์หนึ่งตัวสลับการทำงานระหว่างโครูทีนจำนวนมาก คุณจึงไม่สามารถใช้สถานะแบบคงที่ทั่วไปสำหรับข้อมูลเฉพาะคำขอได้ Swoole จะมอบ บริบท ให้โครูทีนแต่ละตัว (Coroutine::getContext()) ซึ่งเป็นออบเจกต์ที่มีอายุการใช้งานเท่ากับโครูทีน จึงเหมาะอย่างยิ่งสำหรับผู้ใช้ปัจจุบัน รหัสคำขอ หรือแฮนเดิลธุรกรรม
<?php
use Swoole\Coroutine as Co;
Co\run(function () {
go(function () {
$ctx = Co::getContext();
$ctx['request_id'] = 'req-123';
// ... deep call chain can read Co::getContext()['request_id']
echo Co::getContext()['request_id'], PHP_EOL;
});
});แบบจำลองกระบวนการและเวิร์กเกอร์งาน
Swoole ทำงานด้วยกระบวนการ หลัก (จัดการเธรดลูปเหตุการณ์) กระบวนการ ตัวจัดการ (สร้างและตรวจสอบเวิร์กเกอร์) กระบวนการ เวิร์กเกอร์ (เรียกใช้ตัวจัดการคำขอและโครูทีนของคุณ) และ เวิร์กเกอร์งานที่เป็นตัวเลือกสำหรับงานหนัก งานที่บล็อก หรือ งานที่ใช้ CPU ซึ่งถ่ายโอนไปผ่าน $server->task() ให้ใช้เวิร์กเกอร์งานสำหรับการประมวลผลภาพหรืองานที่ใช้ CPU เป็นเวลานาน เพื่อไม่ให้งานเหล่านั้นทำให้โครูทีนของคำขอหยุดชะงัก — ทำให้คุณได้ทั้งการทำงานพร้อมกันและการทำงานแบบขนาน
การเลื่อนดำเนินการและตัวจับเวลา
Swoole ช่วยให้คุณกำหนดเวลางานหลังจากโครูทีนปัจจุบันทำงานเสร็จด้วย Coroutine::defer() — เหมาะสำหรับการคืนทรัพยากรจากกลุ่มการเชื่อมต่ออย่างเชื่อถือได้ แม้จะเกิดข้อยกเว้นก็ตาม ตัวจับเวลาระดับเซิร์ฟเวอร์ (Timer::tick) จะเรียกใช้งานตามช่วงเวลา เช่น การรีเฟรชแคช ภายในเวิร์กเกอร์ได้โดยไม่ต้องใช้ตัวกำหนดเวลาภายนอก
<?php
use Swoole\Coroutine as Co;
Co\run(function () {
go(function () {
$conn = 'borrowed-connection';
Co::defer(function () use ($conn) {
echo "released $conn\n"; // runs when coroutine exits, even on error
});
echo "using $conn\n";
});
});ตรวจสอบอย่างรวดเร็ว
เหตุใดคุณจึงต้องหลีกเลี่ยงการเก็บข้อมูลคำขอไว้ในคุณสมบัติแบบคงที่ของเซิร์ฟเวอร์ Swoole
ทบทวน
Swoole เปลี่ยน PHP ให้เป็นเซิร์ฟเวอร์ที่ทำงานอยู่ในหน่วยความจำและขับเคลื่อนด้วยโครูทีน:
- แอปจะ เริ่มต้นเพียงครั้งเดียว จากนั้นกลุ่มเวิร์กเกอร์จะให้บริการคำขอด้วย โครูทีนในตัว (
Co\run/go()) - ฮุกของรันไทม์ทำให้ PDO/curl/sleep ตามปกติไม่บล็อก ส่วน WaitGroup และ Channels ใช้ประสานงานที่ทำพร้อมกัน
- กลุ่มการเชื่อมต่อนำการเชื่อมต่อฐานข้อมูลกลับมาใช้ซ้ำระหว่างโครูทีน
- หน่วยความจำที่คงอยู่หมายความว่าคุณต้องหลีกเลี่ยง การรั่วไหลของสถานะ: ใช้
Coroutine::getContext()สำหรับข้อมูลเฉพาะคำขอ ตั้งค่าmax_requestและถ่ายโอนงานหนักไปยัง เวิร์กเกอร์งาน
เรียนรู้ PHP ด้วย AI tutor — ฟรี
เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป
- คอร์ส
- 49
- บทเรียน
- 195
คำถามที่พบบ่อย
บทเรียน “เซิร์ฟเวอร์ประสิทธิภาพสูงด้วย Swoole” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “เซิร์ฟเวอร์ประสิทธิภาพสูงด้วย Swoole” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส PHP Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส PHP Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “เซิร์ฟเวอร์ประสิทธิภาพสูงด้วย Swoole”
ให้บริการการเชื่อมต่อหลายพันรายการด้วย Swoole ที่ทำงานบนคอร์รูทีน คุณปฏิบัติ PHP Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน PHP Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน PHP Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “เซิร์ฟเวอร์ประสิทธิภาพสูงด้วย Swoole” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน PHP Academy นี้ได้ไหม
ได้ บทเรียน PHP Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- โมเดลการทำงานพร้อมกันของ PHP
- ไฟเบอร์ของ PHP 8.1
- ลูปเหตุการณ์ด้วย ReactPHP
- เซิร์ฟเวอร์ประสิทธิภาพสูงด้วย Swoole