Giới thiệu chung

  • FrankenPHP là một application server hiện đại dành cho PHP được xây dựng trên Caddy web server.
  • Được tạo bởi Kévin Dunglas, và Symfony Core Team member.
  • FrankenPHP hoạt động với mọi ứng dụng PHP và làm cho các dự án PHP nhanh hơn. FrankenPHP cũng có thể được sử dụng làm thư viện Go độc lập để nhúng PHP vào bất kỳ ứng dụng nào nhờ sử dụng net/http.

SAPI


SAPI là viết tắt của Server Application Programming Interface, là một giao diện lập trình ứng dụng máy chủ. SAPI cung cấp một cách tiêu chuẩn để các ứng dụng web tương tác với máy chủ web.

103 Early Hints


103 Early Hints là một tính năng mới trong PHP 8.1, cho phép các ứng dụng web cung cấp thông tin sớm hơn cho máy chủ web. Điều này có thể giúp cải thiện hiệu suất của ứng dụng.

Về mặt hình thức, Early Hints là một tiêu chuẩn web định nghĩa một HTTP status code mới (103) nhằm xác định các tương tác mới giữa máy khách và máy chủ. 103 được cung cấp cho máy khách trong khi phản hồi 200 OK (hoặc lỗi) được chuẩn bị, tức là trong "thời gian suy nghĩ của máy chủ".

  • Khi không sử dụng Early Hints:
Khi không sử dụng Early Hints
  • Khi sử dụng Early Hints:
Khi có sử dụng Early Hints

Theo một cuộc nghiên cứu của Cloudflare, việc sử dụng 103 Early Hints có thể giúp cải thiện 30% tốc độ load content một trang trên trình duyệt.

FPM


FPM là viết tắt của FastCGI Process Manager, là một SAPI phổ biến nhất được cung cấp bởi PHP. FPM sử dụng mô hình worker process để chạy PHP. Hiện tại nó được hỗ trợ bởi hầu hết web servers: Nginx, Apache, Caddy,...

Nhược điểm:

  • Là dịch vụ ngoài của PHP
  • Yêu cầu UNIX hoặc TCP socket
  • Khó đóng gói

Apache Module

Apache Module là một mô-đun của Apache HTTP Server, cho phép Apache chạy PHP. Apache Module sử dụng mô hình truyền thống để chạy PHP.

Nhược điểm

  • Chỉ làm việc với Apache
  • Hiệu suất thấp hơn FPM

So sánh mô hình truyền thống và FrankenPHP

Mô hình truyền thống PHP-FPM và Nginx.
Mô hình deploy app với Nginx + PHP-FPM

Nhược điểm:

  • PHP không nói chuyện trực tiếp với HTTP.
  • PHP cần 1 cầu nối thông qua một web server của bên thứ 3.
  • PHP-FPM là Server API (SAPI) phổ biết nhất nhưng là server được liên kết bên ngoài nhờ sử dụng FastCGI protocol. Trong khi đó mod_php cho Apache không tương thích hoặc không được khuyến khích dùng với Apache hiện đại.

Tức là:

  • Mô hình PHP-FPM + Nginx cần ít nhất 2 services
  • Cần UNIX/TCP socket hoặc liên kết network giữa FPM và web server

Từ nhược điểm của mô hình trên, chúng ta có thể nào cải tiến hơn được không?

Mô hình FrankenPHP

Hoàn hảo cho containers

  • Chỉ 1 service
  • Không phụ thuộc bên ngoài

Xây dựng dựa trên Caddy

  • Mọi tính năng và modules của Caddy
  • Lợi thế từ Go
  • Có thể mở rộng: trong Go, C, PHP

Config đơn giản:

  • Caddyfile
  • php.ini

Prod, CI, dev

Thư viện Go độc lập

Nhúng PHP vào code Go

Caddy

Caddy là một máy chủ web mã nguồn mở, sử dụng mô hình worker process để chạy PHP.

  • Bảo mật và nhanh
  • Dễ dàng cấu hình
  • Hoạt động trên Cloud: API, hot config reloading,…
  • Tự động HTTPS
  • HTTP/2, HTTP/3, Early Hints…
  • Có thể mở rộng với modules: Mercure, Vulcain, OAuth, OIDC,..
  • Production-ready
  • Viết bằng Go

Đặc điểm nổi bật

Worker Mode

Starting Worker Scripts

Docker

Đặt giá trị của biến môi trường FRANKENPHP_CONFIG thành worker /path/to/your/worker/script.php:

docker run \
    -e APP_RUNTIME=Runtime\\FrankenPhpSymfony\\Runtime \
    -v $PWD:/app \
    -p 80:80 -p 443:443 \
    dunglas/frankenphp

Standalone Binary

Sử dụng --worker option của php-server command để khởi động server từ thư mục hiện tại bằng cách sử dụng một worker:

./frankenphp php-server --worker /path/to/your/worker/script.php

Symfony Runtime

Chế độ worker của FrankenPHP được hỗ trợ bởi Symfony Runtime Component.. Để khởi động bất kỳ ứng dụng Symfony nào trong một worker, hãy cài đặt gói FrankenPHP của PHP Runtime:

composer require runtime/frankenphp-symfony

Khởi động app server của bạn bằng cách xác định biến môi trường APP_RUNTIME để sử dụng FrankenPHP Symfony Runtime:

docker run \
    -e FRANKENPHP_CONFIG="worker ./public/index.php" \
    -e APP_RUNTIME=Runtime\\FrankenPhpSymfony\\Runtime \
    -v $PWD:/app \
    -p 80:80 -p 443:443 \
    dunglas/frankenphp

Benchmark

Để test hiệu năng của FrankenPHP, tôi cài đặt môi trường và kịch bản test như sau:

  • Hello World Symfony app (prod mode)
  • Caddy Web Server (HTTP/2)
  • 300 requests, 10 connected users
  • Benchmark tool: K6

Kết quả:

Average request duration

  • FPM: 29.36 ms
  • FrankenPHP (worker): 1771.71 ms
Môi trường FPM
Môi trường FrankenPHP

Nhìn vào 2 bảng kết quả dưới đây, ở thông số http_req_duration chúng ta có thể nhận thấy với FrankenPHP thời gian xử lý request mất 29.36 ms, còn FPM mất 1771.71 ms. Một sự cải thiện đáng kể về thời gian xử lý đúng không nào?

Kết luận

  • Sử dụng FrankenPHP cho ứng dụng PHP có hiệu suất tốt hơn FPM thông thường
  • Tích hợp sẵn nhiều tính năng (bao gồm bảo mật tốt) và công nghệ Go.
  • Tiết kiệm thời gian phát triển.
  • Tiết kiệm tài nguyên hệ thống.
  • Dễ sử dụng.

Đến thời điểm hiện tại, FrankenPHP vẫn là một app server mới ra mắt nên nguồn tài liệu, cộng đồng vẫn còn hạn chế nhưng nó vẫn có thể phát triển hơn nữa trong tương lai. Nhìn chung đây là một gợi ý cho các developer về việc build môi trường cho dự án PHP một cách nhanh chóng và thuận tiện, rất đáng để apply thử vào trong dự án thực tế. Hy vọng FrankenPHP này sẽ giúp ích cho bạn. Cảm ơn vì đã đọc bài viết!

Tham khảo