Laravel Octane trong 2026: Swoole, RoadRunner và Tối ưu Hiệu năng

Làm chủ Laravel Octane 2.19 với FrankenPHP, Swoole và RoadRunner. Tìm hiểu cách chọn server, phòng tránh memory leak, concurrent tasks và các pattern deployment production cho ứng dụng PHP hiệu năng cao.

Kiến trúc server Laravel Octane hiệu năng cao với Swoole và RoadRunner

Laravel Octane biến đổi hiệu năng ứng dụng PHP bằng cách giữ framework đã bootstrap trong bộ nhớ giữa các request. Phiên bản 2.19 (tháng 8 năm 2026) hỗ trợ ba server sẵn sàng cho production: FrankenPHP, SwooleRoadRunner. Mỗi server phục vụ các yêu cầu vận hành khác nhau, và việc chọn sai sẽ ảnh hưởng đến hiệu năng hoặc độ ổn định.

Tham Khảo Nhanh Về Chọn Server

FrankenPHP: cài đặt đơn giản nhất, HTTP/3 native, single binary. RoadRunner: binary Go đã được thử nghiệm thực tế, không yêu cầu extension PHP. Swoole: throughput tối đa với coroutine concurrency, cần quản lý PECL extension.

Cách Octane Loại Bỏ Chi Phí Bootstrap

PHP-FPM truyền thống khởi tạo một process mới cho mỗi request. Laravel boot service container, load cấu hình, đăng ký provider và resolve middleware trên mỗi lần gọi HTTP. Octane đảo ngược mô hình này: ứng dụng boot một lần cho mỗi worker, sau đó cùng một instance xử lý hàng nghìn request liên tiếp.

Lợi ích hiệu năng đến từ việc loại bỏ công việc lặp lại. Một ứng dụng Laravel 12 điển hình mất 15 đến 40ms để bootstrap trước khi thực thi logic nghiệp vụ. Với Octane, chi phí đó giảm về không sau request đầu tiên. Các benchmark trên phần cứng giống nhau cho thấy cải thiện throughput 2x đến 4x cho các endpoint API, với khoảng cách tăng lên khi độ phức tạp ứng dụng tăng.

config/octane.phpphp
return [
    'server' => env('OCTANE_SERVER', 'frankenphp'),
    
    // Workers handle HTTP requests
    'workers' => env('OCTANE_WORKERS', 8),
    
    // Gracefully restart workers after N requests to prevent memory bloat
    'max_requests' => env('OCTANE_MAX_REQUESTS', 500),
    
    // Task workers for Swoole concurrent operations
    'task_workers' => env('OCTANE_TASK_WORKERS', 6),
    
    // Maximum execution time per request in seconds
    'max_execution_time' => 30,
];

Cấu hình max_requests hoạt động như một van an toàn. Ngay cả code được viết tốt cũng có thể tích lũy bộ nhớ qua hàng trăm request. Đặt giá trị này thành 500 buộc worker phải restart trước khi áp lực bộ nhớ trở nên nghiêm trọng.

FrankenPHP: Mặc Định 2026 Cho Dự Án Mới

FrankenPHP được phân phối dưới dạng single binary được xây dựng trên Caddy và PHP. Server này tự động xử lý chứng chỉ HTTPS thông qua Let's Encrypt, hỗ trợ HTTP/3 ngay lập tức và không yêu cầu cài đặt extension PHP. Installer của Laravel và các ví dụ production hiện mặc định sử dụng FrankenPHP.

bash
# Install Octane with FrankenPHP
composer require laravel/octane
php artisan octane:install --server=frankenphp

# Start the server
php artisan octane:start --server=frankenphp --host=0.0.0.0 --port=8000

Đối với deployment được container hóa, FrankenPHP cung cấp các image Docker chính thức:

dockerfile
# Dockerfile
FROM dunglas/frankenphp

RUN install-php-extensions \
    pcntl \
    pdo_pgsql \
    redis

COPY . /app

ENTRYPOINT ["php", "artisan", "octane:frankenphp"]

Cấu hình Docker Compose cho development kích hoạt HTTPS và HTTP/3:

yaml
# compose.yaml
services:
  frankenphp:
    build:
      context: .
    entrypoint: php artisan octane:frankenphp --workers=1 --max-requests=1
    ports:
      - "443:443"
      - "443:443/udp"
    volumes:
      - .:/app

FrankenPHP xử lý việc restart worker một cách graceful và tích hợp trực tiếp với hệ thống middleware của Caddy cho các tình huống routing nâng cao.

RoadRunner: Độ Ổn Định Dựa Trên Go Không Phụ Thuộc Extension

