Screen Shot 2557-05-15 at 12.10.12 AM

แปลบทความเรื่อง 4 Architecture Issues When Scaling Web Applications: Bottlenecks, Database, CPU, IO
เป็นบทความที่น่าสนใจ
เกี่ยวกับ 4  ประเด็นสำคัญสำหรับการออกแบบสถาปัตยกรรมของระบบ web application
ให้รองรับการขยายตัว และ การใช้งานที่สูงขึ้น
โดยมีเนื้อหาประกอบไปด้วยเรื่องต่างๆ ดังนี้

  1. Architecture bottlenecks ปัญหาคอขวดของสถาปัตยกรรมของระบบ
  2. Scaling database การขยายการรองรับการใช้งานฐานข้อมูล
  3. CPU bound application การใช้งาน CPU
  4. I/O bound application การใช้งาน I/O ( Input/Output )

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

Performance

ว่าด้วยเรื่องประสิทธิภาพของระบบ web application นั้น
มีตัวชี้วัดที่มากมาย แต่ส่วนใหญ่จะวัดกันในเรื่อง
response time และ scalability

โดย response time คือเวลาตั้งแต่การส่ง request ไปยัง server
และ server ส่ง response กลับมา
ซึ่งเวลาควรอยู่ในช่วงเวลาที่เหมาะสมตามที่กำหนดหรือคาดหวังไว้
เพื่อพิจารณาว่าระบบทำงานได้เร็วหรือช้า

ส่วน Scalability คือความสามารถในการขยายระบบเพื่อรองรับการใช้งาน
โดยการขยายมี 2 รูปแบบ คือ

  1. Scale up  หรือ Vertical คือ การเพื่อจำนวน CPU เพิ่มขนาดของ memory
  2. Scale out หรือ Horizontal คือ การเพิ่มจำนวน server เข้าไป หรืออุปกรณ์ต่างๆ เข้าไป

จากทั้งสองรูปแบบทำให้เกิดประเด็นขึ้นมาว่า
เราจะเลือกวิธีไหนดีล่ะ ?
ตรงนี้ต้องขึ้นอยู่กับระบบ องค์กร และ ทีม แล้วล่ะนะ !!

แต่มีคำพูดหนึ่งที่น่าคิดก็คือ

เมื่อใดก็ตามที่ต้องเพิ่มเครื่อง หรือขยายเครื่อง
มันบ่งบอกว่าสถาปัตยกรรมของระบบคุณมีปัญหาแล้วล่ะ
แต่หลายๆ คน มักมองข้ามจุดนี้ไปเสมอ

 

ทั้ง response time และ scalability นั้นควรที่จะทำให้มันสมดุลกัน
ไม่ใช่ให้น้ำหนักไปทางใดทางหนึ่งมากเกินไป
เป้าหมายเพื่อทำให้ระบบงานมีประสิทธิภาพที่ดี

สิ่งที่ควรทำคือ Capacity Planning

โดยต้องทำการวัดประสิทธิภาพด้วยการ Load testing บน product server
เพื่อทำให้รู้ว่าระบบที่พัฒนาด้วยโครงสร้างปัจจุบันสามารถรองรับ
จำนวนผู้ใช้งาน อัตราการเติบโตข้อมูลของระบบ
ถึงจำนวนเท่าไร เพื่อทำการวางแผนการขยายระบบไว้ได้

สถาปัตยกรรมที่สามารถขยายได้ง่ายเป็นอย่างไร

การออกแบบมักจะออกแบบโดยการแยกออกเป็นกลุ่มการทำงาน
เช่น web, application, load balance, database
ซึ่งเป็นการขยายแบบออกด้านข้าง หรือ Scale out นั่นเอง

สิ่งที่น่าสนใจคือการ Scale database

เนื่องจากหลายๆ องค์กรมักจะใส่ business logic
ไปไว้ใน database เช่นพวก store procedure, function
ทำให้เกิด overhead และ ความซับซ้อนที่สูงมาก
ดังนั้น พยายามทำให้ระบบมันง่ายที่สุดเท่าที่จะทำได้ เป็นดีที่สุด

การขยาย database หรือ RDBMS น่าจะเริ่มจากการออกแบบสถาปัตยกรรม
ในรูปแบบ Master-Slave ต่อจากนั้นก็ Multi-Master
ซึ่งรูปแบบทั้งคู่นั้นก็มีขีดความสามารถเช่นกัน
สามารถแก้ไขด้วยการแยก database ออกจากกัน

โดยมีรูปแบบการแยก database 2 แบบ คือ

