สวัสดีครับ สำหรับในบทความนี้เราจะพาทุกคนไปทำความเข้าใจกับสิ่งที่สำคัญในการออกแบบระบบในปัจจุบันนั่นคือ การออกแบบระบบยังไงถึงจะรองรับผู้ใช้งานจำนวนมาก ๆ ได้ โดยการออกแบบระบบนี้เราจะเรียกว่า “ระบบที่รองรับการขยายตัว” หรือ “Scalability”
ทำไมเราการทำระบบที่ต้องสเกลได้?
การออกแบบระบบให้สามารถรองรับการสเกลได้ในปัจจุบันเป็นเรื่องที่สำคัญมากในแง่ของธุรกิจ เนื่องจากในปัจจุบันทุก ๆ อย่างเราขับเคลื่อนด้วยเทคโนโลยีเกือบทั้งหมด เข้าถึงลูกค้าผ่านทางแอปพลิเคชัน สินค้า บริการ รายได้ กำไร ความได้เปรียบทางการแข่งขันดังนั้นการออกแบบระบบที่ดี ทำให้รองรับการสเกล รองรับลูกค้าที่มากขึ้น ไม่พลาดโอกาสต่าง ๆ ในทางธุรกิจ เช่น หากเรานึกถึงการใช้งานในชีวิตประจำวันแอปขายของออนไลน์เจ้าต่าง ๆ ที่ทำให้เราเสียทรัพย์ไปตั้งแต่ต้นเดือน รอกดบัตรคอนเสิร์ต เว็บเหล่านี้คนมาใช้งานเป็นจำนวนพร้อม ๆ กันนั่นหมายความว่ารายได้ที่เข้าไปหาธุรกิจนั่นก็จะมหาศาล แต่ถ้าระบบไม่พร้อมรายได้ก็จะหายไปมหาศาลเช่นกัน นั่นเลยเป็นความสำคัญของการทำระบบให้รองรับการสเกลในเชิงธุรกิจ
มาดูในมุมของ Technical สำหรับสาย Dev และสาย Infra กันบ้าง การออกแบบระบบให้สามารถสเกลในอนาคตได้ง่ายนั้น สิ่งสำคัญเลยคือเราจะต้องมีการออกแบบให้ระบบยืดหยุ่น การออกแบบ แน่นอนว่าเราก็จะต้องมีสถาปัตกรรมมารองรับ โดยสถาปัตยกรรมในการทำ Software ที่รองรับการสเกลในยุคปัจจุบันนั้นมักหนีไม่พ้นกับเรื่องของ Microservices หรือ Modular Architecture ที่จะทำให้เราสามารถสร้างและปรับปรุงฟีเจอร์ใหม่ ๆ ได้อย่างง่ายดาย ลดข้อผิดพลาดที่จะทำให้ฟีเจอร์ใหม่ ไปกระทบกับทั้งระบบเวลาเกิดปัญหา เพราะสถาปัตกรรมเหล่านี้จะเน้นแบ่งการทำงานของแต่ละ service ออกเป็นส่วนย่อย ๆ ทำให้เป็นอิสระต่อกัน เวลาเกิดปัญหาก็สามารถแก้ไขได้ไว ไม่ส่งผลกับ service อื่น ๆ
ส่วนของการสเกลก็จะทำได้ง่ายเพราะหากมี service ไหนคนใช้เยอะ เราก็สเกลไปเป็นราย service ไม่ต้องสเกลระบบทั้งก้อน ซึ่งทำให้สิ้นเปลืองทั้งทรัพยากรและค่าใช้จ่าย ตัวอย่างเช่น หากระบบค้นหาสินค้าในเว็บไซต์ได้รับความนิยมมากกว่าบริการอื่น ๆ เราก็สามารถเลือกสเกลแค่ส่วนนี้โดยไม่ต้องสเกลทั้งระบบ
ซึ่งนอกจากนั้นการเลือกใช้แนวทางการออกแบบที่เหมาะสม อย่างเช่น CQRS (Command Query Responsibility Segregation) และ Event Sourcing ก็จะสามารถช่วยให้ระบบสามารถจัดการกับข้อมูลขนาดใหญ่ได้อย่างมีประสิทธิภาพ โดยแยกการเขียนและการอ่านข้อมูลออกจากกัน ช่วยลดภาระในบางส่วนของระบบที่อาจจะเป็นคอขวด (bottleneck) ในอนาคตได้
Horizontal Scaling
ภาพจาก : https://www.cloudzero.com/blog/horizontal-vs-vertical-scaling/
ซึ่งหากเราพูดถึงเรื่องของการสเกลแล้ว เราจะได้ยินกับการสเกลอยู่สองแบบ คือ สเกลแนวตั้ง (Vertical Scaling) และการสเกลแนวนอน (Horizontal Scaling) โดยหากเป็นทำระบบให้รองรับผู้ใช้งานเป็นจำนวนมาก ๆ นั้นส่วนใหญ่เราจะเน้นไปที่การทำ Horizontal Scaling
โดยการทำ Horizontal Scaling เป็นการเพิ่มจำนวนของเครื่องเซิร์ฟเวอร์ เพื่อเอามาช่วยรันช่วยทำงานหรือที่เราเรียกว่า “กระจายโหลด” ซึ่งจะต่างจากการสเกลแบบ Vertical Scaling ที่เป็นการเพิ่มทรัพยากรพวก CPU แรม พื้นที่จัดเก็บข้อมูล การสเกลแบบนี้จะเอาไว้สำหรับงานที่ต้องประมวลผลหนัก ๆ มากกว่าซึ่งข้อดีหลัก ๆ ของการทำ Horizontal Scaling จะมีความยืดหยุ่นกว่า เราสามารถปรับเพิ่มหรือลดจำนวนเครื่องได้ตามความใช้งานจริง ๆ ได้เลย
ตัวอย่างเช่น บริการของบริษัทใหญ่ ๆ อย่าง Facebook หรือ Netflix ต่างใช้ Horizontal Scaling เพื่อให้บริการกับผู้ใช้เป็นล้านหรือพันล้านคนทั่วโลก แน่นอนว่าเซิร์ฟเวอร์เครื่องเดียวไม่สามารถรองรับโหลดขนาดนี้ได้อยู่แล้ว
Load Balancing
เมื่อเรามีการสเกลแบบแนวนอนออกไปแล้ว จะเห็นได้ว่ามีเซิร์ฟเวอร์หลายตัวช่วยทำงาน แต่ request ที่เข้ามามันจะรู้ได้ยังไงว่าจะต้องไปทำงานที่ตัวไหน เราจะมีกลไลที่ชื่อว่า “Load Balancing” เอามาช่วยในการกระจายโหลดที่เข้ามาเยอะไปทำงานตามเซิร์ฟเวอร์ที่ต้องการ โดยถ้าถามว่ามันจะกระจายโหลดไปยังไง มันก็จะมีวิธีการให้เลือกใช้ได้หลายแบบดังนี้
- Round Robin – วิธีนี้จะเป็นการกระจาย request ที่เข้ามาไปให้เซิร์ฟเวอร์ทีละตามลำดับ เป็นเหมือนเป็นการแจกงานไปทีละคน วน ๆ ไปเรื่อย ๆ เมื่อ request ที่หนึ่งเข้ามาก็ไปที่เซิร์ฟเวอร์ A, request ถัดไปจะไปที่เซิร์ฟเวอร์ B แล้วต่อด้วยเซิร์ฟเวอร์ C และกลับไปที่ A อีกครั้งตามลำดับเลย ซึ่งวิธีนี้จะทำให้แต่ละตัวได้รับโหลดเท่า ๆ กัน
- Least Connections – ต่อมาจะเป็นวิธีที่ดูว่าเซิร์ฟเวอร์ตัวไหนทำงานน้อยที่สุดในตอนนั้น request ก็จะไปหาตัวนั้น เช่น เซิร์ฟเวอร์ A มีการเชื่อมต่อเยอะกว่าเซิร์ฟเวอร์ B, request ใหม่จะถูกส่งไปยังเซิร์ฟเวอร์ B เพื่อให้การกระจายงานมีประสิทธิภาพมากที่สุด
- IP Hash – วิธีนี้จะใช้ IP Address ของผู้ใช้มาทำการคำนวณ แล้วส่ง request ไปยังเซิร์ฟเวอร์เดิมทุกครั้ง เช่น หากผู้ใช้งานมี IP เดิม ระบบก็จะส่ง request ไปยังเซิร์ฟเวอร์เดิม ซึ่งจะเหมาะกับกรณีที่การให้บริการต้องมีการเก็บสถานะของผู้ใช้ (session persistence) อย่างเช่นเว็บไซต์ที่มีการล็อกอิน
- Weighted Round Robin – ส่วนนี้จะเป็นการปรับปรุงจากวิธี Round Robin โดยเซิร์ฟเวอร์ที่มีศักยภาพสูงกว่าจะได้รับโหลดมากกว่าเซิร์ฟเวอร์ที่มีศักยภาพต่ำกว่า เช่น หากเซิร์ฟเวอร์ A มีประสิทธิภาพสูงกว่าเซิร์ฟเวอร์ B, เซิร์ฟเวอร์ A ก็จะได้รับการแจก request มากกว่า วิธีนี้ช่วยให้การใช้งานทรัพยากรของเครื่องได้อย่างมีประสิทธิภาพมากขึ้น
ทั้งหมดนี้เป็นเพียงแค่ตัวอย่างอัลกอริทึมที่เราสามารถใช้ทำ Load Balancing แต่ในการใช้งานยังมีวิธีการให้เราเลือกใช้ตามความเหมาะสมกับโปรเจกต์ได้อีกเพียบ และ ในทางปฏิบัติ เราสามารถใช้เทคโนโลยี Load Balancer เช่น NGINX, HAProxy หรือบริการจากผู้ให้บริการคลาวด์อย่าง AWS Elastic Load Balancing เพื่อช่วยกระจายการทำงานไปยังหลายเซิร์ฟเวอร์ และยังช่วยให้สามารถจัดการทราฟฟิกได้อย่างมีประสิทธิภาพในกรณีที่มีปริมาณงานสูงผิดปกติ เช่น ช่วงลดราคาในเทศกาลได้
Event-Driven Architecture
อีกสถาปัตยกรรมที่สำคัญสำหรับการออกแบบระบบให้สเกลได้ดีคือ “Event-Driven Architecture (EDA)” โดย EDA จะเป็นสถาปัตยกรรมที่ขับเคลื่อนด้วยเหตุการณ์ (event) เมื่อมีการเปลี่ยนแปลงหรือการกระทำบางอย่างเกิดขึ้นในระบบ ข้อมูลจะถูกส่งมาในรูปแบบของ event จาก producer (แหล่งที่สร้างเหตุการณ์) ไปยัง consumer (ผู้ที่รับและประมวลผลเหตุการณ์นั้น ๆ)
ยกตัวอย่างจากชีวิตจริง เช่นตอนที่เรากดสั่งอาหารผ่านแอป
Producer (ผู้สร้างเหตุการณ์): เรา Event (เหตุการณ์): รายการสั่งซื้อถูกส่งไปที่ร้านอาหาร Consumer (ผู้รับเหตุการณ์): ร้านอาหารที่รับคำสั่งซื้อ แล้วเตรียมอาหาร และส่งต่อให้คนส่งอาหาร
โดยเราจะเห็นได้ว่าการใช้ EDA จะทำให้เราสามารถแยก service แต่ละส่วนออกจากกันได้ แถมไม่ต้องต่อไว้แบบ real time ทำงานเฉพาะตอนที่มี event เหมือนมีคนมาปลุก ตอนที่มีลูกค้ามา ไม่มีก็แอบงีบได้ แบบนี้ก็จะทำให้บาง service ถ้าไม่มีคนใช้ก็ไม่ต้องรัน service ไหนคนใช้เยอะ ๆ ก็สเกลออกไป แบบนี้จะทำให้เราทำระบบที่สเกลได้ตรงจุด และยืดหยุ่นขึ้น แถมถ้ามีบาง service เสียก็จะไม่กระทบกับ service อื่น ๆ อีกด้วย
ตัวอย่างระบบที่ใช้ EDA เช่น ระบบ E-Commerce ที่ต้องรับมือกับการสั่งซื้อสินค้าจำนวนมาก สามารถใช้ EDA ในการรับ event การสั่งซื้อ (purchase event) จากผู้ใช้ จากนั้นข้อมูลการสั่งซื้อจะถูกส่งไปยัง service ที่เกี่ยวข้อง เช่น service ที่ทำหน้าที่คำนวณสต็อกสินค้า, ระบบการชำระเงิน, และระบบจัดส่งสินค้า ทำให้ทุก service ทำงานได้อย่างอิสระและทำงานไปพร้อม ๆ กันได้ โดยเครื่องมือที่มักใช้ในการสร้าง EDA ที่นิยในปัจจุบันนี้ก็จะเป็น Apache Kafka, RabbitMQ, และ AWS EventBridge ซึ่งทั้งหมดนี้ช่วยในการจัดการและส่ง event ไปยังบริการต่าง ๆ ได้อย่างมีประสิทธิภาพ
มาดูว่า Netflix ออกแบบระบบที่รองรับผู้ใช้งานจำนวนมากยังไง?
สำหรับการออกแบบระบบที่รองรับผู้ใช้งานจำนวนมากได้ดีและมีประสิทธิภาพ แอดขอยกของ Netflix มาให้ดูกันเลย โดยเดิมที Netflix ใช้ระบบแบบ Monolithic ที่รวมทุกฟังก์ชันไว้ในระบบเดียว แต่เมื่อผู้ใช้เพิ่มมากขึ้น Netflix ได้มีการเปลี่ยนสถาปัตยกรรมของระบบมาเป็น Microservices โดยทำการแยกฟังก์ชันออกเป็นส่วนย่อย ๆ เช่น ระบบแนะนำ (Recommendation), ระบบชำระเงิน (Billing) และระบบจัดการผู้ใช้ (User Management) เพื่อที่จะใช้ความสามารถของการทำ Microservices ที่จะทำให้แต่ละส่วนสามารถสเกลได้อย่างอิสระ ลดปัญหาคอขวดในการทำงาน แค่นั้นยังไม่พอ Netflix ได้มี CDN ของตัวเองชื่อว่า Open Connect ซึ่งมีการวางเซิร์ฟเวอร์ใกล้กับผู้ใช้งานในหลายพื้นที่ทั่วโลก การออกแบบนี้ช่วยลดความหน่วง (Latency) และเพิ่มประสิทธิภาพในการสตรีมมิ่ง ทำให้เราดูซีรีย์กันได้แบบลื่นไหล ไม่ว่าจะมีคนใช้งานมากแค่ไหนก็ตาม
สรุป
จากบทความนี้เราก็ได้เห็นความสำคัญของการออกแบบระบบให้รองรับการสเกลกันไปแล้วว่ามันสำคัญสำหรับธุรกิจแค่ไหน ธุรกิจเราจะโตต้องโตแบบไม่สะดุด อย่าให้หยุดที่เซิร์ฟล่มตอนลูกค้าเยอะ เพราะนั่นอาจจะหมายถึงการสูญเสียลูกค้า สูญเสียประสบการณ์การใช้งานที่ดีกับธุรกิจของเราไปเลย ดังนั้นการใช้งานสถาปัตยกรรมอย่าง Microservices, Event-Driven Architecture และการทำ Horizontal Scaling รวมถึงการเลือกใช้เทคโนโลยีที่เหมาะสมสำหรับการจัดการโหลดอย่าง Load Balancer ล้วนเป็นแนวทางที่ช่วยให้ระบบสามารถรองรับการขยายตัวได้ดียิ่งขึ้น การเรียนรู้และเข้าใจเรื่องการออกแบบระบบที่สเกลได้จึงเป็นสิ่งที่ไม่ควรมองข้ามนั่นเอง
สามารถอ่าน Case study ของ Netflix เพิ่มเติมได้ที่ 😊