จากบทความเรื่อง From 15,000 database connections to under 100: DigitalOcean's tale of tech debt
ทำการอธิบายถึง Technical Debt หรือหนี้ทางเทคนิค
ที่ทาง DigitalOcean ได้สร้างมันขึ้นมา
แต่ว่าในช่วงแรกก็ต้องเลือกว่า เป้าหมายที่ต้องการคืออะไร
ระหว่างการ scale business หรือ technical
สิ่งที่ทาง DigitalOcean เลือกคือ การ scale ทาง business ก่อน
แน่นอนว่า ในวันที่มีคนใช้งานเพิ่มถึงจุดหนึ่ง
จะทำให้หนี้ที่สร้างไว้มันส่งผลกระทบออกมา
จึงต้องทำการแก้ไข มาดูเรื่องราวกัน
เริ่มต้นด้วยระบบงานจะมีโครงสร้างดังรูป
เป็นโครงสร้างที่เรียบง่ายไม่ซับซ้อน
พัฒนาในส่วนของ UI และ API ด้วย Rails
ส่วนของ backend ที่ใช้จัดการระบบ cloud พัฒนาด้วยภาษา Perl คือส่วนของ Scheduler และ DOBE
การติดต่อระหว่าง UI และ Backend จะผ่าน Message Queue
ซึ่งใช้งานบน MySQL database
MySQL database ทำ 2 หน้าที่คือ เก็บข้อมูล และ เป็น message broker
ขั้นตอนการทำงานเป็นดังนี้
- เมื่อผู้ใช้งานทำการสร้าง droplet ผ่าน UI
- UI จะส่งข้อมูลการสร้างไปยัง MySQL เพื่อ insert ข้อมูล
- ในฝั่ง scheduler ที่อยู่ backend จะทำการดึงข้อมูลจาก MySQL ทุก ๆ วินาที เพื่อดูว่ามีคำสั่งมาหรือไม่
- ถ้าเจอก็ข้อมูลใหม่ ก็จะทำการสร้าง droplet ตามการร้องขอนั้น ๆ
แสดงการทำงานดังรูป
ต่อมาในฝั่ง backend ก็เริ่มนำแนวคิด Microservices มาใช้งาน
เปลี่ยนจาก Perl มาเป็น Go
ติดต่อสื่อสารภายในกันผ่าน gRPC แทนที่ HTTPS
ส่วนตรงกลางยังเป็น MySQL เช่นเดิม
เมื่อเวลาผ่านไปตั้งแต่ปี 2012-2016 นั้น
เพิ่ม feature ต่าง ๆ เข้ามามากมาย
ส่งผลให้มีจำนวนผู้ใช้งานเพิ่มมากขึ้นถึง 10,000 %
ผลที่ตามมาคือ จำนวน connection ไปยัง MySQL database
จะเท่ากับจำนวนการสร้าง droplet เลย !!
ยังไม่พอยังมีชุดคำสั่ง SQL ที่เรียกว่า ลูกอีช่าง JOIN ถึง 18 table !!
ยิ่งก่อให้เกิดความซับซ้อน และ load database อย่างมาก
ซึ่งยากต่อการ scale และ ดูแลรักษา
ส่งผลให้ performance ของระบบแย่ลง
เมื่อมองกลับไปที่โครงสร้างที่ได้ทำกันมาแล้ว
พบว่าแต่ละส่วนงานผูกมัดกันมาก (Tight coupling)
มัน work ในช่วงเวลาหนึ่ง แต่เมื่อถึงอีกจุดหนึ่งมันไม่ work เสียแล้ว
แต่ละส่วนงานเกิดเป็นปัญหาคอขวดขึ้นมา
ดังนั้นจึงได้เวลา refactor ระบบแล้ว
มีเป้าหมายของการ refactor ดังนี้
- ลดจำนวนของ database connection ลง
- ปรับปรุงการทำงานของระบบ scheduler ให้มีความเสถียร
- แก้ไขปัญหาเรื่องของ messaging ซึ่งดันไปใช้ MySQL database
การแก้ไขปัญหาในส่วนของ Backend เพื่อลดจำนวน connection มายัง database
ด้วยการเพิ่มส่วนของ Proxy เรียกว่า Event router มาคั่นกลาง
แสดงดังรูป
ในส่วนของ Message Queue ก็เช่นกัน นำ RabbitMQ มาใช้แทน MySQL
โดยใช้ MySQL เก็บข้อมูลต่าง ๆ
ส่วน event จากฝั่ง UI ก็ใช้ RabitMQ ซะ เพราะว่ามันเก่งเรื่องนี้กว่ามาก
โดยมี API layer หรือ Microservices มาจัดการ droplet service ไปเลย
ส่งผลให้แต่ละส่วนงานทำงานแยกกันอย่างเป็นอิสระ
มีหน้าที่รับผิดชอบอย่างชัดเจน
เลือกใช้เครื่องมือให้เมาะกับงานนั้น ๆ และทำงานเดียวให้ดีไปเลย
ส่วนตรงไหนที่ก่อให้เกิดปัญหาคอขวดก็ทำการแก้ไข
ผลที่ตามมาคือ ระบบเอื้อต่อการ scale ของทั้ง busienss และ technical ด้วย
เราได้เรียนรู้อะไรจากบทความนี้บ้าง ?