RoadRunner được compile thành binary Go quản lý các process worker PHP. Server này giao tiếp với PHP qua giao thức binary, giữ việc quản lý worker và xử lý HTTP trong Go trong khi thực thi code ứng dụng trong PHP. Kiến trúc này cung cấp process isolation: một worker PHP bị crash không ảnh hưởng đến Go parent hoặc các worker sibling.

bash
# Install Octane with RoadRunner
composer require laravel/octane spiral/roadrunner-cli spiral/roadrunner-http

php artisan octane:install --server=roadrunner

# Download the RoadRunner binary
./vendor/bin/rr get-binary

# Start the server
php artisan octane:start --server=roadrunner --host=0.0.0.0 --port=8000

Cấu hình RoadRunner nằm trong .rr.yaml tại thư mục gốc của dự án:

yaml
# .rr.yaml
version: "3"

server:
  command: "php artisan octane:start --server=roadrunner --host=0.0.0.0 --port=8000"
  relay: pipes

http:
  address: 0.0.0.0:8000
  middleware: ["headers", "gzip"]
  pool:
    num_workers: 8
    max_jobs: 500
    supervisor:
      max_worker_memory: 128

Cấu hình max_worker_memory (tính bằng MB) terminate các worker vượt quá giới hạn bộ nhớ, cung cấp lớp bảo vệ bổ sung ngoài max_requests. Đối với các team có CI pipeline đã thiết lập và cơ sở hạ tầng PHP-FPM sẵn có, RoadRunner cung cấp lộ trình migration mượt mà nhất.

Swoole: Throughput Tối Đa Với Coroutine Concurrency

Swoole hoạt động như một PHP extension thay thế vòng đời request tiêu chuẩn bằng runtime event-driven có khả năng coroutine. Swoole cung cấp các tính năng không có sẵn ở các server khác: thực thi task đồng thời, ticks và intervals, cùng với in-memory cache có throughput 2 triệu operations mỗi giây.

bash
# Install Swoole via PECL
pecl install swoole

# Add to php.ini
echo "extension=swoole.so" >> $(php --ini | grep "Loaded Configuration" | cut -d: -f2 | xargs)/php.ini

# Install Octane with Swoole
composer require laravel/octane
php artisan octane:install --server=swoole

# Start with task workers for concurrent operations
php artisan octane:start --server=swoole --workers=8 --task-workers=6

Thực thi task đồng thời của Swoole xử lý các I/O operation song song trong một request:

app/Http/Controllers/DashboardController.phpphp
use App\Models\User;
use App\Models\Order;
use App\Models\Analytics;
use Laravel\Octane\Facades\Octane;

class DashboardController extends Controller
{
    public function index()
    {
        // Execute three queries concurrently instead of sequentially
        [$users, $orders, $analytics] = Octane::concurrently([
            fn () => User::active()->count(),
            fn () => Order::today()->sum('total'),
            fn () => Analytics::hourly()->get(),
        ]);

        return view('dashboard', compact('users', 'orders', 'analytics'));
    }
}

Không có Octane::concurrently(), ba query này thực thi tuần tự: 50ms + 30ms + 40ms = tổng 120ms. Với thực thi đồng thời, tổng thời gian bằng query chậm nhất: 50ms. Flag --task-workers kiểm soát số lượng concurrent operation có thể chạy đồng thời trên tất cả các request worker.

Tính Năng Chỉ Có Ở Swoole

Concurrent tasks, ticks, intervals, Octane cache và Swoole tables yêu cầu extension Swoole. FrankenPHP và RoadRunner không hỗ trợ các tính năng này. Đánh giá xem ứng dụng có cần các tính năng này không trước khi chọn độ phức tạp vận hành của Swoole.

Phòng Tránh Memory Leak: Viết Code Stateless

Hiệu năng của Octane đến từ persistent state, điều này tạo ra thách thức chính: code hoạt động tốt dưới PHP-FPM có thể gây memory leak nghiêm trọng dưới Octane. Instance ứng dụng tồn tại giữa các request, vì vậy static property, singleton và global state sẽ tích lũy.

Ba pattern gây ra phần lớn memory leak:

Mảng static tăng không giới hạn:

php
// WRONG: Memory leak - array grows with every request
class MetricsCollector
{
    public static array $data = [];

    public static function record(string $metric): void
    {
        self::$data[] = $metric; // Never cleared between requests
    }
}

// CORRECT: Use request-scoped storage or external systems
class MetricsCollector
{
    public function record(string $metric): void
    {
        Redis::lpush('metrics', $metric); // External storage
    }
}

Singleton giữ dữ liệu cụ thể theo request:

php
// WRONG: First request's user leaks into subsequent requests
$this->app->singleton(UserContext::class, function ($app) {
    return new UserContext($app['request']->user());
});