1. Vertical Split หรือการทำ partitioning  คือการแยกออกในระดับ domain
แต่ในความเป็นจริงยังอยู่ที่เดียวกัน เช่น Customer database , Product database เป็นต้น

2. Horizontal Split หรือการทำ sharding เป็นการแยก database ออกจากกันในระดับ server กันเลย
เพื่อแยกข้อมูลแต่ละส่วนออกจากกัน เช่น
Customer database ของคนในทวีปเอเชีย
Customer database ของคนในทวีปยุโรป

แต่ในปัจจุบันไม่ได้มีเพียง RDBMS เท่านั้น
ยังมีสิ่งที่เรียกว่า NoSQL ให้ใช้งานกัน
ซึ่งถือว่าเป็นความท้าทายอย่างยิ่ง
สำหรับการออกแบบสถาปัตยกรรมระบบในปัจจุบัน

มาดูรูปแบบของสถาปัตยกรรมที่มักเกิดปัญหาคอขวด

1. Centralize component จะเป็นส่วนงานกลาง ที่ใช้งานเยอะ
และไม่สามารถขยายเพื่อรองรับจำนวนการใช้งานที่สูงขึ้นได้
มักจะมีความสามารถในการกำหนดจำนวนผู้ใช้งานสูงสุด

2. High latency component  จะเป็นส่วนการทำงานที่ใช้เวลาทำงานนานมาก
ส่งผลกับ response time โดยตรง
วิธีการแก้ไขสุด classic คือ เปลี่ยนให้มันทำงานแบบ asynchronous ซะ
เช่นการนำระบบ queue มาใช้ หรือใช้ batching/background แทน
แถวบ้านผมเขาเรียกว่า เป็นการสร้างปัญหาบนปัญหา

CPU bound application

เป็นระบบ ที่มีค่า throughput สูงสุดตามความเร็วของ CPU
ดังนั้นถ้าเกิดใช้งาน CPU หมด ก็ต้องทำการเพิ่ม CPU เข้าไป
เพื่อลดเวลาของ response time ลง

ระบบที่มักทำให้เกิด CPU bound ได้แก่

  • ระบบการประมวลผลข้อมูล โดยไม่ได้ใช้ I/O เช่น ระบบ Finance, Trading เป็นต้น
  • ระบบที่ใช้ข้อมูลจาก cache สูง
  • ระบบแบบ Asynchronous หรือพวก Non-blocking เช่น Reactive application และ NodeJS application

ดังนั้น ระบบควรที่จะมีการทำ profiling
ทำให้เห็นจุดที่เป็นปัญหาเพื่อแก้ไขต่อไป

ตัวอย่างการแก้ไขปัญหา CPU bound ได้แก่

  • การคำนวณข้อมูลต่างๆ ที่จะใช้งาน และเก็บไว้ใน caching ก่อน
  • แยกส่วนประมวลผลออกเป็น batching หรือ background job

I/O bound application

เป็นระบบ ที่มีค่า throughput สูงสุดตามความขนาดของ I/O หรือ network
ซึ่งแน่นอนว่าการเพิ่ม CPU เข้าไป มันไม่ได้ช่วยอะไรเลย
การแก้ไขนั้นก็ไม่ง่าย เนื่องจากมันเกี่ยวข้องกับระบบภายนอกเยอะมาก
เช่นการเพิ่มขนาดของ network เข้าไป จำเป็นต้องปิดระบบที่เกี่ยวข้อง

ตัวอย่างระบบที่ทำให้เกิดปัญหา I/O bound เช่น

  • ระบบ Streaming ที่ใช้ bandwidth ของ network เยอะมากๆ หรือใช้ทั้งหมด
    ทำให้ระบบไม่สามารถใช้งานได้ แนวทางการแก้ไขแรกเลยก็คือ restart ระบบเลย
  • ระบบที่ใช้งาน Database สูงๆ จะติดเรื่องจำนวน connection หรือ I/O ไปยัง database นั้นๆ

สรุปส่งท้าย

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

ยิ่ง feedback loop สั้นและเร็วมากขึ้นเท่าไร
ยิ่งจะทำให้เราเห็นข้อผิดพลาด และทำการแก้ไข ได้รวดเร็วมากขึ้นเท่านั้น
อะไรที่มันทำแล้วเจ็บปวด ก็ให้ทำบ่อยๆ ครับ อย่าไปกลัวมัน

ลองกลับไปดูว่า คุณใช้เวลาในการคุยเรื่องสถาปัตยกรรมมากหรือน้อยเท่าไร ???