เรามี API ที่ใช้งานผ่าน ServiceStack ซึ่งโฮสต์ใน IIS ในขณะที่ทำการทดสอบการโหลดของ API เราพบว่าเวลาตอบสนองนั้นดี แต่ก็ลดลงอย่างรวดเร็วทันทีที่เรามีผู้ใช้งานพร้อมกันประมาณ 3,500 คนต่อเซิร์ฟเวอร์ เรามีเซิร์ฟเวอร์สองเครื่องและเมื่อมีผู้ใช้ถึง 7,000 คนเวลาตอบสนองโดยเฉลี่ยอยู่ต่ำกว่า 500ms สำหรับอุปกรณ์ปลายทาง กล่องเหล่านี้อยู่ด้านหลัง load balancer เราจึงได้รับ 3,500 concurrents ต่อเซิร์ฟเวอร์ อย่างไรก็ตามทันทีที่เราเพิ่มจำนวนผู้ใช้พร้อมกันทั้งหมดเราจะเห็นเวลาตอบสนองที่เพิ่มขึ้นอย่างมีนัยสำคัญ การเพิ่มผู้ใช้พร้อมกันถึง 5,000 ต่อเซิร์ฟเวอร์ทำให้เรามีเวลาตอบสนองโดยเฉลี่ยต่อปลายทางประมาณ 7 วินาที
หน่วยความจำและ CPU บนเซิร์ฟเวอร์ค่อนข้างต่ำทั้งในขณะที่เวลาตอบสนองที่ดีและเมื่อพวกเขาเสื่อมสภาพ ที่สูงสุดด้วยผู้ใช้ 10,000 คนพร้อมกันค่าเฉลี่ยของ CPU เพียงแค่ต่ำกว่า 50% และ RAM อยู่ที่ประมาณ 3-4 GB จาก 16 สิ่งนี้ทำให้เราคิดว่าเรากำลัง จำกัด ขอบเขตบางแห่ง ภาพหน้าจอด้านล่างแสดงตัวนับหลักใน perfmon ระหว่างการทดสอบโหลดซึ่งมีผู้ใช้งานพร้อมกันทั้งหมด 10,000 คน ตัวนับที่ไฮไลต์คือคำร้องขอ / วินาที ทางด้านขวาของสกรีนช็อตคุณสามารถเห็นคำขอต่อกราฟที่สองกลายเป็นเอาแน่เอานอนไม่ได้ นี่คือตัวบ่งชี้หลักสำหรับเวลาตอบสนองช้า ทันทีที่เราเห็นรูปแบบนี้เราจะสังเกตเห็นเวลาตอบสนองช้าในการทดสอบโหลด
เราจะแก้ไขปัญหาประสิทธิภาพการทำงานนี้ได้อย่างไร เรากำลังพยายามระบุว่านี่เป็นปัญหาการเข้ารหัสหรือปัญหาการกำหนดค่า มีการตั้งค่าใด ๆ ใน web.config หรือ IIS ที่สามารถอธิบายพฤติกรรมนี้ได้หรือไม่? กลุ่มแอพลิเคชันกำลังเรียกใช้. NET v4.0 และรุ่น IIS คือ 7.5 การเปลี่ยนแปลงเดียวที่เราทำจากการตั้งค่าเริ่มต้นคือการอัปเดตค่าความยาวคิวแอปพลิเคชันจาก 1,000 เป็น 5,000 เราได้เพิ่มการตั้งค่าคอนฟิกต่อไปนี้ไปยังไฟล์ Aspnet.config ด้วย:
<system.web>
<applicationPool
maxConcurrentRequestsPerCPU="5000"
maxConcurrentThreadsPerCPU="0"
requestQueueLimit="5000" />
</system.web>
รายละเอียดเพิ่มเติม:
วัตถุประสงค์ของ API คือการรวมข้อมูลจากแหล่งข้อมูลภายนอกต่างๆและส่งคืนเป็น JSON ขณะนี้กำลังใช้การใช้แคช InMemory เพื่อแคชการโทรภายนอกแต่ละรายการที่ชั้นข้อมูล คำขอแรกไปยังทรัพยากรจะดึงข้อมูลทั้งหมดที่จำเป็นและคำขอใด ๆ ที่ตามมาสำหรับทรัพยากรเดียวกันจะได้รับผลลัพธ์จากแคช เรามี 'นักวิ่งแคช' ที่ใช้เป็นกระบวนการพื้นหลังที่อัปเดตข้อมูลในแคชตามช่วงเวลาที่กำหนด เราได้เพิ่มการล็อกรอบโค้ดที่ดึงข้อมูลจากทรัพยากรภายนอก นอกจากนี้เรายังได้ใช้บริการเพื่อดึงข้อมูลจากแหล่งภายนอกในรูปแบบอะซิงโครนัสเพื่อให้ปลายทางควรช้าเท่ากับการโทรภายนอกที่ช้าที่สุด (เว้นแต่ว่าเรามีข้อมูลในแคชแน่นอน) สิ่งนี้ทำได้โดยใช้คลาส System.Threading.Tasks.Taskเราสามารถ จำกัด จำนวนเธรดที่มีอยู่สำหรับกระบวนการได้หรือไม่?