FrankenPHP: แอปเซิร์ฟเวอร์ PHP สมัยใหม่
(frankenphp.dev)- ในเวิร์กโฟลว์การดีพลอยที่ต้องการรันแอป PHP โดยไม่ต้องมี PHP-FPM แยกต่างหาก FrankenPHP คือแอปเซิร์ฟเวอร์บน Go ที่ฝัง ตัวรัน PHP อย่างเป็นทางการไว้ใน Caddy ทำให้รันเว็บแอป PHP และสคริปต์ CLI ได้ด้วยคำสั่งเดียว
- รวม HTTP/1.1, HTTP/2, HTTP/3, ใบรับรอง HTTPS อัตโนมัติ, การบีบอัด Brotli/Zstandard/Gzip, structured logging และเมตริก Prometheus เป็นฟีเจอร์พื้นฐาน เพื่อลดการตั้งค่าเซิร์ฟเวอร์
- Worker mode บูตแอปหนึ่งครั้งแล้วคงไว้ในหน่วยความจำ โดยอธิบายว่าจากเบนช์มาร์กของแอป API Platform เองให้ผลลัพธ์ เร็วกว่า FPM 3.5 เท่า
- เข้ากันได้กับ PHP 8.2+, ส่วนขยาย PHP ส่วนใหญ่ และโมดูล Caddy รวมถึงรองรับส่วนขยายยอดนิยมอย่าง OPcache และ XDebug แบบเนทีฟ
- รองรับ Docker image, Kubernetes, แพลตฟอร์มคลาวด์ และการดีพลอยเป็นไบนารีสแตติกแบบ standalone ช่วยทำให้ หน่วยการดีพลอยแอป PHP เรียบง่ายขึ้น
วิธีรันและโฟลว์การใช้งานพื้นฐาน
- FrankenPHP มุ่งเป็น แอปเซิร์ฟเวอร์ PHP สมัยใหม่ที่เขียนด้วย Go โดยจัดโครงสร้างการติดตั้งและการรันแอปเซิร์ฟเวอร์ PHP ให้เน้นคำสั่งเดียว
- ตัวอย่างการติดตั้งแบ่งตามระบบปฏิบัติการ
- Linux/macOS:
curl https://frankenphp.dev/install.sh | sh - Windows PowerShell:
irm https://frankenphp.dev/install.ps1 | iex
- Linux/macOS:
- การรันบนเครื่องรองรับทั้งเว็บเซิร์ฟเวอร์และ CLI
frankenphp php-server -r public/: เสิร์ฟไดเรกทอรีpublic/frankenphp php-cli script.php: รันสคริปต์ PHP บน command line
- การรันด้วย Docker ก็ใช้ image เดียวกัน
- เสิร์ฟไดเรกทอรี
public/ด้วย imagedunglas/frankenphp - สามารถรันสคริปต์ CLI เช่น
php script.phpจาก image เดียวกันได้
- เสิร์ฟไดเรกทอรี
- การตั้งค่าอิงกับ Caddy โดยตัวอย่างคอนฟิกจะเปิดการบีบอัดในบล็อก
localhostและใช้php_serverเพื่อจัดการไฟล์ PHP และไฟล์ static asset ในไดเรกทอรีปัจจุบัน
ฟีเจอร์เซิร์ฟเวอร์และความเข้ากันได้กับ PHP
-
ฟีเจอร์เว็บเซิร์ฟเวอร์
- ฝังตัวรัน PHP อย่างเป็นทางการไว้ใน Caddy
- รองรับ HTTP/1.1, HTTP/2, HTTP/3 แบบเนทีฟ
- สร้าง ต่ออายุ และเพิกถอนใบรับรอง HTTPS ผ่าน Let’s Encrypt หรือ ZeroSSL โดยอัตโนมัติ
- รองรับการบีบอัด Brotli, Zstandard และ Gzip เป็นค่าเริ่มต้น
- รวม structured logging และ การรองรับ Prometheus
-
สภาพแวดล้อมรันไทม์ PHP
- เข้ากันได้กับ PHP 8.2+, ส่วนขยาย PHP ส่วนใหญ่ และโมดูล Caddy ทั้งหมด
- รองรับส่วนขยาย PHP ยอดนิยม รวมถึง OPcache และ XDebug แบบเนทีฟ
- ไม่ต้องใช้ PHP-FPM และใช้ SAPI ของตัวเองที่สร้างมาสำหรับเว็บเซิร์ฟเวอร์ Go
Worker mode และฟีเจอร์ที่มุ่งเน้นประสิทธิภาพ
- Worker mode บูตแอปพลิเคชันหนึ่งครั้งแล้วคงไว้ในหน่วยความจำ ทำให้พร้อมจัดการคำขอได้ภายในไม่กี่มิลลิวินาที
- รองรับแบบเนทีฟใน Symfony, API Platform และ Laravel
- ใช้ PHP superglobals เดิมโดยไม่ต้องมี PSR-7
- แม้แอปจะไม่เข้ากันได้กับ Worker mode ก็ยังสามารถเสิร์ฟได้ตามเดิม
- มี watcher สำหรับรีสตาร์ท worker อัตโนมัติเมื่อโค้ดเปลี่ยน
- แนะนำว่าจากเบนช์มาร์กของตัวเองบนแอป API Platform แสดงประสิทธิภาพ เร็วกว่า FPM 3.5 เท่า
การดีพลอยและแพ็กเกจจิง
- สามารถดีพลอยแอป cloud-native ด้วย Docker image
- เข้ากันได้กับ Kubernetes และแพลตฟอร์มคลาวด์สมัยใหม่
- สามารถแพ็กเกจเว็บแอปพลิเคชัน PHP และเครื่องมือ command line เป็น ไบนารีสแตติกแบบ standalone ได้
- อธิบายว่ารันเป็นบริการเดียวและไบนารีเดียว โดยไม่ต้องมีบริการภายนอก
ฟีเจอร์เว็บแพลตฟอร์มเพิ่มเติม
- รองรับ 103 Early Hints และแนะนำว่าเป็นฟีเจอร์ที่สามารถปรับปรุงเวลาโหลดเว็บไซต์ได้ 30% โดยอ้างอิงบทความของ Cloudflare
- ผ่านฮับ Mercure ในตัว แอป PHP สามารถส่งอีเวนต์ไปยังเบราว์เซอร์ที่เชื่อมต่ออยู่ และเบราว์เซอร์รับ payload ได้ทันทีในรูปแบบอีเวนต์ JavaScript
- รองรับการดีพลอยแบบไม่หยุดให้บริการด้วย Graceful reload
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
คาแรกเตอร์ช้างแฟรงเกนสไตน์มันประหลาด หน้าตาไม่สวย แต่น่ารัก ดีไซน์ สี ข้อความ และแอนิเมชันก็ดูเรียบร้อย จากมุมของคนที่ห่างจากการพัฒนา PHP ไปพักใหญ่ value proposition สื่อออกมาได้ชัด และดูเหมาะกับการเริ่มทำอะไรเล็ก ๆ ได้อย่างรวดเร็ว
ไม่อยากต้องรันคอนเทนเนอร์ 8 ตัวเพื่อแยกซอฟต์แวร์ห่วย ๆ หรือ dependency ที่พันกันยุ่ง ๆ ออกมา ผมไม่ชอบแนวทางที่แทนจะปล่อยซอฟต์แวร์ที่ติดตั้งได้ กลับเอา “บนเครื่องผมรันได้นะ” มาห่อแล้วโยนออกสู่โลก อาจจะลองจับดูเพราะความคิดถึงได้ แต่ไม่แน่ใจแล้วว่าอยากเอาอะไรแบบนี้เข้า production อีกไหม
ภาษาควรไปในทิศทางแบบนี้ มากกว่าจะเป็นแนวที่ต้องตั้งค่า Apache ค่อนข้างซับซ้อนเหมือน LAMP สมัยก่อน
ผมก็คิดว่าจะลองตัวนี้ดูเหมือนกัน แต่ไม่เคยเจอคอขวดจาก nginx หรือ Apache เลย ทั้งคู่ใช้เวลามากสุดไม่กี่นาทีก็รันขึ้นได้
มันรันเป็นบริการเดียวเหมือน Apache + mod_php จัดการ multiprocessing ของ PHP และภาษาอื่น ๆ, ไฟล์ static, reverse proxy และสามารถจัดการทั้งตัวมันเองกับ PHP จาก config เดียวกันแบบ runtime ผ่านไฟล์หรือ socket ได้: https://unit.nginx.org/configuration/#php
ตัวอย่าง config จริงอยู่ที่ https://github.com/PrivateBin/docker-unit-alpine/blob/master... และยังทำ container image ผลลัพธ์ให้ค่อนข้างเล็กได้ด้วย: https://hub.docker.com/r/privatebin/unit-alpine
นอกจากรีสตาร์ต Apache แล้วก็จำไม่ได้ว่าต้องทำอะไรเพิ่มเป็นพิเศษ
ก็ประมาณ
LoadModule proxy_fcgi_module "/usr/lib/apache2/modules/mod_proxy_fcgi.so"กับSetHandler "proxy:fcgi://127.0.0.1:9000"นอกจากนี้ยังมีตัวอย่าง Nginx ที่คล้ายกันในเชิงแนวคิดกับวิธีตั้งค่า Apache และรวมถึงการติดตั้งแพ็กเกจที่จำเป็นด้วย: https://news.ycombinator.com/item?id=37443911มี container image ที่ build ไว้ล่วงหน้าซึ่งให้ผลใกล้เคียงกันด้วย แต่ถ้าอยากดูว่าข้างในทำงานอย่างไร ก็ลองทำเองได้ แน่นอนว่าง่ายกว่าการตั้งค่า Tomcat หรือ GlassFish ด้วยมือใน application server ของ Java สมัยก่อน และแม้คำสั่งรันเดี่ยว ๆ จะดีกว่าในทุกสภาพแวดล้อม แต่ LAMP ก็ไม่ได้แย่ขนาดนั้นเมื่อเทียบกับ stack อื่น ๆ
ถ้ามีไบนารี ก็ผูกเข้ากับแอป Electron ได้ง่ายขึ้นด้วย
php -S 0.0.0.0:8000 public/index.phpแต่มันเป็น single-thread และช้า จึงไม่เหมาะกับ production FrankenPHP ดูมีอนาคต แต่ปัญหาเรื่องข้อจำกัดของ core/thread[2] ก็ดูเหมือนอาจเป็นปัญหาใน production ได้เหมือนกัน ถึงอย่างนั้นก็อาจลองนำไปใช้กับโปรเจกต์ pure-todo[1] เพื่อดูว่ามีปัญหาเดียวกันไหม Docker image พื้นฐานดูค่อนข้างดี
1: https://github.com/sandreas/pure-todo
2: https://github.com/dunglas/frankenphp/discussions/294
ดูคำเตือนด้านบนของหน้า: https://www.php.net/manual/en/features.commandline.webserver...
ผมก็ไม่แน่ใจว่าการเอามาเป็นตัวเปรียบเทียบในบริบทนี้ยุติธรรมหรือเปล่า
PHP_CLI_SERVER_WORKERSก็สามารถรันแบบ หลายเธรด ได้ถ้าเป็นไซต์เล็ก ๆ ที่มีผู้ใช้น้อย ผมอยากรู้ว่าจะขาดอะไรไปเมื่อเทียบกับสภาพแวดล้อมอื่นที่ “พร้อมสำหรับ production”
เขาบอกว่าใช้ไม่กี่คำสั่งก็พร้อม production และเร็วกว่า FPM 3.5 เท่า แต่ในสภาพแวดล้อมของผมมันทำงานได้ประมาณ 1% ของประสิทธิภาพ FPM เท่านั้น ลองใช้ไฟล์ executable แล้วก็เจอปัญหาเดียวกัน และถ้าเป็น hello world อย่างน้อยผมคาดหวังไว้สัก 200K rps
ในเบนช์มาร์กส่วนใหญ่ เมื่อเปิดโหมด worker แล้ว FrankenPHP มักเร็วกว่า FPM มาก โดยประมาณราว 3 เท่า ถึงอย่างนั้นก็ยังมีบางกรณียกเว้น และกำลังแก้ไขร่วมกับผู้ดูแล PHP อยู่
ตัว Caddy เองให้ประสิทธิภาพดีมากเมื่อใช้ร่วมกับ PHP จึงเป็นสถานการณ์ที่ค่อนข้างแปลก
ตอนนี้อยู่ท้ายสุดด้วยสถานะ did not complete
มี ปัญหาด้านประสิทธิภาพ อยู่ ถ้าไม่นับเรื่องนั้น ก็เป็นโปรเจกต์ที่มีอนาคตมากจริง ๆ
อย่างไรก็ตาม ยังไม่ได้ขุดลึก และการทดสอบก็ทำใน Docker ไม่ใช่การตั้งค่าทั่วไป WordPress ก็แทบเป็นค่าเริ่มต้น จึงไม่มีธีมหนัก ๆ ทำให้ไม่ใช่เงื่อนไขที่สมจริงนัก ถึงอย่างนั้นก็อยากลองทดสอบใหม่และทำความเข้าใจให้ดีขึ้น
อย่างไรก็ตาม สามารถใช้ 103 Early Hints เพื่อโหลด asset ล่วงหน้าและลด latency ของการโหลดหน้าได้ 30% ถึงอย่างนั้น FrankenPHP ก็ทำให้เปิด HTTP cache ใน WordPress ได้ง่ายขึ้น และทำให้การ deploy ง่ายขึ้นด้วย ยังมีโปรเจกต์เฉพาะสำหรับ WordPress กับ FrankenPHP ซึ่งมี HTTP cache ในตัวที่ปรับแต่งสำหรับ WordPress โดยใช้ไลบรารี Souin Go รวมอยู่ด้วย: https://github.com/StephenMiracle/frankenwp
จะช่วยประหยัดหน่วยความจำของ Apache ได้อีกเล็กน้อย และเปิดพื้นที่ให้รองรับคำขอ PHP ได้มากขึ้น
docker run -v $PWD:/app/public -p 443:443 \ dunglas/frankenphpถ้าต้องการสร้าง Docker container เพื่อให้บริการแอปเอง คำสั่งด้านล่างน่าจะเพียงพอสำหรับเปลี่ยน Debian ใหม่ให้เป็น container ที่ต้องการ:
apt install -y apache2 libapache2-mod-phpและตั้งค่า/etc/apache2/sites-enabled/000-default.confกำลังดูแล repository ที่แสดงกระบวนการตั้งแต่ศูนย์ไปจนถึงเว็บแอปพลิเคชันที่รันอยู่จริง ด้วยภาษาและเฟรมเวิร์กยอดนิยมหลายตัว ร่วมกับเพื่อน ๆ: https://github.com/no-gravity/web_app_from_scratch
ทุกครั้งที่เปิด xdebug หลังจบเซสชันดีบักต้องรีสตาร์ต Apache ตั้งแต่เมื่อวานเริ่มตั้งค่า apache2 ให้ใช้ php-fpm แล้ว และสงสัยว่า FrankenPHP นี้จะเหมาะกับเราหรือไม่ อย่างน้อยก็ในสภาพแวดล้อมพัฒนา แต่หาในเอกสารไม่เจอว่าจะติดตั้ง PHP extension อย่างไร
000-default.confค่าเริ่มต้นของ Apache redirect จาก 443 ไป 80 หรือเปล่า?FPM และสถาปัตยกรรมแบบไม่แชร์อะไรเลยของมันเคยเป็นหัวใจสำคัญของความสำเร็จของ PHP มานานแล้ว แต่ก็รู้สึกว่าในขณะเดียวกัน มันก็เป็นโซ่ตรวนของ PHP ด้วย