Tarayıcı dönüyor, birkaç saniye sonra beyaz sayfa veya 504 Gateway Timeout mesajı geliyor. PHP logunda hiçbir hata yok, sunucu CPU'su da düşük, ancak istek hiçbir zaman tamamlanmıyor. Bu durum neredeyse her zaman tek bir anlama gelir: istek zincirindeki halkalardan biri, yanıt hazır olmadan önce sabırsızlanıp bağlantıyı kapatmıştır. Sizin işiniz o halkayı bulmaktır, körü körüne tüm timeout sürelerini yükseltmek değil.
504 hatası hangi katmandan gelir
Kullanıcının isteği, sizin kodunuza ulaşmadan önce birkaç aracıdan geçer. Her birinin kendi bağımsız timeout süresi vardır ve hangisi daha erken biterse aynı mesajı üretir:
- Kullanıcının tarayıcısı (dahili timeout, genellikle uzun)
- Cloudflare gibi ön CDN veya proxy
- Reverse proxy rolünü oynayan ön web sunucusu (Nginx veya Apache)
- PHP-FPM gibi PHP işlem yöneticisi
- Uygulama kodu ve sonunda veritabanı veya harici bir API
Kilit nokta şudur: 504 mesajı yalnızca aracı katmanlardan gelir. Eğer PHP'nin kendisi ölürse veya belleği tükenirse, 504 değil 500 veya 502 hatası görürsünüz. Yani 504 görmek, kodunuzun muhtemelen hayatta olduğu, sadece geç yanıt verdiği anlamına gelir.
504'ün 502 ve 524'ten farkı
502, aracının üst sunucuya bağlanamadığı anlamına gelir; bağlantı kurulamadı. 504 ise bağlantının kurulduğu ancak yanıtın izin verilen süre içinde gelmediği anlamına gelir. Cloudflare tam da bu durum için 524 sayısını kullanır ve varsayılanı 100 saniyedir. Cloudflare logunda 524 sayısı görüyorsanız ve Nginx logunda isteğe dair hiçbir iz yoksa, bu istek sunucunuza hiç ulaşmamış ya da yanıt 100 saniyeden önce hazır olmamış demektir. Bu ayrım, sorun giderme işinin yarısıdır.
Hangi timeout daha erken biter
Gerçek sıralamayı loglardan çıkarmanız gerekir, ancak yaygın varsayılan sıralama şöyledir:
| Katman | Parametre | Yaygın varsayılan değer |
|---|---|---|
| Cloudflare | Proxy timeout | 100 saniye |
| Nginx (proxy) | proxy_read_timeout | 60 saniye |
| PHP-FPM | request_terminate_timeout | Genellikle sınırsız veya 30 saniye |
| PHP | max_execution_time | 30 saniye |
| MySQL | wait_timeout | 28800 saniye |
Bu tabloya göre ilk öldüren şey PHP'dir: 30. saniyede betiği öldürür ve eğer temiz bir çıktı vermezse, Nginx 60 saniyeye kadar bekler ve sonra 504 verir. Yani kullanıcı, kökeni 30. saniyede olan bir hatayı görmek için 60 saniye bekler. Burada şu hata yapılır: max_execution_time 300'e çıkarılır ama proxy_read_timeout değiştirilmez. Sonuç, hatanın değişmemesi, sadece daha geç gelmesi ve PHP logunun artık orada olmayan Maximum execution time of 30 seconds exceeded ile dolmasıdır.
Log ile darboğaz halkasını bulmak
Herhangi bir değişiklik yapmadan önce, isteğin nerede takıldığını anlamalısınız. Üç yere aynı anda bakın:
tail -f /var/log/nginx/error.log
tail -f /var/log/php*-fpm.log
tail -f /var/log/nginx/access.log | grep " 504 "
Nginx erişim loguna $request_time ve $upstream_response_time alanlarını ekleyin. Eğer upstream_response_time sizin timeout sürenize yakın bir sayıysa, sorun PHP veya veritabanındadır. Eğer tire veya sıfırsa, istek upstream'e hiç ulaşmamıştır ve sorun Nginx'in kendisinde veya ağdadır.
log_format timed '$remote_addr $request_time $upstream_response_time "$request" $status';
En yavaş istekleri görmek için logu zamana göre sıralayın. Basit bir betik yeterlidir, ancak elle zaman harcamak istemiyorsanız, ücretsiz web yöneticisi araçları sunucu yanıtını ve başlıkları hızlıca kontrol etmek için işi kısaltır.
Sorun veritabanında olduğunda
WordPress sitelerinde 504'ün en yaygın kökeni, indekssiz bir sorgudur. MySQL'de slow query log'u etkinleştirerek hangi sorgunun bir saniyeden uzun sürdüğünü öğrenin:
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;
Rows_examined değeri birkaç yüz binin üzerinde olan bir sorgu görürseniz, sorun timeout değildir; sorun indekstir ve hiçbir timeout bunu çözmez. Burada şu hata yapılır: indeks eklemek yerine timeout yükseltilir ve site herkes için daha yavaş hale gelir, çünkü her yavaş istek artık kaynakları daha fazla meşgul eder.
Timeout sürelerini doğru sırayla ayarlamak
Kural basittir: her katmanın timeout süresi iç katmandan daha büyük olmalıdır, aksi halde dış katman daha erken keser ve yanıltıcı bir mesaj verir. Mantıklı bir sıralama:
- PHP:
max_execution_time = 120 - PHP-FPM:
request_terminate_timeout = 130 - Nginx:
proxy_read_timeout 150s;vefastcgi_read_timeout 150s; - Cloudflare: üst planlarda artırılabilir, ancak 100 saniyenin altında tutmak daha mantıklıdır
Bu işin maliyetini de söyleyelim: eklenen her timeout saniyesi, bir PHP-FPM işlemini daha fazla meşgul eder. Eğer pm.max_children değerini de yükseltmezseniz, birkaç yavaş istek kuyruğu doldurmaya yeter ve site herkese 504 verir. Yeterli kapasite olmadan uzun timeout, sorunu bir kullanıcıdan tüm kullanıcılara taşır.
Yüksek trafikli siteler için önerilen yol
Trafik yüksekse, timeout süresini uzatmak yerine ağır işi istek yolundan çıkarın. Ağır raporları cron ve kuyruk (queue) ile çalıştırın ve sonucu veritabanına veya önbelleğe koyun. Böylece kullanıcı sayfası her zaman hızlı yanıt verir ve timeout hiçbir zaman yürütme aşamasına ulaşmaz. Daha fazla kaynağa ihtiyaç duyan siteler için, özel sunucu bu parametreleri daha hassas ayarlama imkânı verir, ancak paylaşımlı hostingde genellikle bu değerlerin yalnızca bir kısmı sizin erişiminizdedir.
Hiçbir timeout'un sorunu çözmediği durumlar
Pratikte timeout ayarının işe yaramadığı üç durumu çok gördüm:
- Kendisi timeout'u olmayan yavaş bir harici API. Burada sunucuda değil, kodda timeout koymalısınız.
- Asla bitmeyen sonsuz bir döngü. Timeout onu yalnızca öldürür, ancak köken yerinde kalır.
- Sunucu ile harici veritabanı arasındaki ağ sorunu.
mtrveyatracerouteile kontrol edin.
İlk durumda, kodda kısa timeout en iyi çözümdür: eğer API 5 saniyede yanıt vermezse, önbelleğe alınmış değeri gösterin. Kullanıcı biraz eski bir sayfa görür ama hata sayfası görmez.
Sık sorulan sorular
504 hatası neden yalnızca bazı kullanıcılarda görülür?
Çünkü genellikle ağ yoluna veya önbelleğe bağlıdır. CDN önbelleğinden sunulan kullanıcı sunucunuza hiç ulaşmaz ve hata görmez. İsteği cache miss alan kullanıcı tam yolu kat eder ve o anda sunucu yoğunsa 504 alır. Bu yüzden logu yalnızca toplam hata sayısına göre değil, IP ve istek yoluna göre filtrelemelisiniz.
max_execution_time değerini yükseltmek 504 hatasını çözer mi?
Yalnızca PHP gerçekten diğer katmanlardan daha erken kesiliyorsa ve dış katmanlar da aynı oranda daha büyük timeout süresine sahipse. Eğer Cloudflare 100 saniyede kesiyorsa, max_execution_time değerini 300'e çıkarmak yalnızca işlemin boşuna devam etmesine neden olur ve kullanıcı yine hata görür. Önce timeout sıralamasını düzeltin, sonra değerleri yükseltin.
Sorunun sunucudan mı yoksa site kodundan mı olduğunu nasıl anlarım?
İçeriği <?php echo "ok"; ?> olan basit bir PHP dosyası oluşturun ve doğrudan istek gönderin. Eğer bu dosya hızlı yanıt veriyor ama ana sayfa 504 veriyorsa, sorun kodda veya veritabanındadır. Eğer aynı basit dosya da yavaşsa, sorun web sunucusunda, PHP-FPM'de veya sunucu kaynaklarındadır. Bu iki dakikalık test, sorun giderme yönünü belirler.
DNS'in 504 hatasındaki rolü nedir?
Genellikle hiç yoktur. 504, TCP bağlantısının kurulduğu ve yanıtın gelmediği anlamına gelir; eğer DNS sorunlu olsaydı, 504 değil bağlantı hatası görürdünüz. Tek istisna, kaydınızın kendisi yavaş olan bir proxy veya aracı hizmete işaret etmesidir. Kayıtların ve yolun doğru olduğundan emin olmak için DNS ve ağ kontrolü yapın ve sonra timeout sürelerine geçin.
Sonraki adım bellidir: Nginx logunu $upstream_response_time ile etkinleştirin, hatayı bir kez yeniden üretin ve sayının nerede durduğunu görün. O sayı, size suçlu katmanı gösterecektir. Bu incelemeden sonra bu parametreleri size sunacak bir hostinge ihtiyaç duyarsanız, ServerNet Linux hosting bu imkânı verir; ancak kökeni bulana kadar hosting değiştirmek yalnızca hatayı başka yere taşır.
Yorumlar 0
Henüz yorum yok — ilk siz olun!