อ่านประมาณ 8 นาที
ระดับสูง
หมวด: คลาวด์
อ้างอิง: AWS Architecture Blog — Building resilient real-time streaming workers with Amazon DynamoDB leases
บริการถอดเสียงประชุมแบบเรียลไทม์ที่รองรับ 500 ประชุมพร้อมกันเจอปัญหาว่า เมื่อ worker ตัวเดียวล่ม การเชื่อมต่อกว่า 100 รายการจะหลุด และข้อมูลหายรายการละ 2-3 นาทีจนกว่าจะมีคนมารีสตาร์ตเอง AWS Architecture Blog เสนอทางแก้ด้วยกลไก lease บน DynamoDB ที่ให้ worker ตัวอื่นรับงานต่อได้เองโดยไม่ต้องมีระบบประสานงานแยก บทความนี้สรุปการออกแบบตาราง อัลกอริทึม ค่าตั้งต้น ต้นทุน และจุดที่ต้องคิดเพิ่มก่อนนำไปใช้กับระบบในไทย
ปัญหาของงานที่ต้องถือการเชื่อมต่อค้างไว้นาน ๆ
งานประมวลผลแบบสตรีมมิงผ่าน WebSocket ต่างจากงาน API ทั่วไป เพราะ worker ต้องถือการเชื่อมต่อค้างไว้ตลอดช่วงประชุม เมื่อ worker ล่ม การเชื่อมต่อที่มันถืออยู่จะไม่มีเจ้าของทันที โจทย์ที่ AWS ยกมามีสี่ข้อ คือ worker ล่มแล้วการเชื่อมต่อค้างไม่มีใครดูแล การ deploy แบบทยอยสลับเครื่องสร้างช่วงที่การเชื่อมต่อไม่มีเจ้าของ การลดจำนวนเครื่องต้องระบายงานออกให้หมดก่อน และความเสี่ยงที่ worker สองตัวรับงานเดียวกันซ้ำ
lease คืออะไร
lease คือสิทธิ์ความเป็นเจ้าของที่มีวันหมดอายุ worker ที่ถือ lease ของการเชื่อมต่อใดต้องต่ออายุเป็นระยะ ถ้าหยุดต่ออายุเพราะล่ม สิทธิ์นั้นจะหมดอายุเองและ worker ตัวอื่นรับไปได้ ข้อดีคือได้การย้ายงานอัตโนมัติ (failover) โดยไม่ต้องติดตั้งระบบประสานงานแยก เพราะใช้ความสามารถ conditional write ของ DynamoDB ที่มีอยู่แล้ว
โครงสร้างตาราง lease ใน DynamoDB ตามบทความต้นฉบับ| แอตทริบิวต์ | ชนิด | หน้าที่ |
|---|
| pk | String (partition key) | รหัสการเชื่อมต่อ เช่น CONN#meeting-123 |
| desired_state | String | สถานะที่ต้องการ คือ STARTED หรือ STOPPED |
| ws_url | String | URL ของ WebSocket ต้นทาง |
| lease_owner | String | รหัสของ worker ที่เป็นเจ้าของอยู่ |
| lease_expires_at_ms | Number | เวลาหมดอายุของ lease เป็นมิลลิวินาทีแบบ epoch |
| last_seq | Number | ลำดับข้อมูลล่าสุดที่ประมวลผลแล้ว ใช้ทำงานต่อจากจุดเดิม |
ตารางมีดัชนีรอง (GSI) บน desired_state และ lease_expires_at_ms เพื่อค้นหาการเชื่อมต่อที่ควรทำงานอยู่แต่ lease หมดอายุแล้วได้อย่างรวดเร็ว
วงจรชีวิตของ lease สี่ขั้น
ขั้นรับงาน worker เขียนข้อมูลแบบมีเงื่อนไขว่าต้องยังไม่มี lease หรือ lease เดิมหมดอายุแล้วเท่านั้น ถ้า worker สองตัวพยายามรับงานเดียวกันพร้อมกัน DynamoDB จะตรวจเงื่อนไขแบบ atomic และให้สำเร็จเพียงตัวเดียว
ขั้นต่ออายุ worker เจ้าของส่ง heartbeat ทุก 5 วินาทีโดยค่าเริ่มต้น พร้อมเงื่อนไขว่า lease_owner ต้องยังเป็นตัวเอง ถ้าต่ออายุไม่สำเร็จแปลว่าเสียสิทธิ์ไปแล้ว worker ต้องหยุดงานนั้นทันที ขั้นคืนงาน เมื่อได้รับสัญญาณปิดเครื่องอย่าง SIGTERM worker จะล้าง lease_owner และตั้งเวลาหมดอายุเป็น 0 เพื่อให้ตัวอื่นรับต่อได้เลยโดยไม่ต้องรอหมดอายุ
ขั้นหมดอายุ ถ้า worker ล่มกะทันหัน lease จะค้างอยู่แต่ไม่ถูกต่ออายุ ทุก worker รันวงรอบกระทบยอด (reconciliation) ทุก 60 วินาทีเพื่อค้นหาผ่าน GSI ว่ามีการเชื่อมต่อที่ควรทำงานแต่ lease หมดอายุหรือไม่ แล้วรับไปทำต่อ ส่วนงานใหม่จะแจ้งผ่าน Amazon SQS เพื่อไม่ต้องรอรอบกระทบยอดถัดไป
ภาพประกอบบทความหมวดคลาวด์
นาฬิกาไม่ตรงกันคือจุดอ่อนที่ต้องจัดการ
ประเด็นที่ง่ายจะมองข้ามคือ DynamoDB ตรวจเงื่อนไขหมดอายุด้วยค่าเวลาปัจจุบันที่ worker ส่งมาเอง ไม่ใช่นาฬิกาของ DynamoDB ถ้านาฬิกาของแต่ละเครื่องเพี้ยนไม่เท่ากัน worker อาจเข้าใจผิดว่า lease ของตัวอื่นหมดอายุแล้ว บน AWS Fargate ในภูมิภาคเดียวกันนาฬิกาถูกซิงก์ผ่าน Amazon Time Sync Service ให้คลาดกันเพียงไม่กี่มิลลิวินาที แต่ถ้ารันบนเครื่องอื่นต้องตั้ง NTP ติดตามการคลาดของนาฬิกา และบวกค่าคลาดสูงสุดที่คาดไว้เข้าไปในระยะเวลา lease
ค่าตั้งต้นและต้นทุน
ค่าตั้งต้นที่บทความต้นฉบับแนะนำ| พารามิเตอร์ | ค่าเริ่มต้น | เหตุผล |
|---|
| ระยะ lease | 20 วินาที | ย้ายงานได้เร็ว แต่ทนเครือข่ายสะดุดสั้น ๆ ได้ |
| รอบ heartbeat | 5 วินาที | มีช่องว่างความปลอดภัย 4 เท่าก่อน lease หมดอายุ |
| รอบกระทบยอด | 60 วินาที | สมดุลระหว่างความเร็วในการกู้คืนกับค่าอ่านข้อมูล DynamoDB |
| การเชื่อมต่อสูงสุดต่อ task | 700 | ได้จากการวัดหน่วยความจำและ CPU |
ด้วยค่าตั้งต้นนี้ เวลากู้คืนสูงสุดเมื่อ worker ล่มกะทันหันอยู่ที่ราว 80 วินาที มาจากระยะ lease 20 วินาทีบวกรอบกระทบยอดสูงสุด 60 วินาที ด้านต้นทุนคิดจากการเขียน heartbeat เป็นหลัก AWS ประเมินไว้ที่ราว 65 ดอลลาร์ต่อเดือนแบบ on-demand หรือราว 10 ดอลลาร์แบบ provisioned สำหรับ 100 การเชื่อมต่อ และราว 1,300 ดอลลาร์กับ 190 ดอลลาร์ตามลำดับสำหรับ 2,000 การเชื่อมต่อ การยืดรอบ heartbeat หรือรอบกระทบยอดช่วยลดค่าใช้จ่ายได้ แต่แลกกับการกู้คืนที่ช้าลง
จุดที่ควรคิดเพิ่มก่อนนำไปใช้จริง
แพตเทิร์นนี้อาศัย conditional write และการหมดอายุของ lease เป็นหลัก บทความต้นฉบับไม่ได้ใช้ fencing token หรือหมายเลขกำกับรุ่นของสิทธิ์ ในความเห็นของทีมงาน สิ่งที่ควรคิดต่อคือช่วงสั้น ๆ ที่ worker ตัวเดิมยังไม่รู้ว่าเสียสิทธิ์ไปแล้ว เช่น ระหว่างเครือข่ายสะดุด ซึ่งอาจทำให้สองตัวส่งข้อมูลซ้ำกันชั่วครู่ ระบบปลายทางจึงควรรับข้อมูลซ้ำได้โดยไม่เสียหาย (idempotent) โดยใช้เลขลำดับอย่าง last_seq ที่ตารางเก็บไว้อยู่แล้วเป็นตัวตัดข้อมูลซ้ำ
แพตเทิร์นเดียวกันนี้ใช้ได้กับงานในไทยอีกหลายแบบ เช่น ระบบแชตกับลูกค้าแบบเรียลไทม์ ระบบติดตามรถขนส่ง หรือระบบรับข้อมูลจากอุปกรณ์ IoT ที่ต้องถือการเชื่อมต่อค้างไว้ และควรพิสูจน์ว่าการย้ายงานทำงานได้จริงด้วยการจำลองความล้มเหลว ดังที่สรุปไว้ในบทความทดสอบความทนทานของระบบด้วย SQS และ AWS FIS
ทีมงาน Smart Cyber Tech ย้ายระบบขึ้นคลาวด์และวางโครงสร้างพื้นฐานบน AWS Azure และ GCP รวมถึงออกแบบสถาปัตยกรรมที่ย้ายงานได้เองเมื่อเซิร์ฟเวอร์ล่ม ปรึกษาได้ที่ แบบฟอร์มติดต่อ
สรุปสาระสำคัญ
- ปัญหาของงานที่ต้องถือการเชื่อมต่อค้างไว้นาน ๆ
- lease คืออะไร
- วงจรชีวิตของ lease สี่ขั้น
แหล่งอ้างอิงเรียบเรียงจาก AWS Architecture Blog — Building resilient real-time streaming workers with Amazon DynamoDB leases —
อ่านบทความต้นฉบับภาพปก: AWS Architecture Blog · ลิขสิทธิ์ภาพเป็นของเจ้าของต้นฉบับ ใช้ประกอบการรายงานพร้อมอ้างอิงแหล่งที่มา
มีคำถามเพิ่มเติมเกี่ยวกับบทความนี้? เขียนหาเราได้ที่
info@smart-cyber-tech.com
บริการที่เกี่ยวข้องจากทีมงาน Smart Cyber Tech
แบ่งปันบทความนี้:
LINE
Facebook
X
ปรึกษาทีมของเรา