HTTP reverse proxies โดยทั่วไปจะเปิดใช้งาน HTTP Keep-Alive ที่ฝั่งไคลเอ็นต์ของการเชื่อมต่อ proxied ไม่ใช่ในฝั่งเซิร์ฟเวอร์หรือไม่?


30

HAProxy มีความสามารถในการเปิดใช้งาน HTTP keep-alive บนฝั่งไคลเอ็นต์ (ไคลเอนต์ <-> HAProxy) แต่ปิดการใช้งานบนฝั่งเซิร์ฟเวอร์ (เซิร์ฟเวอร์ HAProxy <->)

ลูกค้าของเราบางคนเชื่อมต่อกับบริการเว็บของเราผ่านดาวเทียมดังนั้นเวลาในการตอบสนองคือ ~ 600ms และฉันคิดว่าการเปิดใช้งาน Keep-Alive จะช่วยเพิ่มความเร็วให้กับสิ่งต่างๆ ฉันถูกไหม?

Nginx รองรับสิ่งนี้หรือไม่? นี่เป็นคุณสมบัติที่นำไปใช้อย่างกว้างขวางในตัวโหลดบาลานซ์ซอฟต์แวร์และฮาร์ดแวร์อื่น ๆ มีอะไรนอกเหนือจาก HAProxy

คำตอบ:


43

แก้ไข:คำตอบของฉันครอบคลุมเฉพาะคำถามที่ไม่ได้แก้ไขดั้งเดิมซึ่งเป็นสิ่งที่ประเภทนี้เป็นเรื่องปกติใน load balancer / reverse proxies ฉันไม่แน่ใจว่า nginx / product X รองรับสิ่งนี้หรือไม่ 99.9% ของประสบการณ์การพร็อกซีย้อนกลับของฉันอยู่กับ HAproxy

แก้ไข. HTTP Keep-Alive ที่ฝั่งไคลเอ็นต์ แต่ไม่ใช่ฝั่งเซิร์ฟเวอร์

ทำไม?

หากคุณแยกรายละเอียดเล็กน้อยคุณจะเห็นได้อย่างรวดเร็วว่าเหตุใดจึงเป็นประโยชน์ สำหรับตัวอย่างนี้สมมติว่าเรากำลังโหลดหน้าเว็บ www.example.com และหน้านั้นมี 3 ภาพ img [1-3] .jpg

เบราว์เซอร์โหลดหน้าโดยไม่มี Keep-Alive

  1. ลูกค้าสร้างการเชื่อมต่อ TCP ไปที่ www.example.com บนพอร์ต 80
  2. ลูกค้าร้องขอ HTTP GET สำหรับ "/"
  3. เซิร์ฟเวอร์ส่งเนื้อหา HTML ของ URI "/" (ซึ่งมีแท็ก HTML อ้างอิง 3 ภาพ)
  4. เซิร์ฟเวอร์ปิดการเชื่อมต่อ TCP
  5. ลูกค้าสร้างการเชื่อมต่อ TCP ไปที่ www.example.com บนพอร์ต 80
  6. ลูกค้าร้องขอ HTTP GET สำหรับ "/img1.jpg"
  7. เซิร์ฟเวอร์ส่งภาพ
  8. เซิร์ฟเวอร์ปิดการเชื่อมต่อ TCP
  9. ลูกค้าสร้างการเชื่อมต่อ TCP ไปที่ www.example.com บนพอร์ต 80
  10. ลูกค้าร้องขอ HTTP GET สำหรับ "/img2.jpg"
  11. เซิร์ฟเวอร์ส่งภาพ
  12. เซิร์ฟเวอร์ปิดการเชื่อมต่อ TCP
  13. ลูกค้าสร้างการเชื่อมต่อ TCP ไปที่ www.example.com บนพอร์ต 80
  14. ลูกค้าร้องขอ HTTP GET สำหรับ "/img3.jpg"
  15. เซิร์ฟเวอร์ส่งภาพ
  16. เซิร์ฟเวอร์ปิดการเชื่อมต่อ TCP

ขอให้สังเกตว่ามีการสร้างเซสชัน TCP แยกกัน 4 เซสชันแล้วปิด

เบราว์เซอร์กำลังโหลดหน้าเว็บพร้อม Keep-Alive

