สถานะปัจจุบันในไตรมาสที่ 1 ปี 2018: การยอมรับ หยุดทั้งสัปดาห์เพื่อแกะกล่องและตกแต่งสถานที่ใหม่ของฉัน! วันนี้ฉันมีเรื่องราวดีๆ มาฝากคุณ หากคุณชอบเรื่องราวหลังการชันสูตรศพ

การโยกย้าย Redis และไดโนไมต์

เมื่อสัปดาห์ที่แล้วเราไม่ได้ไปโปรดักชั่นกับ Dynomite อย่างที่ฉันหวังไว้ มีบางสิ่งเกิดขึ้นในสภาพแวดล้อมการแสดงละครของเราซึ่งฉันต้องดำเนินการก่อนที่เราจะสามารถเพลิดเพลินกับการพลิกสวิตช์อีกครั้ง ฤกษ์ดี!

  1. แม้ว่าฉันจะพยายามอย่างเต็มที่เพื่อหลีกเลี่ยงคำสั่งที่ไม่ได้กำหนดไว้ แต่ฉันลืมเปลี่ยน INCR เป็น UUID ที่แอปสร้างขึ้น ซึ่งทำให้การเขียนองค์ประชุมบางอย่างล้มเหลว ผลกระทบก็คือเซิร์ฟเวอร์ Clouddriver สองเซิร์ฟเวอร์ที่แตกต่างกันสามารถ (และทำ) ได้รับคำขอดำเนินการในเวลาเดียวกัน และ Dynomite จะสร้าง ID เดียวกันสำหรับทั้งสองเซิร์ฟเวอร์ ฉันยังคงเห็นข้อผิดพลาดในการเขียนที่ไม่ใช่องค์ประชุมอื่นๆ หลังจากแก้ไขปัญหานี้ ฉันสงสัยว่าฉันกำลังเขียนด้วยผลลัพธ์ SCAN
  2. ฉันปรับใช้ ClusteredSortAgentScheduler ที่เป็นมิตรกับ Dynomite ซึ่งมีประสิทธิภาพและถูกต้องมากกว่า ClusteredAgentScheduler AgentSchedulers มีหน้าที่รับผิดชอบในการกำหนดเวลาแคชใด (เช่น กลุ่มความปลอดภัยของ AWS ในบัญชีทดสอบใน us-east-1) ที่ได้รับการจัดทำดัชนีใหม่และตามเซิร์ฟเวอร์ clouddriver ใด น่าเสียดายที่สวิตช์ไม่ราบรื่นเท่าที่ฉันจินตนาการและดูเหมือนว่าจะทำให้แคชเสียหาย เนื่องจากเราเป็นสีแดง/ดำ ฉันไม่คิดว่าจะต้องเรียกใช้ตัวกำหนดเวลาที่แตกต่างกันสองตัวในเวลาเดียวกันด้วยอัลกอริธึมที่แตกต่างกัน [ใส่ครึ่งหัวเราะ ครึ่งร้องไห้ตรงนี้]
  3. ความเสียหายของแคชนั้นไม่ได้แก้ไขตัวเองด้วยตัวเอง น่าสงสัยมากเพราะฉันเขียนเวทย์มนตร์ "การรักษาตัวเอง" ลงในแคช สิ่งที่ฉันต้องการทำด้วยเหตุผลนี้และเหตุผลอื่นๆ คือให้ Clouddriver รองรับการทำดัชนีแคชหรือเซ็ตย่อยของแคชหรือเซ็ตย่อยอีกครั้งเป็นศูนย์ผ่าน API ผู้ดูแลระบบ

ฉันไม่มีเวลาจริงๆ ที่จะเปิดตัวสิ่งเหล่านี้ เนื่องจากปัญหาด้านประสิทธิภาพอันแสนหวานของ Orca ที่เราต้องแก้ไข

ช่วงเวลาสนุกสนานของการถดถอยประสิทธิภาพ Orca

ปีที่แล้ว Rob Fletcher และฉันได้เขียนโค้ดเบสการกำหนดเวลาการทำงานของ Orca ใหม่จาก Spring Batch ไปยังไลบรารีคิวงานที่สร้างขึ้นตามจุดประสงค์ของเราเอง ซึ่งตอนนี้ได้ยกเข้าสู่โปรเจ็กต์ของตัวเองที่ชื่อว่า Keiko แม้ว่า Keiko จะรองรับการใช้งานคิวต่างๆ แต่เราก็ได้เขียนไว้บน Redis แล้ว

ในขณะที่พัฒนา Keiko เราได้ตัดมุมบางส่วนเพื่อให้สามารถส่งมอบได้ อย่างที่ใครทำ มุมหนึ่งที่เราตัดออกไปคืออัลกอริธึมการล็อกข้อความซึ่งมีการถดถอยด้านประสิทธิภาพอย่างรุนแรงและหยุดนิ่งเป็นเวลาเกือบหนึ่งปี เรารู้ว่านี่จะเป็นปัญหาในที่สุด แต่การวัดประสิทธิภาพของเราแสดงให้เห็นว่ามันไม่ใช่อุปสรรคในการออกสิ่งต่าง ๆ ในตอนแรก เมื่อตัดมุม อย่าลืมย้อนกลับและยกเลิกการตัดก่อนที่จะเกิดปัญหา!