// CORRECT: Use closures for deferred resolution
$this->app->singleton(UserContext::class, function ($app) {
    return new UserContext(fn () => $app['request']->user());
});

Inject container và request trong constructor:

php
// WRONG: Captures stale container/request
class PaymentService
{
    public function __construct(
        private Application $app,
        private Request $request
    ) {}
}

// CORRECT: Inject via method parameters or use helpers
class PaymentService
{
    public function processPayment(Request $request): void
    {
        $user = $request->user();
        $config = config('services.stripe.key'); // Global helper, always fresh
    }
}

Các global helper app(), request()config() luôn trả về giá trị hiện tại. Sử dụng chúng thay vì constructor injection tránh được phần lớn các leak liên quan đến singleton.

Pattern Deployment Production

Các server Octane cần process supervision để restart khi crash. Supervisor xử lý việc này một cách đáng tin cậy:

ini
; /etc/supervisor/conf.d/octane.conf
[program:octane]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/app/artisan octane:start --server=frankenphp --host=127.0.0.1 --port=8000
autostart=true
autorestart=true
user=www-data
redirect_stderr=true
stdout_logfile=/var/www/app/storage/logs/octane.log
stopwaitsecs=3600

Đối với deployment, các worker Octane phải reload để nhận code mới. Lệnh octane:reload xử lý việc này một cách graceful, chờ các request đang xử lý hoàn thành trước khi tái chế worker:

bash
# In deployment script (after git pull, composer install, etc.)
php artisan octane:reload

Nginx đứng trước Octane để phục vụ static assets và terminate SSL:

nginx
# /etc/nginx/sites-available/app.conf
upstream octane {
    server 127.0.0.1:8000;
    keepalive 32;
}

server {
    listen 443 ssl http2;
    server_name example.com;
    root /var/www/app/public;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    location / {
        try_files $uri $uri/ @octane;
    }

    location @octane {
        proxy_http_version 1.1;
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Connection "";
        proxy_pass http://octane;
    }
}

Directive keepalive duy trì các kết nối persistent giữa Nginx và Octane, giảm chi phí TCP handshake cho các request được proxy.

Sẵn sàng chinh phục phỏng vấn Laravel?

Luyện tập với mô phỏng tương tác, flashcards và bài kiểm tra kỹ thuật.

Cây Quyết Định Chọn Server

Việc chọn giữa FrankenPHP, RoadRunner và Swoole phụ thuộc vào các ràng buộc vận hành và yêu cầu ứng dụng:

Yêu CầuServer Được Khuyến Nghị
Cài đặt đơn giản nhất, deployment container hóaFrankenPHP
Hỗ trợ HTTP/3 ngay lập tứcFrankenPHP
Không phụ thuộc PHP extensionFrankenPHP hoặc RoadRunner
Process isolation tối đaRoadRunner
Cơ sở hạ tầng PHP-FPM đã cóRoadRunner
I/O đồng thời trong requestSwoole
In-memory caching (2M ops/giây)Swoole
Ticks, intervals, background tasksSwoole
Swoole tables cho shared stateSwoole

Đối với các team bắt đầu dự án mới trong năm 2026, FrankenPHP cung cấp sự cân bằng tốt nhất giữa đơn giản và khả năng. Migration ứng dụng hiện có hoạt động tốt nhất với RoadRunner do process isolation và mô hình deployment quen thuộc. Swoole phù hợp với các API throughput cao cần tận dụng coroutine concurrency và yêu cầu các tính năng đặc thù của Swoole.

Câu Hỏi Phỏng Vấn Về Laravel Octane

Các buổi phỏng vấn kỹ thuật ngày càng đề cập đến Octane khi các ứng dụng Laravel lưu lượng cao áp dụng nó. Các câu hỏi phổ biến và điều người phỏng vấn tìm kiếm:

"Octane đạt được cải thiện hiệu năng như thế nào?"

Câu trả lời mong đợi: Octane boot Laravel một lần cho mỗi worker và tái sử dụng instance đó giữa các request, loại bỏ chi phí bootstrap 15-40ms trên mỗi request. Ứng viên nên đề cập rằng các method registerboot của service provider chạy một lần cho mỗi worker, không phải mỗi request.

"Điều gì gây ra memory leak trong ứng dụng Octane?"

Câu trả lời mạnh mẽ xác định ba nguồn: mảng static tích lũy dữ liệu, singleton capture state cụ thể theo request, và constructor injection các object container hoặc request. Ứng viên nên giải thích rằng cách khắc phục liên quan đến việc sử dụng closure cho deferred resolution hoặc truyền dữ liệu qua tham số method.

"Khi nào nên chọn Swoole thay vì RoadRunner?"