HTTP Keep-Alive อนุญาตให้มีการเชื่อมต่อ TCP เดียวเพื่อให้บริการคำขอ HTTP หลายรายการซึ่งกันและกัน

  1. ลูกค้าสร้างการเชื่อมต่อ TCP ไปที่ www.example.com บนพอร์ต 80
  2. ไคลเอนต์ทำการร้องขอ HTTP GET สำหรับ "/" และขอให้เซิร์ฟเวอร์ตั้งค่าเซสชัน HTTP Keep-Alive
  3. เซิร์ฟเวอร์ส่งเนื้อหา HTML ของ URI "/" (ซึ่งมีแท็ก HTML อ้างอิง 3 ภาพ)
  4. เซิร์ฟเวอร์ไม่ปิดการเชื่อมต่อ TCP
  5. ไคลเอนต์ทำและคำขอ HTTP GET สำหรับ "/img1.jpg"
  6. เซิร์ฟเวอร์ส่งภาพ
  7. ไคลเอนต์ทำและคำขอ HTTP GET สำหรับ "/img2.jpg"
  8. เซิร์ฟเวอร์ส่งภาพ
  9. ไคลเอนต์ทำและคำขอ HTTP GET สำหรับ "/img3.jpg"
  10. เซิร์ฟเวอร์ส่งภาพ
  11. เซิร์ฟเวอร์ปิดการเชื่อมต่อ TCP หากไม่ได้รับการร้องขอ HTTP อีกภายในระยะเวลาหมดเวลา HTTP Keep-Alive

โปรดสังเกตว่าด้วย Keep-Alive จะมีการสร้างการเชื่อมต่อ TCP เพียง 1 รายการเท่านั้น

ทำไม Keep-Alive ถึงดีกว่า?

ในการตอบคำถามนี้คุณต้องเข้าใจว่าต้องทำอย่างไรเพื่อสร้างการเชื่อมต่อ TCP ระหว่างไคลเอนต์และเซิร์ฟเวอร์ สิ่งนี้เรียกว่าการจับมือ TCP 3-way

  1. ไคลเอนต์ส่งแพ็คเก็ต SYN (chronise)
  2. เซิร์ฟเวอร์ส่ง AC-chronise SYN (chronise) กลับไปตอนนี้ SYN-ACK
  3. ไคลเอนต์ส่งแพคเก็ต ACK (nowledgement)
  4. ขณะนี้การเชื่อมต่อ TCP ถูกพิจารณาว่าใช้งานได้โดยทั้งไคลเอนต์และเซิร์ฟเวอร์

เครือข่ายมีความล่าช้าดังนั้นแต่ละขั้นตอนในการจับมือ 3 ทางใช้เวลาพอสมควร ให้บอกว่ามีไคลเอ็นต์และเซิร์ฟเวอร์ 30 มิลลิวินาทีการส่งแพ็คเก็ต IP ที่จำเป็นในการสร้างการเชื่อมต่อ TCP หมายความว่าต้องใช้เวลา 3 x 30ms = 90ms เพื่อสร้างการเชื่อมต่อ TCP

สิ่งนี้อาจไม่ฟังดูมากนัก แต่ถ้าเราพิจารณาว่าในตัวอย่างดั้งเดิมของเราเราต้องสร้างการเชื่อมต่อ TCP แยกต่างหาก 4 อันสิ่งนี้จะกลายเป็น 360ms เกิดอะไรขึ้นถ้าเวลาแฝงระหว่างไคลเอ็นต์และเซิร์ฟเวอร์คือ 100ms แทนที่จะเป็น 30ms จากนั้นคนรู้จักทั้ง 4 คนของเราใช้เวลาในการสร้าง 1200 มิลลิวินาที

ยิ่งแย่ไปกว่านั้นหน้าเว็บทั่วไปอาจต้องการรูปภาพมากกว่า 3 รูปเพื่อโหลดอาจมีไฟล์ CSS, JavaScript, รูปภาพหรือไฟล์อื่น ๆ ที่ลูกค้าต้องร้องขอ หากหน้าโหลดไฟล์อื่น ๆ 30 ไฟล์และเวลาแฝงของไคลเอ็นต์เซิร์ฟเวอร์คือ 100 มิลลิวินาทีเราใช้เวลานานแค่ไหนในการสร้างการเชื่อมต่อ TCP?

  1. หากต้องการสร้าง 1 การเชื่อมต่อ TCP ใช้เวลา 3 x เวลาแฝงนั่นคือ 3 x 100ms = 300ms
  2. เราต้องทำเช่นนี้ 31 ครั้งสำหรับหน้าหนึ่งครั้งและอีก 30 ครั้งสำหรับไฟล์อื่น ๆ ที่อ้างอิงโดยหน้าเว็บ 31 x 300ms = 9.3 วินาที

ใช้เวลา 9.3 วินาทีในการสร้างการเชื่อมต่อ TCP เพื่อโหลดหน้าเว็บที่อ้างอิงไฟล์อื่น ๆ 30 ไฟล์ และนั่นไม่ได้นับเวลาที่ใช้ในการส่งคำขอ HTTP และรับการตอบกลับ

ด้วย HTTP Keep-Alive เราต้องการเพียงสร้างการเชื่อมต่อ 1 TCP ซึ่งใช้เวลา 300ms

ถ้า HTTP Keep-Alive นั้นยอดเยี่ยมทำไมไม่ลองใช้มันที่ฝั่งเซิร์ฟเวอร์ด้วย?

