PHP FPM ve Nginx Optimizasyon Rehberi
Bu rehber, PHP-FPM ile Nginx'in birlikte çalıştığı tipik bir kurulumda performansı ve kararlılığı artırmaya yönelik ayarları ele alır. Hedef kitle, temel Nginx ve PHP bilgisine sahip orta seviye geliştiricilerdir. Amaç, kopyala-yapıştır yapılabilecek hazır bir yapılandırma sunmak değil; hangi ayarın hangi sorunu çözdüğünü anlatıp kendi ortamınıza uyarlamanızı sağlamaktır.
Önkoşullar ve kapsam
- Nginx ve PHP-FPM'in kurulu ve çalışır durumda olduğu bir sunucu.
- PHP-FPM pool yapılandırmasına (
www.confgibi) ve Nginx site yapılandırmasına erişim. - Temel
systemctl, süreç izleme ve log okuma bilgisi.
Sürüm kapsamı: Bu rehber, PHP-FPM'in pm (process manager) modelini ve Nginx'in fastcgi_pass üzerinden PHP'ye istek iletme akışını temel alır. Bu davranış PHP 7.x ve 8.x serilerinde büyük ölçüde aynıdır. Aşağıdaki örneklerde bilinçli olarak belirli bir sürüm numarası verilmemiştir; ayar isimleri bu serilerde geçerlidir. Kullandığınız dağıtımın paket yolları ve varsayılan değerleri farklılık gösterebilir, bu yüzden değişiklikten önce mevcut dosyalarınızı yedekleyin.
Önce ölçün, sonra ayarlayın
Optimizasyon, ayar değiştirmekle değil, darboğazı bulmakla başlar. Erken yapılan "tahmini" ayarlar çoğu zaman sorunu çözmez, hatta gizler.
- Süreç durumunu izleyin: PHP-FPM'in durum sayfası (
pm.status_path) etkinleştirildiğinde aktif süreçler, boştaki süreçler ve kuyruk uzunluğu görülebilir. Bu,pm.max_childrendeğerinin yeterli olup olmadığını anlamanın en doğrudan yoludur. - Yavaş istekleri kaydedin:
request_slowlog_timeoutveslowlogayarları, belirli bir süreyi aşan isteklerin yığın izini (stack trace) dosyaya yazar. Yavaşlığın FPM kaynaklı mı, uygulama kaynaklı mı olduğunu ayırt etmeye yardımcı olur. - Nginx erişim ve hata loglarını okuyun: 502/504 hatalarının sıklığı ve zamanlaması, FPM havuzunun tükendiğine dair güçlü bir sinyaldir.
Bu veriler olmadan yapılan her ayar, deneme yanılmadır.
PHP-FPM süreç yönetimi
PHP-FPM'in kalbindeki ayar pm (process manager) seçimidir. Üç mod vardır:
static: Sabit sayıda alt süreç. Bellek kullanımı öngörülebilirdir, ani yük dalgalanmalarına esneklik sunmaz. Yükün sabit ve yoğun olduğu durumlarda uygundur.dynamic: Süreç sayısı yük arttıkçapm.max_childrensınırına kadar büyür, azaldıkçapm.start_serverscivarına iner. Değişken yüklerde yaygın tercihtir.ondemand: Süreçler yalnızca istek geldiğinde oluşturulur. Boşta bellek tüketimini düşürür, ama ani trafikte süreç başlatma gecikmesi yaratabilir.
pm.max_children değerini rastgele büyütmek yaygın bir hatadır. Her alt süreç bellek tüketir; sınırı sunucunun kullanılabilir belleğine göre hesaplamak gerekir. Kaba bir yaklaşım:
pm.max_children ≈ (PHP-FPM için ayrılabilir bellek) / (tek sürecin ortalama bellek kullanımı)
Tek sürecin bellek kullanımını, çalışan bir süreçte ps veya benzeri araçlarla gözlemleyerek tahmin edebilirsiniz. Bu değeri ölçmeden belirlediğiniz sınır, ya boşa kaynak bırakır ya da bellek tükenmesine (OOM) yol açar.
dynamic modda dikkat edilecek diğer ayarlar:
pm.start_servers: Başlangıçta oluşturulacak süreç sayısı.pm.min_spare_servers/pm.max_spare_servers: Boşta tutulacak süreç aralığı.pm.max_requests: Bir alt sürecin kaç istekten sonra yeniden başlatılacağı. Uzun ömürlü süreçlerde biriken bellek sızıntılarını sınırlamaya yardımcı olur; ancak çok düşük bir değer, gereksiz süreç yeniden başlatma maliyeti getirir.
Bu parametrelerin doğru değerleri uygulamanıza ve donanımınıza bağlıdır; hazır bir sayı vermek yanıltıcı olur. Ölçüm verilerinize göre ayarlayın.
İstek zaman aşımları
Zaman aşımı ayarları, hem kaynak tüketimini hem de kullanıcı deneyimini etkiler. İki katmanda düşünmek gerekir:
- PHP-FPM tarafı:
request_terminate_timeout, tek bir isteğin en fazla ne kadar çalışabileceğini belirler. Sonsuz döngüye giren veya takılan bir betiğin süreci süresiz meşgul etmesini engeller. - Nginx tarafı:
fastcgi_read_timeout, Nginx'in FastCGI arka ucundan yanıt beklerken ne kadar süre sabredeceğini tanımlar.
Bu iki değerin tutarlı olması önemlidir. Nginx'in zaman aşımı FPM'inkinden belirgin şekilde kısaysa, FPM hâlâ çalışırken Nginx bağlantıyı keser; bu da gereksiz 502/504 hatalarına ve boşa harcanan iş gücüne yol açar. Uzun süren işleri (rapor üretimi, toplu işlem) senkron istek yerine kuyruk tabanlı bir yapıya taşımak genellikle daha sağlıklıdır.
Nginx ile FastCGI bağlantısı
Nginx'in PHP'ye istek iletmesi fastcgi_pass yönergesiyle yapılır. Yaygın iki yaklaşım vardır:
- TCP soketi:
fastcgi_pass 127.0.0.1:9000;gibi. Kurulumu ve hata ayıklaması kolaydır; ayrı makineler arası iletişimde gereklidir. - Unix soketi:
fastcgi_pass unix:/run/php/php-fpm.sock;gibi. Aynı makinede çalışırken genellikle daha düşük ek yük getirir.
Unix soketi kullanıyorsanız, soket dosyasının izinleri ve sahipliği kritik önemdedir. Nginx çalışan kullanıcısının sokete erişimi yoksa bağlantı kurulamaz ve 502 hataları görülür. Bu, en sık karşılaşılan yapılandırma sorunlarından biridir.
Statik dosyalar ve try_files
PHP isteklerini FPM'e yönlendirirken, var olan statik dosyaların (görsel, CSS, JS) doğrudan Nginx tarafından sunulması gerekir. Aksi halde her istek gereksiz yere PHP'ye gider. Bunu sağlayan tipik kalıp:
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
Burada dikkat edilmesi gereken nokta SCRIPT_FILENAME parametresidir; yanlış tanımlanırsa FPM betiği bulamaz ve "File not found" döner. Ayrıca location ~ \.php$ bloğunun, yüklenen dosyaların çalıştırılabilmesine izin vermeyecek şekilde kısıtlanması güvenlik açısından önemlidir (aşağıda değinilmiştir).
Tamponlama ve sıkıştırma
Nginx'in FastCGI yanıtlarını tamponlaması (fastcgi_buffers, fastcgi_buffer_size) ve istemciye sıkıştırılmış içerik sunması (gzip), bant genişliği ve gecikme üzerinde doğrudan etkilidir. Ancak bu ayarların doğru değerleri yanıt boyutlarına bağlıdır. Yanıtların tamponlara sığmaması durumunda Nginx bunları diske yazabilir; bu da gecikmeyi artırır. Bu yüzden sabit bir değer ezberlemek yerine, gerçek yanıt boyutlarınızı gözlemleyip ayarlamak daha doğrudur.
Güvenlik etkileri
Optimizasyon ayarları yalnızca hızla ilgili değildir; bazıları doğrudan güvenlik yüzeyini etkiler.
- Yüklenen dosyaların çalıştırılması: Kullanıcıların yüklediği dosyaların bulunduğu dizinde PHP çalıştırılmasına izin vermek, uzaktan kod çalıştırma riskini doğurur. Yükleme dizinlerinde PHP yorumlayıcısını devre dışı bırakmak yaygın bir korumadır.
fastcgi_paramsızıntıları: İstemciden gelen başlıkların doğrudan FastCGI parametresi olarak geçirilmesi, istenmeyen değerlerin uygulamaya ulaşmasına neden olabilir. Yalnızca gereken parametreleri iletin.- Durum sayfasının korunması:
pm.status_pathgibi uç noktalar süreç ve kuyruk bilgisi sızdırır. Bunları yalnızca yerel ağa veya kimlik doğrulamalı erişime açın. - Süreç kullanıcısı: PHP-FPM süreçlerinin ayrıcalıksız bir kullanıcı altında çalıştığından emin olun;
rootaltında çalıştırmak, olası bir açığın etkisini büyütür.
Yaygın hatalar
- Ölçmeden
pm.max_children'ı şişirmek: Bellek tükenmesine ve süreçlerin OOM tarafından öldürülmesine yol açar. - Nginx ve FPM zaman aşımlarını uyumsuz bırakmak: Gereksiz 502/504 hataları üretir.
- Unix soketi izinlerini göz ardı etmek: Nginx sokete erişemez, istekler başarısız olur.
- Statik dosyaları PHP üzerinden sunmak: Gereksiz FPM yükü ve daha yavaş yanıtlar.
- Yükleme dizinlerinde PHP'ye izin vermek: Güvenlik açığı.
- Ayar değişikliklerini üretimde doğrudan denemek: Yapılandırmayı önce test ortamında doğrulamak,
nginx -tile sözdizimini kontrol etmek ve değişiklikleri kademeli uygulamak gerekir.
Sonuç
PHP-FPM ve Nginx optimizasyonu, tek seferlik bir yapılandırma değil sürekli bir döngüdür: ölç, ayarla, izle, gerektiğinde geri al. Süreç yönetimi, zaman aşımları, FastCGI bağlantısı ve güvenlik ayarları birbirini etkilediği için bunları birlikte değerlendirmek gerekir. Kendi ortamınızın bellek, trafik ve yanıt profiline göre değerleri belirlemek; kopyalanan hazır ayarlardan çok daha güvenilir sonuç verir.