Ưu điểm của Swoole là coroutine concurrency qua Octane::concurrently(), Octane cache tốc độ cao, và các tính năng như ticks và intervals. Đánh đổi là độ phức tạp vận hành: Swoole yêu cầu quản lý PECL extension, trong khi RoadRunner được phân phối dưới dạng binary Go. Đối với ứng dụng CRUD không cần concurrent I/O, RoadRunner đơn giản hơn để vận hành.

"Làm thế nào để xử lý deployment với Octane?"

Trình tự deployment: ngừng nhận kết nối mới, chờ các request đang xử lý hoàn thành, reload worker với code mới. Lệnh php artisan octane:reload xử lý việc này. Ứng viên nên đề cập Supervisor hoặc systemd cho process supervision và Nginx hoặc Caddy làm reverse proxy.

Monitoring và Profiling Ứng Dụng Octane

Việc monitoring bộ nhớ trở nên quan trọng dưới Octane. Worker tồn tại, vì vậy sự tăng trưởng bộ nhớ chỉ ra leak thay vì overhead request bình thường. Laravel Pulse và Telescope đều hoạt động với Octane và cung cấp profiling ở cấp request.

app/Providers/AppServiceProvider.phpphp
use Laravel\Octane\Events\RequestReceived;
use Laravel\Octane\Events\RequestTerminated;

public function boot(): void
{
    Event::listen(RequestReceived::class, function ($event) {
        $event->sandbox->instance('request.memory.start', memory_get_usage());
    });

    Event::listen(RequestTerminated::class, function ($event) {
        $start = $event->sandbox->make('request.memory.start');
        $delta = memory_get_usage() - $start;
        
        if ($delta > 1024 * 1024) { // More than 1MB growth
            Log::warning('High memory delta', [
                'path' => $event->request->path(),
                'delta_mb' => round($delta / 1024 / 1024, 2),
            ]);
        }
    });
}

Event listener này ghi lại các request tăng bộ nhớ hơn 1MB, giúp xác định các endpoint cần tối ưu. Đối với monitoring production, các công cụ APM bên ngoài như Datadog hoặc New Relic cung cấp khả năng hiển thị ở cấp worker.

Tích Hợp Octane Với Queue và Horizon

Octane xử lý HTTP request; Laravel Horizon quản lý queue worker. Cả hai hoạt động độc lập và bổ sung cho nhau. Xử lý nặng nên được đặt trong queued job, giữ cho worker Octane luôn responsive.

app/Http/Controllers/ReportController.phpphp
use App\Jobs\GenerateReport;

class ReportController extends Controller
{
    public function generate(Request $request)
    {
        // Dispatch to queue instead of blocking the Octane worker
        GenerateReport::dispatch($request->user(), $request->input('parameters'));

        return response()->json(['status' => 'processing']);
    }
}

Những Điều Cần Nhớ Về Laravel Octane trong 2026

  • Octane 2.19 hỗ trợ ba server: FrankenPHP (đơn giản nhất), RoadRunner (ổn định nhất) và Swoole (nhiều tính năng nhất)
  • Cải thiện hiệu năng đến từ việc loại bỏ bootstrap mỗi request; kỳ vọng cải thiện throughput 2x đến 4x
  • Memory leak xảy ra vì worker state tồn tại; tránh mảng static, request được inject trong constructor, và singleton với dữ liệu request
  • Sử dụng --max-requests=500 để buộc tái chế worker trước khi áp lực bộ nhớ tăng
  • Các tính năng chỉ có ở Swoole bao gồm Octane::concurrently(), ticks, intervals và Octane cache
  • Deploy phía sau Nginx hoặc Caddy với Supervisor để quản lý process
  • Profiling sự tăng trưởng bộ nhớ mỗi request; delta trên 1MB chỉ ra potential leak
  • Queue công việc nặng qua Horizon; để worker Octane xử lý các HTTP response nhanh

Bắt đầu luyện tập!

Kiểm tra kiến thức với mô phỏng phỏng vấn và bài kiểm tra kỹ thuật.

Thử thách hôm nay

Bạn có tìm ra lỗi trong Laravel không?

Một đoạn mã thật, một lỗi ẩn, mỗi ngày một lượt. Không cần tài khoản để thử.

Anthony Fillion-Maillet

Viết bởi

Anthony Fillion-Maillet

Người sáng lập SharpSkill

Lập trình viên fullstack hơn 10 năm. Anh điều hành SharpSkill và chịu trách nhiệm về mọi nội dung đăng tại đây.

Cập nhật ngày 11 tháng 9, 2026

Thẻ

#laravel
#octane
#swoole
#roadrunner
#frankenphp
#performance
#php

Chia sẻ

Bài viết liên quan