HTTP reverse proxies (เช่น HAproxy) มักจะถูกนำไปใช้งานใกล้กับเซิร์ฟเวอร์ส่วนหลังที่พวกเขากำลังใช้งานอยู่ ในกรณีส่วนใหญ่เวลาแฝงระหว่างพร็อกซีย้อนกลับและเซิร์ฟเวอร์แบ็กเอนด์จะต่ำกว่า 1 มิลลิวินาทีดังนั้นการสร้างการเชื่อมต่อ TCP จะเร็วกว่ามากระหว่างไคลเอ็นต์

นั่นเป็นเพียงครึ่งหนึ่งของเหตุผล เซิร์ฟเวอร์ HTTP จัดสรรจำนวนหน่วยความจำที่แน่นอนสำหรับการเชื่อมต่อลูกค้าแต่ละครั้ง ด้วย Keep-Alive จะทำให้การเชื่อมต่อยังคงอยู่และโดยการขยายจะรักษาจำนวนหน่วยความจำที่ใช้งานบนเซิร์ฟเวอร์จนกว่าจะถึงเวลาหมด Keep-Alive ซึ่งอาจสูงถึง 15 วินาทีขึ้นอยู่กับการกำหนดค่าเซิร์ฟเวอร์ .

ดังนั้นหากเราพิจารณาถึงผลกระทบของการใช้ Keep-Alive ที่ฝั่งเซิร์ฟเวอร์ของ HTTP reverse proxy เรากำลังเพิ่มความต้องการหน่วยความจำ แต่เนื่องจากเวลาแฝงระหว่างพร็อกซีและเซิร์ฟเวอร์ต่ำดังนั้นเราจึงไม่ได้รับประโยชน์ที่แท้จริงจาก ลดเวลาในการจับมือ 3-way ของ TCP ดังนั้นโดยทั่วไปแล้วดีกว่าการปิดใช้งาน Keep-Alive ระหว่างพร็อกซีและเว็บเซิร์ฟเวอร์ในสถานการณ์นี้

คำเตือน: ใช่คำอธิบายนี้ไม่ได้คำนึงถึงความจริงที่ว่าเบราว์เซอร์มักจะสร้างการเชื่อมต่อ HTTP หลายไปยังเซิร์ฟเวอร์ในแบบคู่ขนาน อย่างไรก็ตามมีข้อ จำกัด เกี่ยวกับจำนวนการเชื่อมต่อแบบขนานที่เบราว์เซอร์จะทำกับโฮสต์เดียวกันและโดยทั่วไปแล้วสิ่งนี้ยังมีขนาดเล็กพอที่จะทำให้เป็นที่ต้องการได้


5
ความรุ่งโรจน์สำหรับคำอธิบายที่ยอดเยี่ยมแกรมฉันไม่เคยใช้เวลานานพอสำหรับการตอบกลับใครก็ตามที่ถามฉันและฉันจะเก็บลิงค์ไปยังโพสต์นี้เพื่อตอบสนองที่ชัดเจนมากในขณะนี้ :-)
Willy Tarreau

2
จะมีข้อได้เปรียบสำหรับ keepAlive ที่ฝั่งเซิร์ฟเวอร์หรือไม่หากการเชื่อมต่อระหว่างพร็อกซีและส่วนหลังเป็น https
avmohan

"เซิร์ฟเวอร์ HTTP จัดสรรจำนวนหน่วยความจำที่แน่นอนสำหรับการเชื่อมต่อไคลเอนต์แต่ละครั้ง" ใช่ แต่จะมีการเชื่อมต่อเหล่านั้นน้อย (?) เพียงหนึ่งต่อการโหลดบาลานเซอร์เท่านั้น? ไม่ใช่หนึ่งต่อลูกค้าบนอินเทอร์เน็ต (?)
Raedwald

@Raedwald หาก load balancer ของคุณถูก จำกัด ให้ทำการเชื่อมต่อ HTTP เดียวกับเซิร์ฟเวอร์ที่ได้รับการสนับสนุนแต่ละเครื่องคุณจะมีเวลาที่ไม่ดีนัก :-)
ThatGraemeGuy

7

Nginx รองรับการใช้งานทั้งสองด้าน


คุณจะบอกว่าการมีชีวิตอยู่มีประโยชน์สำหรับแบ็กเอนด์หากมีความล่าช้าระหว่างพร็อกซีและแบ็กเอนด์? จำนวนที่เหมาะสมที่สุดของการเชื่อมต่อที่มีอยู่จะอนุญาตให้มีอะไรบ้าง
CMCDragonkai

@CMCDragonkai หากแบ็กเอนด์ของคุณตั้งอยู่บนเซิร์ฟเวอร์เฉพาะมันจะมีประโยชน์ในการหลีกเลี่ยงเวลาแฝงการเชื่อมต่อซึ่งขึ้นอยู่กับเครือข่ายของคุณ ไม่มีค่าเฉลี่ยสีทองจำนวนที่ดีที่สุดขึ้นอยู่กับการตั้งค่าของคุณสภาพแวดล้อมของคุณแอปพลิเคชันและรูปแบบคำขอของคุณเป็นหลัก
VBart

ฉันหวังว่าจะหาสมการเพื่อแก้ปัญหานี้!
CMCDragonkai

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