การถดถอยของประสิทธิภาพแสดงให้เห็นในขณะที่ข้อความพร้อมของคิวงานเพิ่มขึ้น ("พร้อม" คือเวลาจัดส่งในขณะนี้หรือในอดีต) แต่เธรดพูลของผู้ปฏิบัติงานไม่เต็ม สำหรับผู้ใช้ปลายทาง สิ่งนี้จะถูกแสดงเนื่องจากไปป์ไลน์ของ Spinnaker และการดำเนินการงานช้า ผู้ใช้รายหนึ่งรายงานว่า “ไปป์ไลน์การปรับใช้ของฉันมักจะใช้เวลาประมาณ 2 นาที แต่วันนี้ใช้เวลาประมาณ 6 นาที” อิอิอิอิอิอิ.

ทุกครั้งที่ QueueProcessor ดำเนินการสำรวจ เราจะดูข้อความที่พร้อมใช้งานที่เก่าที่สุดผ่าน ZRANGEBYSCORE และเราทำสิ่งนี้ทุกๆ 10 มิลลิวินาทีในทุกอินสแตนซ์ Orca หลังจากดูข้อความแล้ว แต่ละอินสแตนซ์ Orca จะพยายามรับการล็อกผ่าน SET NX/EX จากนั้นจึงอ่านข้อความนอกคิวเพื่อประมวลผลในที่สุด เราทำทั้งหมดนี้ภายในด้วยคำสั่งของเจไดแต่ละคน

เมื่อเราเติบโตขึ้น เราได้เปลี่ยนจาก 3 Orca instance เป็น 4, 6, 8, 10... การเติบโตเริ่มทะยานขึ้นจริงๆ เมื่อสองสามสัปดาห์ก่อน และเรายังคงตามไม่ทันกับข้อความที่ค้างอยู่ . เรายังพยายามปรับขนาดเป็น 15 Orca เป็นเวลาประมาณ 10 นาทีสำหรับ "วิทยาศาสตร์" แม้ว่าจะตระหนักดีว่าสิ่งนี้อาจไม่ช่วยอะไรก็ตาม มันไม่ได้

จากนั้น เนื่องจากฉัน [sarcasm] เก่ง ฉันจึงตัดสินใจเริ่มดูข้อความที่พร้อมใช้หลายข้อความและวนซ้ำข้อความเหล่านั้นจนกว่าจะได้รับล็อค สิ่งนี้ไม่ได้ช่วยอะไร ที่จริงแล้วมันทำให้สิ่งต่างๆ มาก แย่ลง โอเค อะไรนะ ฉันเพิ่งทำให้สามารถหลีกเลี่ยงความขัดแย้งในการล็อคได้ใช่ไหม! เราสามารถเขียนได้ว่า Redis ทำงานช้าได้อย่างปลอดภัย เพราะ Orca ไม่ใช่ฮิปโปที่หิวโหย แล้วไงล่ะ?

เมื่อดูบันทึกหลังจากการเปลี่ยนแปลงของฉัน เราพบว่ามีข้อความแสดงข้อผิดพลาดเพิ่มขึ้นอย่างมากในบรรทัด "ไม่สามารถอ่านเนื้อหาข้อความสำหรับ: {UUID}" เลวร้าย. ข้อความนั้นไม่ได้แย่เสมอไป แต่ปริมาณที่เพิ่มขึ้นก็คือ คิวกำลังถูกล็อค ID ข้อความที่ไม่มีเนื้อหา ในทางปฏิบัติ นี่ไม่ใช่ปัญหาการสูญหายของข้อมูล หรือเป็นสัญญาณว่า Spinnaker ทำลายไปป์ไลน์หรืออะไรก็ตาม: เนื้อความของข้อความจะถูกล้างข้อมูลเมื่อจัดการข้อความแล้ว สิ่งที่เกิดขึ้นจริงคืออินสแตนซ์ Orca สามารถดูข้อความ รับการล็อค อ่านข้อความ จัดการมันได้อย่างเต็มที่ และ ล้างข้อมูลก่อนที่อินสแตนซ์ Orca อื่นจะมีโอกาสย้ายจากการดู รหัสข้อความเพื่อรับการล็อค ขั้นตอนการล้างข้อความจะลบคีย์ล็อคอย่างชัดเจนสำหรับกรณีการใช้งาน เช่น การส่งอีกครั้ง ดังนั้นจึงมีการแอบดู ID ข้อความ จากนั้นจะพยายามล็อคข้อความที่ไม่มีอยู่อีกต่อไป ซึ่งใช่… คุณสามารถตั้งค่าการล็อคนั้นได้ ไม่มีปัญหา

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

การแก้ไขขั้นสุดท้ายคือฉันเขียนข้อความอ่านแล้วใหม่ / ตรรกะการโพลของ Keiko ใน Lua เพื่อให้การดำเนินการดู ล็อค และอ่านดำเนินการเป็นการดำเนินการแบบอะตอมมิก เมื่อปรับใช้แล้ว ข้อความที่พร้อมใช้งานจะลดลงเหลือ 0

