Nginx proxy_read_timeout ile proxy_connect_timeout karşılaştırması


15

Nginx'i bir tür hizmet sağlayan sunucular kümesi için ters proxy olarak kullanmaya başladım.

Hizmet zaman zaman oldukça yavaş olabilir (Java ve JVM üzerinde bazen birkaç saniye sürebilen "tam çöp toplama" sıkışmış olur), bu yüzden proxy_connect_timeoutNginx anlamaya yeterli zaman verecek 2 saniye için ayarladım hizmetin GC'ye yapıştığını ve zamanında yanıt vermeyeceğini ve isteği farklı bir sunucuya iletmesi gerektiğini unutmayın.

Ayrıca proxy_read_timeout, hizmetin kendisi yanıtı hesaplamak için çok fazla zaman alırsa ters proxy'nin takılmasını önlemek için ayarladım - yine, zamanında yanıt vermek için yeterince ücretsiz olması gereken başka bir sunucuya isteği taşımalıdır.

Bazı ölçütleri çalıştırdım ve proxy_connect_timeoutbazı istekler tam olarak bağlantı zaman aşımı için belirtilen sürede döndüğü için düzgün çalıştığını görebiliyorum , hizmet sıkışmış ve gelen bağlantıları kabul etmiyor (hizmet yerleşik olarak Jetty kullanıyor sunucu kabı). proxy_read_timeoutBen zaman aşımı sonra geri dönüşü belirtilen istekleri görebileceğiniz gibi de çalışır.

Sorun, proxy_read_timeout + proxy_connect_timeouthizmet sıkışmışsa ve Nginx erişmeye çalıştığında bağlantıları kabul etmezse, ancak zaman aşımına uğrayan bazı istekleri görmeyi beklememdir , ancak Nginx zaman aşımına uğramadan önce - serbest bırakılır ve işlemeye başlar, ancak çok yavaştır ve Nginx okuma zaman aşımı nedeniyle iptal edilir. Hizmetin bu gibi durumlara sahip olduğuna inanıyorum, ancak birkaç kriter çalıştırdıktan sonra, birkaç milyon istek toplamı - yukarıdaki herhangi bir şeyde proxy_read_timeout(daha büyük zaman aşımı olan) dönen tek bir istek göremedim .

Bağlantıdan sonra zaman aşımı sayacı sıfırlanmıyorsa (Ben henüz kod bakmak zorunda, bu yüzden bu sadece bir varsayım) Nginx bir hata nedeniyle olabileceğini düşünüyorum rağmen ben bu konuda herhangi bir yorum takdir ediyorum Nginx akış yukarı sunucudan hiçbir şey okumadıysa başarılı olur.


1
Hangi NGINX sürümü? Sanırım eski bir sürümde benzer bir şey hatırlıyorum (yaklaşık 0.6 / 7 belki) ama daha yeni bir sürümde düzeltildi (En son kararlı sürüm 1.0.5), ancak bu yanlış olabilir. Sürümünüzün hala yardımcı olacağını bilmek
Smudge

Dokümanların proxy_read_timeout"global zaman aşımı" olmadığını, ancak 2 okuma işlemi arasında olduğunu unutmayın.
poige

@Sam: Nginx 1.0.0 kullanıyorum. @poige - evet, bunun farkındayım, bu yüzden toplam zaman aşımının olmasını bekliyorum proxy_read_timeout + proxy_connect_timeout.
Guss

1
Bir yan not olarak, muhtemelen JVM'niz için eşzamanlı çöp toplama ayarını araştırmalısınız: en.wikipedia.org/wiki/…
polinom

@polynomial: Yaptık ama karşılaştırmalı değerlendirmelerimize göre, eşzamanlı çöp toplama özelliği "dünyayı durdur" GC ile karşılaştırıldığında genel olarak GC'ye daha fazla CPU zamanı kaybına neden oluyor, bu nedenle Nginx ayarına yatırım yapmayı tercih ediyoruz :-)
Guss

Yanıtlar:


18

Aslında bunu çoğaltamadım:

2011/08/20 20:08:43 [notice] 8925#0: nginx/0.8.53
2011/08/20 20:08:43 [notice] 8925#0: built by gcc 4.1.2 20080704 (Red Hat 4.1.2-48)
2011/08/20 20:08:43 [notice] 8925#0: OS: Linux 2.6.39.1-x86_64-linode19

Bunu nginx.conf dosyasında kurdum:

proxy_connect_timeout   10;
proxy_send_timeout      15;
proxy_read_timeout      20;

Daha sonra iki test sunucusu kurdum. Biri yalnızca SYN'de zaman aşımı olacak ve bağlantıları kabul edecek, ancak asla yanıt vermeyecek:

upstream dev_edge {
  server 127.0.0.1:2280 max_fails=0 fail_timeout=0s; # SYN timeout
  server 10.4.1.1:22 max_fails=0 fail_timeout=0s; # accept but never responds
}

Sonra bir test bağlantısı gönderdim:

[m4@ben conf]$ telnet localhost 2480
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
GET / HTTP/1.1
Host: localhost

HTTP/1.1 504 Gateway Time-out
Server: nginx
Date: Sun, 21 Aug 2011 03:12:03 GMT
Content-Type: text/html
Content-Length: 176
Connection: keep-alive

Sonra bunu gösteren error_log izledi:

2011/08/20 20:11:43 [error] 8927#0: *1 upstream timed out (110: Connection timed out) while connecting to upstream, client: 127.0.0.1, server: ben.dev.b0.lt, request: "GET / HTTP/1.1", upstream: "http://10.4.1.1:22/", host: "localhost"

