"Bad gateway" diyen aslında kim
Durum kodunu uygulamanızın kendisi değil, önünde duran her ne varsa o üretir. Bir istek ziyaretçi → CDN edge'i → origin sunucunuz → (çoğu zaman) uygulama sunucunuz yolunu izler ve bir sonrakine proxy yapan her durak, kendinden sonraki durak hakkında 502 üretebilir. Bu önemlidir, çünkü baktığınız sayfayı proxy yazmıştır: uygulamanız bir şekilde cevap vermiş olsaydı, hatayla bile olsa, karşınızda kendi 500 sayfanız olurdu.
Yani 502, başarısız olmuş bir konuşma hakkında bir ifadedir ve işe yarar soru hep aynıdır: hangi iki makine konuşuyordu ve aralarında ne ters gitti?
502 ile 504: herkesin atladığı ayrım
Bu ikisi blog yazılarında birbirinin yerine kullanılıyor; kullanılmamalı.
504 Gateway Timeout, proxy'nin sorunsuz bağlandığını ve sonra beklediğini anlatır. Origin'iniz isteği kabul etti ama zaman aşımı süresi içinde cevabını bitirmedi. Alışılmış sebepler: yavaş bir veritabanı sorgusu, kendi zaman aşımı olmayan bir dış API çağrısı ya da dolduğu için kuyruğa alan bir süreç havuzu.
502 Bad Gateway, beklenecek kullanılabilir bir cevabın hiç olmadığı demektir. Bağlantı reddedildi, ya da kabul edilip düşürüldü, ya da geri gelen baytlar geçerli bir HTTP yanıtı değildi.
504 görüyorsanız uygulamanızın ne kadar sürdüğüne bakın. 502 görüyorsanız uygulamanızın cevap verip vermediğine bakın.
Sebep 1 — origin bağlantıyı reddetti
Proxy origin'inize bir TCP bağlantısı açtı ve anında ret aldı ya da hiçbir rota bulamadı. O portu dinleyen bir şey yoktu veya bir güvenlik duvarı paketi düşürdü.
Pratikte bunu üretenler: web sunucusu ya da container durmuştur; genel arayüz yerine 127.0.0.1 dinliyordur; origin ayarlarınızdaki port, servisin bulunduğu portla aynı değildir; bir sunucu güvenlik duvarı veya güvenlik grubu CDN'in IP adreslerini engelliyordur.
Nasıl doğrulanır. Kendi ağınızın dışından origin'e doğrudan sorun ve sitenizin kullandığı Host başlığını gönderin — birden çok siteye hizmet eden bir origin aksi hâlde yanlış site için cevap verir ya da reddeder:
curl -sI -H "Host: example.com" http://ORIGIN_IP/
Bu curl da aynı şekilde başarısız oluyorsa CDN doğruyu raporluyordur ve çözüm origin'dedir. Bu curl başarılı olurken edge ret görüyorsa, aradaki fark neredeyse her zaman size izin verip edge'e vermeyen bir güvenlik duvarı kuralıdır.
Sebep 2 — origin bağlantıyı erken kapattı
Bağlantı kabul edildi, sonra tam bir yanıt dönmeden öldü. Yük altındaki PHP ve Node yığınlarında en sık görülen 502 budur.
Bunu üretenler: bütün worker'ları meşgul bir PHP-FPM havuzu — yeni bağlantılar çekirdek kuyruğunda kabul edilip sonra düşürülür; bellek sınırına çarpıp yanıtın ortasında öldürülmüş bir worker; tam da o istekte çöken bir uygulama süreci; origin'in boştaki bağlantıları, proxy'nin yeniden kullanmayı beklediğinden daha erken kapattığı bir keepalive uyuşmazlığı.
Nasıl doğrulanır. 502 anında origin'in kendi hata loguna bakın — origin'in anlatacak net bir hikâyesinin olduğu tek durum budur. Bir Premature end of script headers, bir segfault satırı ya da bir PHP-FPM server reached pm.max_children uyarısı sebebi açıkça söyler. 502'ler rastgele değil de trafik zirvelerinde kümeleniyorsa, karşınızdaki bir hata değil havuz tükenmesidir.
Sebep 3 — origin'e giden TLS el sıkışması başarısız oldu
Proxy origin'inizle HTTPS üzerinden konuşuyorsa, el sıkışma ziyaretçilerinizin gördüğü sertifikayla hiç ilgisi olmayan sebeplerle başarısız olabilir. Genel sertifikayı edge tutar; arkasındaki bağlantı, kendi sertifikası olan ayrı bir konuşmadır.
Bunu üretenler: origin sertifikasının süresi dolmuştur ve genel sertifika otomatik yenilendiği için kimse fark etmemiştir; origin birden çok isme hizmet eder ve doğrusunu seçmek için SNI ister; origin yalnızca proxy'nin sunmadığı TLS sürümlerini ya da şifre takımlarını kabul ediyordur; sertifika www.example.com adını kapsarken proxy example.com isteyerek bağlanıyordur.
Nasıl doğrulanır.
openssl s_client -connect ORIGIN_IP:443 -servername example.com </dev/null | head -20
Zinciri ve tarihleri okuyun. cdn.com.tr'de edge origin'e SNI gönderir; yani tanımladığınız alan adı için geçerli bir sertifika anlaşmayı tamamlar, yalnızca varsayılan vhost için geçerli olan tamamlayamaz.
Sebep 4 — yanıt geçerli HTTP değildi
Daha seyrek ve bulunması keyifli. Origin cevap verdi ama geri gelen şey ayrıştırılamadı: proxy'nin arabelleğinden uzun bir başlık satırı, başlıklardan önce basılmış başıboş bir çıktı satırı (bir PHP uyarısı, bir include dosyasındaki byte-order mark), gövdeyle uyuşmayan bir Content-Length iddiası ya da 443 portundan sunulan düz metin bir çökme dökümü.
Nasıl doğrulanır. Origin'i doğrudan çekin ve işlenmiş sayfaya değil ham baytlara bakın:
curl -sv -H "Host: example.com" http://ORIGIN_IP/ -o /dev/null
Geri gelen ilk satır HTTP/1.1 ... değilse, bulmuşsunuz demektir. Çözüm uygulamanızda ya da çıktı arabelleğindedir; proxy reddetmekte haklıydı.
Önde bir CDN varken ne yapmalı
CDN teşhisi iki işe yarar biçimde değiştirir.
Önbellekteki sayfalar sunulmaya devam eder. Edge önbelleğinde zaten bulunan bir şeyi isteyen ziyaretçi, origin kapalıyken bile onu alır; yani kısmi bir 502 — bazı sayfalar bozuk, bazıları düzgün — genelde origin'in ayakta olduğunu ama önbelleğe alınmamış yollarda, yani tipik olarak dinamik olanlarda, başarısız olduğunu gösterir.
İkinci bir bakış açınız olur. Edge origin'inizi dışarıdan ve sürekli görür. Edge 502 raporlarken kendi tarayıcınız origin'e ulaşıyorsa, hata bu iki isteğin arasındaki farktadır: sizin IP'nize izin veren bir güvenlik duvarı, size başka bir yeri gösteren bir DNS kaydı ya da yalnızca sizin kullandığınız isme uyan bir sertifika.
cdn.com.tr'de dağıtım kuralları, buna tahammülü olan yollarda daha uzun bir önbellek TTL'i tutmanızı sağlar; bir origin olayını ölü bir site yerine kısıtlı çalışan bir siteye çeviren şey de budur. Bunu ihtiyacınız olduğunda değil, olmadan önce ayarlamaya değer.
Origin'inizle hiç ilgisi olmayan 502
Bir durum adıyla anılmayı hak ediyor, çünkü saatler yiyor. DNS'iniz bir CDN edge'ini gösteriyor ama o alan adı henüz o edge'de tanımlanmadıysa 502 almazsınız — bu alan adı için tanımlı bir servis olmadığını söyleyen bir sayfayla 503 alırsınız. Bu, edge'in size hangi origin'e soracağını bilmediğini söylemesidir.
İnsanlar DNS'i değiştirdikten hemen sonra bir hata sayfası görüyor, origin'in bozulduğunu varsayıyor ve işin içinde hiç olmamış servisleri yeniden başlatmaya koyuluyor. Önce durum koduna bakın: 502, edge'in origin'inizi deneyip başarısız olduğu demektir; bu türden bir 503 ise edge'in deneyecek bir origin'inin hiç olmadığı.
502 Bad Gateway SSS
502 benim hatam mı, CDN'in mi?
Genelde ikisi de değil — origin'in. CDN yaşadığı hatayı raporlar, uydurmaz. Kontrol etmeye değer istisna bağlantıdır: origin güvenlik duvarı edge IP adreslerini engelliyorsa, origin sizin için sağlıklı ama CDN için erişilemezdir ve çözüm uygulamada bir şey değil, bir izin kuralıdır.
Neden 502'yi yalnızca ara sıra alıyorum?
Aralıklı 502'ler neredeyse her zaman yapılandırmayı değil kapasiteyi gösterir. Zirvelerde dolan bir süreç havuzu, geri dönüştürülen bir worker ya da keepalive bağlantılarını proxy'nin beklediğinden erken kapatan bir origin; hepsi gelip giden hatalar üretir, üstelik dizüstünüzden yaptığınız basit test her seferinde geçer.
Sayfayı yenilemek işe yarar mı?
Size bir şey söyler. Yenileme işe yarıyorsa hata aralıklıdır ve karşınızda kapasite ya da belirli bir worker vardır. Her yenileme aynı şekilde başarısız oluyorsa bu bir yapılandırma meselesidir — reddedilen bağlantı, yanlış port, süresi dolmuş origin sertifikası — ve yenilemek onu değiştirmez.
Durum kodu olmadan 502 ile 504'ü nasıl ayırırım?
Ne kadar beklediğinizden. 504 size zaman aşımını sonuna kadar bekletir, tipik olarak onlarca saniye, çünkü proxy gerçekten bir cevap bekliyordur. 502 genelde hızlı gelir, çünkü reddedilen ya da bozulan bir bağlantı çabuk başarısız olur.
Ziyaretçilerime varsayılan hata sayfasından iyisini gösterebilir miyim?
Evet ve göstermelisiniz. CDN, proxy'nin varsayılanı yerine önbellekteki eski içeriği ya da markalı bir hata sayfası sunar; bu da bir kesintiyi bozuk bir site yerine her zamankinden kötü bir deneyime çevirir. Olaydan önce ayarlayın, çünkü olay sırasında ayıracak dikkatiniz olmayacak.