Nginx proxy_read_timeout เทียบกับ proxy_connect_timeout


15

ฉันเริ่มใช้ Nginx เป็น reverse proxy สำหรับชุดเซิร์ฟเวอร์ที่ให้บริการบางประเภท

บริการอาจค่อนข้างช้าในบางครั้ง (การทำงานบน Java และ JVM บางครั้งอาจติดอยู่ใน "การรวบรวมขยะเต็ม" ซึ่งอาจใช้เวลาหลายวินาที) ดังนั้นฉันจึงตั้งค่าเป็นproxy_connect_timeout2 วินาทีซึ่งจะทำให้ Nginx มีเวลาพอที่จะคิด ออกว่าบริการติดอยู่ใน GC และจะไม่ตอบสนองในเวลาและมันควรจะผ่านการร้องขอไปยังเซิร์ฟเวอร์ที่แตกต่างกัน

ฉันยังได้ตั้งค่าproxy_read_timeoutเพื่อป้องกันไม่ให้พร็อกซีย้อนกลับติดขัดหากบริการใช้เวลามากเกินไปในการคำนวณการตอบสนอง - อีกครั้งควรย้ายคำร้องขอไปยังเซิร์ฟเวอร์อื่นที่ควรจะว่างพอที่จะตอบกลับในเวลาที่เหมาะสม

ฉันใช้การวัดประสิทธิภาพบางอย่างและฉันสามารถเห็นได้อย่างชัดเจนว่าการproxy_connect_timeoutทำงานอย่างถูกต้องตามที่คำขอบางอย่างกลับมาตรงตามเวลาที่กำหนดไว้สำหรับการหมดเวลาการเชื่อมต่อเนื่องจากบริการติดขัดและไม่ยอมรับการเชื่อมต่อขาเข้า (บริการกำลังใช้ Jetty ภาชนะ servlet) proxy_read_timeoutยังทำงานที่ฉันสามารถดูการร้องขอว่าการกลับมาหลังจากที่หมดเวลาที่ระบุไว้มี

ปัญหาคือฉันคาดว่าจะเห็นคำขอบางอย่างที่หมดเวลาหลังจากproxy_read_timeout + proxy_connect_timeoutนั้นหรือเกือบระยะเวลานั้นถ้าบริการค้างอยู่และไม่ยอมรับการเชื่อมต่อเมื่อ Nginx พยายามเข้าถึงมัน แต่ก่อนที่ Nginx จะหมดเวลา - มันจะถูกปล่อยออกมา และเริ่มการประมวลผล แต่ช้าเกินไปและ Nginx จะยกเลิกเนื่องจากการหมดเวลาอ่าน ฉันเชื่อว่าบริการดังกล่าวมีกรณีดังกล่าว แต่หลังจากใช้การวัดประสิทธิภาพหลายครั้งรวมคำขอหลายล้านรายการ - ฉันไม่เห็นคำขอเดียวที่ส่งคืนสิ่งใด ๆ ข้างต้นproxy_read_timeout(ซึ่งเป็นการหมดเวลาที่มากขึ้น)

ฉันจะขอบคุณความคิดเห็นใด ๆ เกี่ยวกับปัญหานี้แม้ว่าฉันคิดว่าอาจเป็นเพราะข้อผิดพลาดใน Nginx (ฉันยังไม่ได้ดูรหัสดังนั้นนี่เป็นเพียงข้อสันนิษฐาน) ว่าตัวนับการหมดเวลาไม่ได้รับการรีเซ็ตหลังจากการเชื่อมต่อ สำเร็จถ้า Nginx ไม่อ่านอะไรจากเซิร์ฟเวอร์ upstream


1
NGINX รุ่นใด ฉันคิดว่าฉันจำบางสิ่งที่คล้ายกันในรุ่นที่เก่ากว่า (ประมาณ 0.6 / 7 อาจจะ) แต่มันได้รับการแก้ไขในรุ่นที่ใหม่กว่า (รุ่นที่เสถียรล่าสุดคือ 1.0.5) แต่อาจผิด ยังคงรู้รุ่นของคุณจะช่วย
รอยเปื้อน