sonra:

2011/08/20 20:12:03 [error] 8927#0: *1 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 127.0.0.1, server: ben.dev.b0.lt, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:2280/", host: "localhost"

Ve sonra beklenen 30s zaman aşımına sahip erişim.log (10 + 20):

504:32.931:10.003, 20.008:.:176 1 127.0.0.1 localrhost - [20/Aug/2011:20:12:03 -0700] "GET / HTTP/1.1" "-" "-" "-" dev_edge 10.4.1.1:22, 127.0.0.1:2280 -

Tek tek yukarı akış zaman aşımlarını içeren kullandığım günlük biçimi:

log_format  edge  '$status:$request_time:$upstream_response_time:$pipe:$body_bytes_sent $connection $remote_addr $host $remote_user [$time_local] "$request" "$http_referer" "$http_user_agent" "$http_x_forwarded_for" $edge $upstream_addr $upstream_cache_status';

1
Yukarıdaki sorum, senaryonuzda daha çok şöyle: 0 ile 20 saniye arasında rastgele bir süre sonra bağlantıyı kabul eden ve ardından yanıt vermeden önce 19 saniye ile 21 saniye arasında rastgele bir süre bekleyen bir test sunucusu olduğunu varsayalım. Sonra buna karşı basit bir kıyaslama yapın. İsteklerin yaklaşık% 50'sinin 10 saniyelik bir zaman aşımı ile,% 25'inin 20 ~ 30 saniyelik bir zaman aşımı ile ve% 25'inin başarılı bir yanıt alacağını görmeyi beklerim. Böyle bir durumda, kaç başarılı isteğin tamamlanması 20 saniyeden uzun sürecektir? Karşılaştırmamda, hiçbiri değil - ve bu beni rahatsız ediyor.
Guss

SYN üzerinde rastgele bir kayıp kurarak ve sonra yaklaşık 50 saniye boyunca gerçekten yavaşça tüküren bir CGI'ya sahip olarak test ettim. Her iki zaman aşımı süresinden çok daha uzun süren ancak yine de başarılı olan istekleri görebildim: box.access.log 200: 69.814: 67.100:.: 1579 33 127.0.0.1 test.host - [21 / Ağu / 2011: 20: 30:52 -0700] "GET / huugs HTTP / 1.1" "-" "-" "-" dev_edge 127.0.0.1:2280 -
polinom

Tamam, bu tamamen farklı bir seviyede garip :-). Olası bir açıklama, Nginx'in isteği yazması ( proxy_send_timeout) için zaman alması ve daha yüksek bir değere ayarladığınızda proxy_connection_timeout, bu aslında 20 saniye boyunca herhangi bir gecikmeyi hesaba katabilir proxy_read_timeout. "Çizgileri gerçekten yavaşça tükür" dediğinde ne demek istiyorsun?
Guss

yanıt gövdesindeki HTML yazdırma satırları arasında 1 uyku. Sadece proxy_read_timeout öğesinin okumalar arasında nasıl olduğunu tam olarak okumak değil.
polinom

1
Ah, anlıyorum. Bu kesinlikle benim durumum değil ve OP'mde netleştirmediğim için üzgünüm. Benim durumumda, uygulama sunucusu herhangi bir yanıt vermeden önce tüm işlemi tamamlar ve sonra her şeyi bir kerede döndürür - böylece proxy_read_timeoutya istek tamamen başarısız olur veya tamamen izin verir. Bu aynı zamanda gördüğünüz davranış ile gördüğüm davranış arasındaki farkı da açıklar.
Guss

3

Sorun, hizmet sıkışmışsa ve Nginx erişmeye çalıştığında bağlantıları kabul etmezse, proxy_read_timeout + proxy_connect_timeout'tan sonra zaman aşımına uğrayan bazı istekleri görmeyi beklememdir, ancak Nginx zaman aşımına uğramadan önce bağlantıları kabul etmez. yayınlanır ve işlemeye başlar, ancak çok yavaştır ve Nginx okuma zaman aşımı nedeniyle iptal edilir.

Bağlantı zaman aşımı, el sıkışma sırasında TCP durakları anlamına gelir (örneğin, SYN_ACK'ler yoktu). TCP, SYN'leri göndermeyi tekrar dener, ancak yalnızca 2 saniyeyi vermişsinizdir. Başka bir Sunucu kullanmak için Nginx'e gidin, bu nedenle SYN'leri yeniden göndermek için zamanı yoktur.

UPD. : Dokümanlarda bulunamadı, ancak tcpdump 3 saniye olduğunu gösteriyor . 1. gönderilen SYN ile 2. SYN gönderme denemesi arasındaki gecikme.


Bu tam olarak sorduğumu sanmıyorum - soru: yukarı akış takılır ve 1.999 saniye sonra SYN_ACK döndürürse, nginx neden geçerli yukarı akış ile işleme devam etmiyor?
Guss

Tam olarak emin olmak istiyorsanız sniffer'ı kullanabilirsiniz. 2 saniyeden daha az ACK olmadığı ortaya çıkabilir.
Ağustos'ta poige

Sniffer'ı gerçekten kullanamıyorum çünkü bu davranışın sistemde yüksek bir yük olduğu yerde olmasını bekliyorum. Bunun hiçbir zaman ACK'ların açıklaması daha sonra bazı X'ten sonra değil, ancak 2 saniyeden önce, milyonlarca istek göz önünde bulundurulduğunda bile mantıklı görünmüyor.
Guss
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.