ขณะที่ฉันอยู่ที่นั่น ฉันยังเปลี่ยนพฤติกรรม QueueProcessor เป็น "เติมพูลเธรดผู้ปฏิบัติงาน" ทุกรอบการสำรวจ แทนที่จะประมวลผลข้อความเดียวทุกช่วงเวลา (นี่เป็นค่าเริ่มต้นที่ปิดใช้งานใน Orca แต่คุณสามารถเปิดใช้งานได้ผ่านทาง keiko.queue.fillExecutorEachCycle=true) การเปลี่ยนแปลงนี้ทำให้การซูมเพิ่มขึ้นในการประมวลผลคิวของเราจริงๆ และ ง่ายที่จะทำ มีวิธีที่มีประสิทธิภาพมากกว่านี้ในการทำสิ่งนี้แต่มีผลกระทบน้อย

แน่นอนว่าการแก้ไขคอขวดด้านประสิทธิภาพที่เดียวก็แค่ย้ายมันไปที่อื่น การปรับปรุง Orca ท้ายที่สุดทำให้เกิดปัญหาประสิทธิภาพดาวน์สตรีมสำหรับ Clouddriver เพราะตอนนี้เรากำลังส่งงานให้มากขึ้นในช่วงเวลาใดก็ตาม อย่างที่เจ้านายเก่าของฉันเคยพูดไว้ว่า “นั่นคือปัญหาของร็อบในอนาคต คุณเกลียด Future Rob” อย่างน้อยเราก็มีระบบที่เราสามารถโทรกลับได้ ณ จุดนี้หาก Clouddriver ไม่สามารถจัดการกับโหลดได้จริงๆ ซึ่งทำให้เรามีช่องว่างเล็กๆ น้อยๆ ที่จะทำการเปลี่ยนแปลงที่เราต้องการใน Clouddriver โดยไม่ต้องตื่นตระหนกในทันที

ในส่วนหนึ่งของงานนี้ Fletcher ยังได้เพิ่มตัวชี้วัดใหม่สำหรับ Orca ซึ่งเป็นตัวบ่งชี้ประสิทธิภาพที่สำคัญสำหรับ Orca: queue.message.lag ความล่าช้าหมายถึงระยะเวลาที่ข้อความอยู่ในสถานะพร้อมใช้งาน แต่ยังไม่ได้ประมวลผล ฉันแปลกใจที่เราไม่ได้ติดตามเรื่องนี้อยู่แล้ว แต่เราอยู่นี่แล้ว นี่คือสัปดาห์ที่แล้ว ค่าเฉลี่ยคือสีน้ำเงิน สีแดงคือสูงสุด

เนื่องจากคุณไม่สามารถมองเห็นสีน้ำเงินได้ นี่คือภาพซูมของสองวันที่ผ่านมา:

สูงสุด 1–2 วินาทีก็ไม่เลว 20.7 วินาทีถือว่าแย่ เราจะเปลี่ยนหน่วยเมตริกนี้เป็นฮิสโตแกรมและแจ้งเตือนออกจาก p99

ประเด็นอื่นๆ

เราได้พูดคุยกันมานานแล้วเกี่ยวกับการสร้างการทดสอบประสิทธิภาพของ Spinnaker เรามีสภาพแวดล้อมการทดสอบโหลด ซึ่งจำลองการใช้งานจริงของเราโดยประมาณ แต่ไม่มีวิธีที่แท้จริงในการสร้างโหลดที่เป็นตัวแทน มี การทดสอบประสิทธิภาพ ที่เราสามารถใช้เพื่อระเบิดสภาพแวดล้อม (และจริงๆ แล้ว หมุนและทำลายโครงสร้างพื้นฐาน AWS และ Titus จริง) แต่นั่นมีราคาแพง

เราจะต้องคิดหาทางออกที่ดีกว่านี้ การเยาะเย้ย AWS & Titus ดูเหมือนเป็นสิ่งที่ถูกต้อง แต่การเยาะเย้ยไม่ใช่ระบบง่ายๆ เลย

ฉันสามารถทำการทดสอบโหลดต่อไปด้วยไปป์ไลน์ที่ยอดเยี่ยมของฉัน...

ฯลฯ

ฉันยังไม่มีความคืบหน้าใดๆ เกี่ยวกับการขยายขนาดบทความ Spinnaker ฉันรู้ว่ามีคนจำนวนมากรออยู่ จนกว่าจะถึงตอนนั้น อืม พยายามรับบริการ Spinnaker ที่รายงานตัววัดและรวบรวมบันทึก คุณจะต้องใช้มันเมื่อเราเข้าใจ

สำหรับฉันน่าแปลกใจจริงๆ ที่คนส่วนใหญ่ในชุมชน Spinnaker ดูเหมือนจะไม่รวบรวมตัวชี้วัดหรือบันทึก ฉันยังไม่แน่ใจว่าทำไมถึงเป็นเช่นนั้น