โปรดสังเกตว่าเอกสารบอกว่าproxy_read_timeoutไม่ใช่ "หมดเวลาทั่วโลก" แต่ระหว่างการดำเนินการอ่าน 2 ครั้ง
poige

@Sam: ฉันใช้ Nginx 1.0.0 @poige - proxy_read_timeout + proxy_connect_timeoutใช่ฉันรู้ว่าซึ่งเป็นเหตุผลที่ผมคาดว่าหมดเวลาที่จะรวม
Guss

1
โปรดทราบว่าคุณควรศึกษาการปรับชุดการรวบรวมขยะพร้อมกันสำหรับ JVM ของคุณ: en.wikipedia.org/wiki/…
พหุนาม

@polynomial: เราได้ แต่ตามมาตรฐานของเราพร้อมกันผลคุณลักษณะการเก็บขยะในเวลา CPU มากขึ้นหายไป GC โดยรวมเมื่อเทียบกับ "หยุดโลก" GC, ด้วยเหตุนี้เราชอบการลงทุนในการปรับจูน Nginx :-)
Guss

คำตอบ:


18

ที่จริงแล้วฉันไม่สามารถทำซ้ำได้ใน:

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

ฉันตั้งค่านี้ใน nginx.conf ของฉัน:

proxy_connect_timeout   10;
proxy_send_timeout      15;
proxy_read_timeout      20;

ฉันตั้งค่าเซิร์ฟเวอร์ทดสอบสองเครื่องแล้ว หนึ่งที่เพิ่งหมดเวลาใน SYN และหนึ่งที่จะยอมรับการเชื่อมต่อ แต่ไม่ตอบสนอง:

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
}

จากนั้นฉันก็ส่งหนึ่งการเชื่อมต่อการทดสอบ:

[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

จากนั้นดู error_log ซึ่งแสดงสิ่งนี้:

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"

แล้ว:

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"

จากนั้น access.log ซึ่งมีการหมดเวลา 30 วินาทีที่คาดไว้ (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 -

นี่คือรูปแบบบันทึกที่ฉันใช้ซึ่งรวมถึงการหมดเวลาอัปสตรีมแต่ละรายการ:

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
ในสถานการณ์ของคุณคำถามของฉันเป็นดังนี้: สมมติว่าเซิร์ฟเวอร์ทดสอบที่ยอมรับการเชื่อมต่อหลังจากเวลาสุ่มระหว่าง 0 ถึง 20 วินาทีแล้วรอเวลาสุ่มระหว่าง 19 วินาทีถึง 21 วินาทีก่อนที่จะตอบคำถาม จากนั้นเรียกใช้เกณฑ์เปรียบเทียบง่าย ๆ ฉันคาดว่าจะเห็นผลลัพธ์ประมาณ 50% ของการร้องขอด้วยการหมดเวลา 10 วินาทีผล 25% กับการหมดเวลา 20 ~ 30 วินาทีและ 25% จะได้รับการตอบสนองที่ประสบความสำเร็จ ในกรณีเช่นนี้คำขอที่ประสบความสำเร็จจำนวนมากจะใช้เวลามากกว่า 20 วินาทีจึงจะเสร็จสมบูรณ์ ในเกณฑ์มาตรฐานของฉันไม่มีพวกเขา - และนั่นทำให้ฉันลำบาก
Guss

ฉันทดสอบโดยตั้งค่าการสูญเสียแบบสุ่มใน SYN แล้วมี CGI ที่พ่นเส้นช้า ๆ เป็นเวลาประมาณ 50 วินาที ฉันสามารถเห็นคำขอที่ยาวกว่าการหมดเวลารวมกันมาก แต่ก็ยังประสบความสำเร็จ: box.access.log 200: 69.814: 67.100:.: 1579 33 127.0.0.1 test.host - [21 / Aug / 2011: 20: 30:52 -0700] "GET / huugs HTTP / 1.1" "-" "-" "-" dev_edge 127.0.0.1:2280 -
พหุนาม

ตกลงนั่นแปลกในระดับที่แตกต่างกันทั้งหมด :-) หนึ่งคำอธิบายที่เป็นไปได้ก็คือว่ามันต้องใช้เวลาสำหรับ Nginx การเขียนคำขอ ( proxy_send_timeout) และเป็นคุณได้ตั้งค่าให้สูงขึ้นแล้วproxy_connection_timeoutที่จริงสามารถบัญชีสำหรับความล่าช้าใด ๆ ในช่วง 20 proxy_read_timeoutวินาที เมื่อคุณพูดว่า "ถ่มน้ำลายสายช้า ๆ " - คุณหมายถึงอะไร
Guss

sleep 1 ระหว่างบรรทัดการพิมพ์ของ HTML ในเนื้อหาของการตอบกลับ เพียงเปิดเผยว่า proxy_read_timeout อยู่ระหว่างการอ่านไม่ใช่การอ่านทั้งหมด
พหุนาม

1
อ่าฉันเข้าใจแล้ว นี่มันไม่ใช่กรณีของฉันและฉันขอโทษที่ทำให้มันไม่ชัดเจนใน OP ของฉัน ในกรณีของฉันเซิร์ฟเวอร์แอปพลิเคชั่นทำการประมวลผลทั้งหมดก่อนที่จะส่งกลับการตอบสนองใด ๆ แล้วส่งคืนทุกอย่างพร้อมกันดังนั้นproxy_read_timeoutคำขอล้มเหลวอย่างสมบูรณ์หรืออนุญาตทั้งหมด สิ่งนี้ยังอธิบายถึงความแตกต่างระหว่างพฤติกรรมที่คุณเห็นและพฤติกรรมที่ฉันเห็น
Guss

3

ปัญหาคือฉันคาดว่าจะเห็นคำขอบางอย่างที่หมดเวลาหลังจาก proxy_read_timeout + proxy_connect_timeout หรือเกือบระยะเวลานั้นถ้าบริการค้างและไม่ยอมรับการเชื่อมต่อเมื่อ Nginx พยายามเข้าถึง แต่ก่อน Nginx สามารถหมดเวลา - มันได้รับการปล่อยตัวและเริ่มการประมวลผล แต่ช้าเกินไปและ Nginx จะยกเลิกเนื่องจากการหมดเวลาอ่าน

การหมดเวลาเชื่อมต่อหมายถึงแผงลอย TCP เมื่อจับมือ (เช่นไม่มี SYN_ACKs) TCP จะลองส่ง SYN อีกครั้ง แต่คุณได้รับเพียง 2 วินาที ถึง Nginx เพื่อใช้เซิร์ฟเวอร์อื่นดังนั้นจึงไม่มีเวลาสำหรับการส่ง SYN ใหม่อีกครั้ง

UPD : ไม่พบในเอกสาร แต่ tcpdump แสดงว่ามี3วินาที หน่วงเวลาระหว่างวันที่ 1 ที่ส่ง SYN และความพยายามครั้งที่สองในการส่ง SYN


ฉันไม่คิดว่านี่เป็นสิ่งที่ฉันกำลังถาม - คำถามคือ: หาก upstream ติดขัดและคืนค่า SYN_ACK หลังจาก 1.999 วินาทีทำไม nginx จะไม่ดำเนินการกับขั้นตอนปัจจุบัน upstream?
Guss

ดีคุณสามารถใช้ดมกลิ่นถ้าคุณต้องการให้แน่ใจว่า มันอาจกลายเป็นว่าไม่มี ACK ใน <2 วินาทีเลย
poige

ฉันไม่สามารถใช้นักดมกลิ่นได้เพราะฉันคาดว่าจะเห็นพฤติกรรมนี้เกิดขึ้นเมื่อระบบมีภาระสูง คำอธิบายของ ACK ไม่เคยมีมาก่อนหลังจากนั้นมี X บางตัว แต่เร็วกว่านั้น 2 วินาทีแม้ว่าจะพิจารณาคำขอนับล้านครั้งดูเหมือนจะไม่น่าเชื่อถือ
Guss
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.