PHP uzun zamandır “yavaş” ya da yüksek ölçekli sistemler için yetersiz bir dil olarak damgalanmış durumda. Bu damga, büyük ölçüde dilin kendisinden değil, geleneksel Shared-Nothing yürütme modelinden kaynaklanıyor.
Bugün, RoadRunner ve PHP 8’in nasıl bu durumu değiştirdiğinden, Go ve Node.js ile boy ölçüşen performanslar sunduğundan bahsedeceğiz.
Sorun: “Shared-Nothing” Döngü Modelinin Darboğazı
Sorun: “Shared-Nothing” Döngü Modelinin Darboğazı
PHP’yi onlarca yıldır şekillendiren geleneksel model (Apache/Nginx + PHP-FPM), Shared-Nothing konseptine dayanıyor. Bu, her HTTP isteğinin izole ve geçici bir olay olarak ele alındığı anlamına geliyor.
Her kullanıcı tıklama işlemi için, sunucu büyük bir çaba harcıyor:
Runtime Başlatma: İşletim sistemi bir işlem veya thread oluşturur ve PHP, Core’unu ve tüm yapılandırılmış uzantıları (mbstring, pdo, json, vb.) yüklemelidir.
Dosyaların Ayrıştırılması: Yorumlayıcı, çok sayıda .php dosyasını okur ve derler, özellikle Laravel veya Symfony gibi frameworklerde. OPcache bile olsa, uygulamanın nesne ağacını “oluşturma” çabası tekrarlanır.
Framework’ün Başlatılması: Uygulama Service Provider’ları örnekler, yapılandırmaları yükler, Bağımlılık Enjeksiyonu Container’ını hazırlar ve rotaları kaydeder.
Harici Bağlantılar: Yeni Veritabanı ve Redis bağlantıları kurulur (bu TCP/TLS el sıkışma maliyetini içerir).
İşlem ve Yok Oluş: Lojik yürütülür, yanıt gönderilir ve işlem hemen yok edilir. Bellek tamamen serbest bırakılır ve bir sonraki istek için hiçbir şey yeniden kullanılmaz.
Bir restoranı düşünün, her müşteri geldiğinde ekip sıfırdan mutfak kurmak, ocak kurmak, yemek pişirmek ve müşteri ödemesini yaptıktan sonra bütün mutfağı bir kırıcı ile yıkmak zorunda kalıyor.
Bu başlatma (bootstrapping) yükü, genellikle uygulama lojiklerinden daha fazla zaman ve CPU tüketiyor. Yüksek trafik sistemlerinde, bu durum PHP-FPM’in yatay bir şekilde verimli bir şekilde ölçeklenmesini engelliyor.
Çözüm: RoadRunner ve İşçi Modeli
Çözüm: RoadRunner ve İşçi Modeli
RoadRunner, Go’da yazılmış yüksek performanslı bir uygulama sunucusudur. PHP-FPM’in aksine, sürekli işçi modeli kullanır.
Uygulamanızı bir kez başlatır ve bellekte canlı tutar. Bir istek geldiğinde, RoadRunner (Go’daki Goroutines aracılığıyla) bunu “hazır” bir PHP işçisine iletir; böylece framework yüklü, veritabanı bağlantıları hazır ve işleme hazırdır.
Performans Artışı (Grafik Temsil)
Performans Artışı (Grafik Temsil)
Basit bir API’deki istek sayısını (RPS) karşılaştırdığımızda:
Laravel Octane: İlk Aşama Deneyimi
Laravel Octane: İlk Aşama Deneyimi
Laravel geliştiricisiyseniz, RoadRunner kullanımı Laravel Octane ile oldukça basit hale gelmiştir. Örgün işçileri yönetme karmaşıklığını soyutlar.
Tek bir komutla:
php artisan octane:start --server=roadrunner
Uygulamanız sürekli bir durumda çalışmaya başlar; bu da iş mantığı değişmeden yüzde 5 ila 10 oranında performans artışı sağlar.
Pratik Örnek: Altında Nasıl Çalışır?
Pratik Örnek: Altında Nasıl Çalışır?
RoadRunner uygulamanızı anlamak için bir yapılandırma dosyası ve bir “giriş noktası” (işçi) kullanır.
Yapılandırma (.rr.yaml)
version: "3"
http:
address: :8080
pool:
num_workers: 4 # Her zaman 4 PHP örneğini canlı tutar
max_jobs: 64
allocate_timeout: 60s
destroy_timeout: 60s
server:
command: "php worker.php" # İşçiyi başlatan komut
PHP İşçisi (worker.php)
spiral/roadrunner kütüphanesini kullanarak, kod şu şekilde olur:
use Spiral\RoadRunner;
use Nyholm\Psr7;
require __DIR__ . '/vendor/autoload.php';
$worker = RoadRunner\Http\HttpWorker::create(
RoadRunner\Worker::create()
);
$factory = new Psr7\Factory\Psr17Factory();
while ($request = $worker->waitRequest()) {
try {
// İş mantığınız burada - Framework zaten bellekte yüklü!
$response = $factory->createResponse(200)
->withBody($factory->createStream('Olá do RoadRunner!'));
$worker->respond($response);
} catch (\Throwable $e) {
$worker->getWorker()->error((string)$e);
}
}
Önemli Dikkat Noktaları
Önemli Dikkat Noktaları
Her şey mükemmel değil. Uygulama her istek sonrası “ölmediği” için dikkat etmeniz gereken noktalar var:
Memory Leak’ler: Sürekli büyüyen global veya statik değişkenler işçiyi çökertir.
Singleton’lar: Container’a enjekte edilen nesneler kullanıcılar arasında kalıcı olabilir; bu nedenle uygun biçimde sıfırlanmalıdır (Octane birçok durumu yönetir).
Veritabanı Bağlantıları: Zaman aşımı ve aktif olmayan bağlantıların (idle) yönetimi dikkate alınmalıdır; zira bağlantılar isteğin sonunda kapanmaz.
PHP 8 ve RoadRunner bir araya geldiğinde, dilin her zamankinden daha canlı olduğunu ve yüksek trafik mikrosistemleri ve API’ler için hazır olduğunu kanıtlamaktadır. Hala işçi modelini test etmediyseniz, performans (ve para) kaybediyorsunuz demektir.
Production ortamında RoadRunner veya Laravel Octane kullanıyor musunuz? Göçte yaşadığınız en büyük zorluklar nelerdi?
Kaynak: Orijinal Makale



