Nginx, statik dosyaları (HTML, görsel, CSS, JavaScript) son derece hızlı sunar; ancak Apache'nin aksine PHP kodunu kendi başına çalıştıramaz. Bir PHP dosyası istendiğinde Nginx bu isteği kendisi işlemek yerine, PHP kodunu yürütecek ayrı bir servise devretmek zorundadır. İşte bu servis PHP-FPM (FastCGI Process Manager) olup, Nginx ile arasındaki köprü FastCGI protokolüyle kurulur. Bu ikilinin doğru yapılandırılması, bir sitenin ister saniyede beş istek ister beş yüz istek alsın kararlı çalışmasının temelidir.
Bu rehberde Nginx'in location ~ \.php$ bloğuyla PHP isteklerini fastcgi_pass üzerinden PHP-FPM'e nasıl ilettiğini, Unix soketi ile TCP arasındaki farkı, www.conf havuz dosyasında pm modunu ve pm.max_children değerini nasıl hesaplayacağınızı, timeout ile buffer ayarlarını ve OPcache'in performansa etkisini adım adım ele alacağız. Ardından WordPress ve Laravel için doğrudan uygulanabilir öneriler vererek, "internetten bulduğum ayarı yapıştırdım" aşamasından kendi sunucunuz için bilinçli değerler üretebildiğiniz aşamaya geçmenizi hedefliyoruz. Nginx henüz kurulu değilse önce Ubuntu'da Nginx kurulumu rehberimizi tamamlamanızı öneririz.
Nginx ile PHP-FPM Nasıl Konuşur?#
Bir ziyaretçi https://siteniz.com/index.php adresini istediğinde olayların sırası şöyle ilerler. Nginx isteği alır ve dosya uzantısına bakar; .php ile bittiğini görünce bunu kendisi çalıştırmaya kalkmaz, FastCGI protokolüyle PHP-FPM servisine iletir. PHP-FPM havuzundaki boş bir işçi (worker) süreci kodu yürütür, veritabanı sorgularını yapar, sonucu HTML olarak üretir ve Nginx'e geri gönderir. Nginx de bu çıktıyı ziyaretçinin tarayıcısına iletir. Statik bir dosya (örneğin bir .jpg) istendiğinde ise Nginx PHP-FPM'e hiç uğramadan dosyayı doğrudan diskten okuyup sunar; bu ayrım, Nginx'in yüksek verimliliğinin sırrıdır.
Bu mimarinin en büyük avantajı, web sunucusu ile PHP yorumlayıcısının birbirinden bağımsız olmasıdır. Apache'nin klasik mod_php modelinde PHP her Apache sürecinin içine gömülüdür; statik bir görsel sunmak için açılan süreç bile PHP'nin tüm bellek yükünü taşır. Nginx + PHP-FPM modelinde ise Nginx yalnızca hafif bağlantı yönetimiyle uğraşır, PHP yükü tamamen ayrı bir havuzda toplanır. Böylece iki tarafı ayrı ayrı ölçekleyebilir, PHP çökse bile Nginx'in ayakta kalıp statik içeriği sunmaya devam etmesini sağlayabilirsiniz.
FastCGI bağlantısının kurulacağı adresi Nginx tarafında fastcgi_pass, PHP-FPM tarafında ise havuzun listen direktifi belirler. Bu iki değerin birebir aynı olması zorunludur; en sık karşılaşılan "502 Bad Gateway" hatalarının önemli bir kısmı, Nginx'in bir soket adresine, PHP-FPM'in ise başka bir adrese ayarlanmış olmasından kaynaklanır.
location ~ .php$ Bloğu ve fastcgi_pass Ayarı#
Nginx'e "PHP dosyalarını PHP-FPM'e gönder" talimatını veren yapı, site yapılandırmanızdaki location ~ \.php$ bloğudur. Bu regex, .php ile biten tüm istekleri yakalar. Ubuntu/Debian üzerinde tipik bir sunucu bloğu şöyle görünür:
server {
listen 80;
server_name siteniz.com www.siteniz.com;
root /var/www/siteniz.com/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
Buradaki her satırın bir görevi vardır. try_files direktifi, gerçek bir dosya yoksa isteği index.php'ye yönlendirir; WordPress, Laravel ve diğer "front controller" mimarili uygulamaların temiz URL'lerinin çalışması için şarttır. include snippets/fastcgi-php.conf; satırı, Nginx'in paketle birlikte gelen ve SCRIPT_FILENAME, PATH_INFO gibi standart FastCGI parametrelerini ayarlayan hazır bir dosyayı içeri alır — bunları elle yazmaktan kurtulursunuz. fastcgi_pass ise isteğin gönderileceği PHP-FPM adresidir.
Güvenlik açısından kritik bir nokta, location ~ \.php$ bloğunun kör biçimde her .php uzantısını çalıştırmasının bir risk oluşturabilmesidir. Kullanıcıların dosya yükleyebildiği dizinlerde (örneğin WordPress'in wp-content/uploads klasörü) PHP çalıştırmayı kapatmak, yüklenen kötü niyetli bir dosyanın sunucuda kod olarak çalışmasını engeller:
location ~* /uploads/.*\.php$ {
deny all;
}
Yapılandırmayı değiştirdikten sonra mutlaka sözdizimini test edip Nginx'i yeniden yükleyin. reload, açık bağlantıları koparmadan yeni ayarları uygular:
sudo nginx -t # sözdizimi testi
sudo systemctl reload nginx # kesintisiz yeniden yükle
Sunucuda birden fazla PHP sürümü barındırıyorsanız, fastcgi_pass satırındaki soket yolunu değiştirerek farklı siteleri farklı PHP sürümlerine yönlendirebilirsiniz; bu esnekliğin ayrıntıları için PHP sürüm yönetimi rehberimize göz atabilirsiniz.
Unix Soketi mi TCP mi? fastcgi_pass İçin Doğru Seçim#
fastcgi_pass iki türlü adres kabul eder ve aralarındaki fark performansı doğrudan etkiler. Birincisi Unix soketi (unix:/run/php/php8.3-fpm.sock), ikincisi TCP soketi (127.0.0.1:9000). İkisi de aynı işi yapar ama farklı senaryolarda avantajlıdır.
Unix soketi, Nginx ile PHP-FPM'in aynı sunucuda olduğu durumlarda daha hızlıdır çünkü veri, TCP/IP yığınının katmanlarına hiç uğramadan doğrudan çekirdek üzerinden akar. Yerel bir kurulumda neredeyse her zaman tercih edilmesi gereken seçenek budur. Buna karşılık TCP soketi, PHP-FPM'in başka bir sunucuda çalıştığı (örneğin PHP işçilerini ayrı bir makineye taşıdığınız yatay ölçekleme senaryolarında) tek geçerli yöntemdir, çünkü Unix soketleri ağ üzerinden erişilemez.
| Kriter | Unix Soketi | TCP Soketi |
|---|---|---|
| Adres örneği | unix:/run/php/php8.3-fpm.sock | 127.0.0.1:9000 |
| Hız (aynı sunucu) | Biraz daha hızlı (yığın atlanır) | Az miktarda ek yük |
| Farklı sunucu desteği | Yok | Var |
| İzin yönetimi | Dosya izinleri gerekir | Firewall/port yönetimi |
| Tipik senaryo | Tek sunuculu klasik kurulum | Dağıtık / konteyner mimarisi |
Unix soketi kullanırken en sık takılınan nokta dosya izinleridir. Nginx www-data kullanıcısıyla çalışıyorsa, PHP-FPM havuzunun oluşturduğu soket dosyasını da bu kullanıcının okuyup yazabilmesi gerekir. Bu, havuz dosyasındaki şu üç satırla ayarlanır:
listen = /run/php/php8.3-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
Bu ayar eksik veya yanlışsa, Nginx logunda connect() to unix:/run/php/... failed (13: Permission denied) hatasını görürsünüz; çözüm neredeyse her zaman listen.owner/listen.group değerlerini Nginx'in çalıştığı kullanıcıyla eşitlemektir. Tek sunuculu klasik bir kurulumda tereddüt etmeden Unix soketini seçin; TCP'ye yalnızca gerçekten ayrı makineler devreye girdiğinde geçin.
PHP-FPM Havuzu (www.conf) Yapılandırması#
PHP-FPM, işçi süreçlerini havuzlar (pool) halinde yönetir. Her havuzun kendi kullanıcısı, kendi soketi ve kendi kaynak sınırları vardır. Varsayılan havuz, sürüme göre /etc/php/8.3/fpm/pool.d/www.conf gibi bir dosyada tanımlanır. Bir havuz dosyasının iskeleti şöyledir:
[www]
user = www-data
group = www-data
listen = /run/php/php8.3-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
pm = dynamic
pm.max_children = 20
pm.start_servers = 4
pm.min_spare_servers = 4
pm.max_spare_servers = 12
pm.max_requests = 500
Aynı sunucuda birden çok site barındırıyorsanız, her sitenin ayrı bir havuz kullanması en sağlıklı yaklaşımdır. Bunun iki büyük faydası vardır. Birincisi güvenlik yalıtımı: her havuzu ilgili sitenin kendi Linux kullanıcısıyla çalıştırırsanız (user = site1), bir sitenin PHP kodu diğerinin dosyalarına erişemez. İkincisi kaynak yalıtımı: bir sitenin ani trafik patlaması tüm işçileri tüketip diğer sitelerin işçilerini açlığa mahkûm etmez. Yeni bir havuz için pool.d/ altına site1.conf gibi bir dosya oluşturup [www] yerine [site1] başlığı, farklı bir user ve farklı bir listen soketi verirsiniz:
[site1]
user = site1
group = site1
listen = /run/php/php8.3-fpm-site1.sock
listen.owner = www-data
listen.group = www-data
pm = ondemand
pm.max_children = 8
pm.process_idle_timeout = 15s
pm.max_requests = 500
Ardından ilgili Nginx sunucu bloğunun fastcgi_pass değerini bu yeni sokete (unix:/run/php/php8.3-fpm-site1.sock) çevirirsiniz. Bu yapı, birçok küçük siteyi tek bir VDS sunucu üzerinde düzenli ve yalıtılmış biçimde toplamanın standart yoludur.
pm Modları ve pm.max_children Hesabı#
Havuz ayarlarının kalbi pm (process manager) direktifidir; işçilerin nasıl açılıp kapatılacağını belirler. Üç mod vardır:
- static: Başlangıçta tam olarak
pm.max_childrenkadar işçi açılır ve hep açık kalır. En öngörülebilir yanıt süresini verir ama boşta bile RAM'i sürekli meşgul eder. Tek, yoğun ve sürekli trafikli sitelerde idealdir. - dynamic:
pm.start_serverskadar işçiyle başlar; trafik arttıkçapm.max_childrensınırına dek yeni işçi açar, düştükçe fazlaları kapatır ve her an bir miktar yedek işçi hazır bekletir. En dengeli ve en yaygın moddur; kararsız kaldığınızda bununla başlayın. - ondemand: Başta hiç işçi açılmaz; ilk istekle işçi oluşturulur,
pm.process_idle_timeoutboyunca istek gelmezse kapatılır. En düşük bellek ayak izini verir, düşük trafikli veya çok sayıda sitenin bulunduğu sunucular için idealdir.
En kritik ayar pm.max_children, yani havuzun açabileceği maksimum işçi sayısıdır. Çok düşük olursa trafik gelince kapasite tükenir ve loglarda server reached pm.max_children setting uyarısıyla birlikte 502 hataları başlar; çok yüksek olursa işçiler tüm RAM'i tüketip sunucuyu takas alanına (swap) iter. Değeri tahminle değil, iki sayıyı ölçerek belirlersiniz: PHP'ye ayırabileceğiniz RAM ve bir işçinin ortalama tükettiği RAM.
Önce bir işçinin gerçek bellek kullanımını, sunucu trafik alırken ölçün:
ps --no-headers -o rss -C php-fpm8.3 | awk '{ s += $1; n++ } END { printf "Ortalama: %d MB\n", s/n/1024 }'
Diyelim çıktı ortalama 60 MB dedi. Sonra PHP'ye ne kadar RAM ayırabileceğinizi belirleyin — işletim sistemi, MySQL/MariaDB ve önbellek de paylarını ister. Veritabanı aynı sunucudaysa RAM'in yaklaşık yarısını PHP-FPM'e ayırmak makul bir başlangıçtır. Formül basittir:
pm.max_children = PHP'ye ayrılan RAM / işçi başına ortalama RAM
4 GB RAM'li bir sunucu için pratik hesap:
Toplam RAM: 4096 MB
İşletim sistemi + MySQL: -2048 MB
Nginx + tampon: -512 MB
---------------------------------------
PHP-FPM'e kalan: 1536 MB
İşçi başına ortalama: 60 MB
pm.max_children = 1536 / 60 ≈ 25
dynamic modda diğer değerler için pratik bir dağılım şudur: start_servers ve min_spare_servers toplam kapasitenin yaklaşık dörtte biri, max_spare_servers ise dörtte üçü olsun. pm.max_requests = 500 ayarı ise her işçiyi 500 istekten sonra yeniden başlatarak, kötü yazılmış eklentilerin biriktirdiği bellek sızıntılarını temizler; bunu 0 (sınırsız) bırakmayın. Farklı sitelere farklı PHP sürümü atamak ve havuzları sürüm bazında yönetmek için PHP sürüm yönetimi rehberimiz konuyu tamamlayıcı biçimde işler.
Timeout, Buffer ve OPcache Ayarları#
Havuz kapasitesini doğru ayarlasanız bile, uzun süren istekler ve yetersiz tamponlar performansı bozar. İki ayrı katmanda ince ayar gerekir: Nginx ile PHP-FPM arasındaki iletişim (timeout ve buffer) ve PHP'nin kendi yürütme hızı (OPcache).
Nginx tarafında timeout değerleri, bir sayfanın ne kadar süre çalışabileceğini sınırlar. fastcgi_read_timeout, PHP-FPM'in yanıt vermesi için Nginx'in beklediği süredir; bunu aşan istekler 504 Gateway Timeout ile sonuçlanır. Ağır rapor sorguları veya toplu işlemler yapan sayfalarınız varsa bu değeri artırmanız gerekebilir, ama körlemesine uzatmak yerine önce yavaşlığın kaynağını bulmak esastır:
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_read_timeout 60s;
fastcgi_connect_timeout 5s;
fastcgi_buffer_size 32k;
fastcgi_buffers 16 16k;
fastcgi_busy_buffers_size 64k;
}
Buffer ayarları, PHP-FPM'den gelen yanıtın Nginx belleğinde ne kadarının tutulacağını belirler. Tampon çok küçükse, Nginx yanıtı geçici olarak diske yazmak zorunda kalır ve loglarda a client request body is buffered to a temporary file benzeri satırlar belirir; bu, gereksiz disk I/O demektir. Yukarıdaki değerler, çoğu dinamik sayfanın çıktısını rahatça belleğe sığdırarak diske taşmayı önler. Ayrıca PHP'nin max_execution_time değeriyle Nginx'in fastcgi_read_timeout değerinin uyumlu olmasına dikkat edin — PHP 30 saniyede süreci öldürürken Nginx 300 saniye beklerse, ziyaretçiye yine de bir hata döner.
Performans için tek başına en etkili ayar ise OPcache'tir. OPcache, PHP kodunu her istekte yeniden derlemek yerine, derlenmiş bytecode'u bellekte tutarak tekrar kullanır; bu, tipik bir PHP uygulamasında yürütme süresini gözle görülür biçimde düşürür. php.ini içinde şu değerlerle etkinleştirilir:
opcache.enable = 1
opcache.memory_consumption = 192
opcache.interned_strings_buffer = 16
opcache.max_accelerated_files = 20000
opcache.revalidate_freq = 60
opcache.validate_timestamps = 1
opcache.memory_consumption OPcache'e ayrılan bellek (MB); büyük uygulamalarda 256'ya çıkarabilirsiniz. opcache.max_accelerated_files önbelleğe alınacak dosya sayısıdır — WordPress + WooCommerce gibi binlerce dosyalı projelerde varsayılan yetersiz kalır, 20000 güvenli bir değerdir. Üretim sunucusunda opcache.validate_timestamps = 0 yaparak PHP'nin dosya değişikliğini her istekte kontrol etmesini kapatabilirsiniz; bu ekstra hız kazandırır ama kod her güncellemede FPM'i reload etmeniz gerektiğini unutmayın. Bir OPcache değişikliğinin devreye girmesi için PHP-FPM'i yeniden yükleyin:
sudo systemctl reload php8.3-fpm
WordPress ve Laravel için Pratik Öneriler#
Genel prensipler her uygulamada geçerli olsa da, iki popüler platformun kendine has ihtiyaçları vardır.
WordPress için başlangıç noktası, kalıcı bağlantıları ve gerçek dosya olmayan URL'leri düzgün ele alan bir try_files yapısıdır. Ayrıca WordPress, wp-cron.php'yi her sayfa yüklemesinde tetiklediği için gizli bir yük oluşturur; bunu kapatıp gerçek bir sistem cron'una taşımak, işçilerin gereksiz meşgul olmasını önler:
location / {
try_files $uri $uri/ /index.php?$args;
}
# Yükleme dizininde PHP çalıştırmayı engelle (güvenlik)
location ~* /wp-content/uploads/.*\.php$ {
deny all;
}
# wp-config.php içine:
# define('DISABLE_WP_CRON', true);
WordPress'te işçiler görece ağır (65-100 MB) olduğundan pm.max_children hesabında bu değeri gerçekçi tutun; ayrıca Redis nesne önbelleği ve bir tam sayfa önbelleği, PHP-FPM'e ulaşan istek sayısını ciddi biçimde azaltarak aynı havuzla çok daha fazla trafiği karşılamanızı sağlar. FPM ayarları hazır gelen WordPress hosting paketlerinde bu optimizasyonların çoğu kutudan çıktığı gibi ayarlıdır.
Laravel için en kritik ayar, dizin yapısıdır: Nginx root değeri projenin public/ klasörünü göstermelidir, kök dizinini değil. Aksi halde .env dosyanız ve tüm uygulama kaynağı web'den erişilebilir hale gelir — ciddi bir güvenlik açığı. Tipik bir Laravel sunucu bloğu şöyledir:
server {
server_name uygulama.com;
root /var/www/uygulama/public;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
Laravel'de üretim performansı için php artisan config:cache, route:cache ve view:cache komutlarını çalıştırmak, OPcache ile birlikte yürütme süresini belirgin biçimde kısaltır. Uzun süren işleri (e-posta gönderimi, rapor üretimi) HTTP isteği içinde değil, kuyruk işçileriyle (queue worker) arka planda çalıştırmak da FPM işçilerinin hızlıca serbest kalmasını sağlar. Her iki platformda da canlıya almadan önce mutlaka bir yedek alın; hatalı bir havuz veya OPcache ayarı siteyi erişilemez bırakabilir.
Yapılandırmayı Test Etme ve İzleme#
Ayarları bir kez yapıp unutmak yerine, gerçek yükü izleyip zamanla ince ayar yapmak gerekir. Değişikliklerden sonra her iki servisin de yapılandırmasını doğrulayın ve kesintisiz yeniden yükleyin:
sudo nginx -t # Nginx sözdizimi
sudo php-fpm8.3 -t # PHP-FPM sözdizimi
sudo systemctl reload nginx
sudo systemctl reload php8.3-fpm
PHP-FPM'in kendi status sayfası, havuzun gerçek yükünü izlemek için yerleşik bir araçtır. Havuz dosyasında etkinleştirin:
pm.status_path = /fpm-status
Ardından Nginx'te bu yolu yalnızca yerelden erişilebilir biçimde açın ve durumu çekin:
location = /fpm-status {
access_log off;
allow 127.0.0.1;
deny all;
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
curl -s "http://127.0.0.1/fpm-status?full"
Çıktıdaki en önemli satırlar şunlardır: active processes (o an meşgul işçi), idle processes (boş işçi) ve max children reached (havuzun kaç kez tamamen dolduğu). Eğer max children reached sıfırdan büyükse havuz yetersizdir; RAM izin veriyorsa pm.max_children'ı yükseltin. Tam tersine, meşgul işçi sayısı hiçbir zaman tavanın yarısına yaklaşmıyorsa gereksiz RAM ayırıyorsunuz demektir ve değeri düşürüp belleği veritabanı önbelleğine verebilirsiniz. Yavaş sayfaları yakalamak için de slow log çok değerlidir:
slowlog = /var/log/php8.3-fpm-slow.log
request_slowlog_timeout = 5s
Bu ayar, 5 saniyeden uzun süren istekleri PHP çağrı yığınıyla birlikte kaydeder; "sitem ara sıra yavaşlıyor" gibi belirsiz bir şikayeti, "şu fonksiyon her seferinde 8 saniye sürüyor" gibi somut bir bulguya çevirir. Sunucuya gelen zararlı veya bot trafiği FPM işçilerini boş yere meşgul ediyorsa, önüne bir WAF ya da DDoS koruması koymak, bu istekleri PHP'ye hiç ulaşmadan elemenin en etkili yoludur. Tüm bu izleme ve ayar döngüsüyle uğraşmak istemiyorsanız, yönetimini bize bırakabileceğiniz bir sunucu yönetimi paketi bu yükü üzerinizden alır.
Sıkça Sorulan Sorular#
Nginx neden PHP kodunu kendisi çalıştırmıyor?#
Nginx, tasarım gereği yalnızca statik dosyaları sunmak ve bağlantıları yönetmek üzerine kuruludur; içinde PHP yorumlayıcısı barındırmaz. Apache'nin mod_php modelinden farklı olarak Nginx, dinamik dil işlemeyi ayrı bir servise devreder. Bu nedenle PHP kodunu çalıştırmak için PHP-FPM gibi bir FastCGI işlemcisine ihtiyaç duyar ve isteği fastcgi_pass üzerinden ona iletir. Bu ayrım aslında bir avantajdır, çünkü web sunucusu ile PHP'yi bağımsız ölçekleyebilir ve statik içeriği PHP yükü olmadan çok daha verimli sunabilirsiniz.
fastcgi_pass için Unix soketi mi TCP mi kullanmalıyım?#
Nginx ve PHP-FPM aynı sunucuda çalışıyorsa Unix soketini (unix:/run/php/...sock) tercih edin, çünkü veri TCP/IP yığınına uğramadan doğrudan çekirdek üzerinden aktığı için biraz daha hızlıdır. TCP soketini (127.0.0.1:9000) yalnızca PHP-FPM'i ayrı bir sunucuda çalıştırdığınız veya konteyner tabanlı bir mimari kullandığınız durumlarda kullanın, zira Unix soketleri ağ üzerinden erişilemez. Klasik tek sunuculu kurulumların neredeyse tamamında doğru seçim Unix soketidir.
502 Bad Gateway hatası neden oluşur ve nasıl çözülür?#
502 hatası genel olarak Nginx'in PHP-FPM'e bağlanamadığı anlamına gelir ve birkaç tipik nedeni vardır. En yaygını, Nginx'teki fastcgi_pass adresiyle PHP-FPM'in listen adresinin uyuşmaması veya soket dosyasının izinlerinin yanlış olmasıdır; bir diğeri havuzun pm.max_children sınırına dayanıp yeni bağlantı kabul edememesidir. Çözmek için önce iki adresin birebir aynı olduğunu doğrulayın, ardından Nginx ve PHP-FPM error loglarına bakın. Logda "server reached pm.max_children setting" satırını görüyorsanız sorun net biçimde havuz kapasitesidir ve max_children değerini gözden geçirmeniz gerekir.
pm.max_children değerini nasıl belirlemeliyim?#
Bu değeri tahminle değil, ölçümle bulmalısınız. Önce sunucu trafik alırken ps komutuyla çalışan FPM işçilerinin ortalama bellek kullanımını ölçün; sade sitelerde bu 30-40 MB, WordPress artı WooCommerce gibi ağır kurulumlarda 80-120 MB olabilir. Sonra PHP'ye ayırabileceğiniz RAM'i (işletim sistemi, veritabanı ve önbellek paylarını çıkardıktan sonra kalanı) bu değere bölün. Örneğin PHP'ye 1500 MB kalıyorsa ve işçi başına 60 MB tüketiliyorsa, pm.max_children için 25 civarı mantıklı bir tavan olur. Değeri RAM sınırının üstüne çıkarmak kapasiteyi artırmaz, aksine sunucuyu swap'a iterek her şeyi yavaşlatır.
OPcache'i açmak gerçekten fark yaratır mı?#
Evet, OPcache tek başına yapabileceğiniz en etkili performans iyileştirmelerinden biridir. Normalde PHP her istekte kaynak kodunu yeniden derler; OPcache ise derlenmiş bytecode'u bellekte tutup tekrar kullanarak bu derleme yükünü ortadan kaldırır ve tipik bir uygulamada yürütme süresini gözle görülür biçimde düşürür. Üretim ortamında opcache.validate_timestamps = 0 ayarıyla ekstra hız kazanabilirsiniz, ancak bu durumda her kod güncellemesinden sonra PHP-FPM'i reload etmeniz gerektiğini unutmayın.
Havuz ayarını değiştirdikten sonra siteyi yeniden başlatmalı mıyım?#
Sitenin kendisini değil, yalnızca PHP-FPM servisini yeniden yüklemeniz yeterlidir ve bunu kesintisiz yapabilirsiniz. Önce php-fpm8.3 -t ile yapılandırmanın sözdizimini doğrulayın, ardından systemctl reload php8.3-fpm komutuyla ayarları uygulayın. reload, restart'tan farklı olarak açık istekleri koparmadan yeni ayarları devreye alır. Nginx tarafında bir değişiklik yaptıysanız aynı şekilde nginx -t ile test edip systemctl reload nginx çalıştırın; kritik bir değişiklikten önce yedek almayı ihmal etmeyin.
Kapanış#
Nginx ve PHP-FPM ikilisi, doğru kurulduğunda hem statik içeriği yıldırım hızıyla sunan hem de dinamik PHP yükünü verimli bir işçi havuzunda yöneten güçlü bir mimaridir. İşin özü birkaç noktada toplanır: location ~ \.php$ bloğuyla PHP isteklerini doğru sokete iletmek, aynı sunucuda Unix soketini tercih etmek, pm modunu siteye göre seçip pm.max_children'ı tahminle değil ölçümle hesaplamak, timeout ile buffer değerlerini uyumlu tutmak ve OPcache'i etkinleştirmek. Bu ayarları FPM status ve slow log gibi araçlarla izleyip zamanla ince ayar yaptığınızda, siteniz hem ani trafik dalgalarına dayanıklı hem de bellek açısından tutumlu olur.
Bu yapılandırmalarla tek tek uğraşmak yerine altyapının sizin için optimize edilmesini tercih ediyorsanız Clou.TR paketleri yardımcı olabilir. Yüksek trafikli projeler için kaynak garantili bir VDS sunucu, tam kontrol istediğiniz kurulumlar için bir sanal sunucu, günlük yükünüz için ise Nginx + PHP-FPM ayarları hazır gelen WordPress hosting ve web hosting paketlerimizi inceleyebilir; kurulumu ve bakımı uzman ekibimize devretmek isterseniz sunucu yönetimi hizmetimizden yararlanabilirsiniz. Konunun temelini pekiştirmek için de Ubuntu'da Nginx kurulumu ve PHP sürüm yönetimi rehberlerimiz iyi birer başlangıç noktasıdır.