การสาธิตการออกแบบระบบ
ผู้ชม
บทความนี้เป็นบทความถัดไปในชุดของฉันเกี่ยวกับวิธีที่ฉันจะออกแบบแอปพลิเคชันยอดนิยม ขอแนะนำ (แม้ว่าจะไม่จำเป็นทั้งหมด) ให้อ่านโพสต์ก่อนหน้านี้ที่ฉันรวบรวมไว้อย่างเป็นประโยชน์ในรายการ "ที่นี่"
เราคาดว่าจะมีความคุ้นเคยขั้นพื้นฐานเกี่ยวกับหลักการสถาปัตยกรรมและ AWS แต่หวังว่าวิศวกรส่วนใหญ่เข้าถึงโพสต์นี้ได้
การโต้แย้ง
ขั้นแรก มาดูคำชี้แจงปัญหาของเรากัน
ระบบการออกแบบ
เราหวังที่จะออกแบบแพลตฟอร์มวิดีโอตามความต้องการ เช่น "YouTube" หรือ "Netflix" เป็นไปได้ยากที่คุณจะไม่เคยพบสิ่งเหล่านี้มาก่อน แต่ในกรณีที่คุณไม่เคยพบเห็น หลักฐานก็คือผู้ใช้สามารถอัปโหลดหรือดูวิดีโอออนไลน์ได้ ข้อกำหนดที่แน่นอนคือ:
- เราควรจะสามารถอัปโหลดวิดีโอได้
- เราควรจะสามารถดูวิดีโอได้
- เราควรจะสามารถค้นหาตามชื่อวิดีโอได้
เราจะเพิกเฉยต่อความจริงที่ว่าคุณไม่สามารถอัปโหลดวิดีโอไปยัง Netflix ได้ เว้นแต่คุณจะเป็นสตูดิโอผลิตภาพ ลองจินตนาการว่าคุณคือ Quentin Tarantino
วิธีการ
เรามีแนวทางมาตรฐานในการออกแบบระบบ ซึ่งมีการอธิบายอย่างละเอียดในบทความ ที่นี่ อย่างไรก็ตาม มีขั้นตอนโดยสรุปดังนี้:
- การชี้แจงข้อกำหนด: ตรวจสอบให้แน่ใจว่าเรามีข้อมูลทั้งหมดก่อนที่จะเริ่มต้น ซึ่งอาจรวมถึงจำนวนคำขอหรือผู้ใช้ที่เราคาดหวัง
- การประมาณค่าด้านหลังซองจดหมาย:ทำการคำนวณอย่างรวดเร็วเพื่อประเมินประสิทธิภาพของระบบที่จำเป็น ตัวอย่างเช่น เราต้องการพื้นที่เก็บข้อมูลหรือแบนด์วิธเท่าใด
- การออกแบบอินเทอร์เฟซระบบ:ระบบของเราจะมีลักษณะอย่างไรเมื่อมองจากภายนอก ผู้คนจะมีปฏิสัมพันธ์กับระบบอย่างไร โดยทั่วไปนี่คือสัญญา API
- การออกแบบโมเดลข้อมูล:ข้อมูลของเราจะมีลักษณะอย่างไรเมื่อเราจัดเก็บ ณ จุดนี้ เราอาจกำลังคิดถึงโมเดลเชิงสัมพันธ์และโมเดลที่ไม่เชิงสัมพันธ์
- การออกแบบเชิงตรรกะ:ประกอบเข้าด้วยกันในระบบที่หยาบกร้าน! ณ จุดนี้ ฉันกำลังคิดในระดับ 'ฉันจะอธิบายแนวคิดของฉันให้คนที่ไม่รู้เกี่ยวกับเทคโนโลยีได้อย่างไร'
- การออกแบบทางกายภาพ:ตอนนี้เราเริ่มกังวลเกี่ยวกับเซิร์ฟเวอร์ ภาษาการเขียนโปรแกรม และรายละเอียดการใช้งาน เราสามารถวางสิ่งเหล่านี้ทับการออกแบบเชิงตรรกะได้
- ระบุและแก้ไขจุดคอขวด:ในขั้นตอนนี้ เราจะมีระบบที่ใช้งานได้! ตอนนี้เราปรับปรุงการออกแบบ
ด้วยที่กล่าวว่ามาติดกันเถอะ!
การชี้แจงข้อกำหนด
ลองคิดถึงคำถามเบื้องต้นบ้าง ในตอนแรก ฉันสงสัยว่าขนาดสูงสุดและขนาดเฉลี่ยของวิดีโอคือเท่าใด จากนั้น ฉันจะคิดถึงจำนวนผู้ใช้และอัตราส่วนการอ่าน/เขียน/การค้นหา
นอกจากนี้ ไคลเอนต์ใช้อุปกรณ์/ความเร็วการเชื่อมต่อใด เราอาจจำเป็นต้องปรับรูปแบบและขนาดไฟล์ให้เหมาะสมตามสิ่งนี้
การประมาณค่าด้านหลังของซองจดหมาย
สมมติว่าเรามีผู้ใช้ 100 ล้านคน (จริงๆ แล้วน่าจะมากกว่านั้น!) อ่านและเขียนในอัตราส่วนรายวัน 100:1 ขนาดไฟล์โดยเฉลี่ยคือ 1GB สำหรับ HD และขนาดไฟล์สูงสุดคือ 50GB (ไม่สำคัญว่าจะแม่นยำแค่ไหน)
ซึ่งหมายความว่าเราจะมีความจุคร่าวๆ 100,000,000 * 1GB = 100PB/d
สำหรับการอัปโหลดเท่านั้น! เราสามารถทำงานได้ในคำขอต่อวินาทีตามความยาววิดีโอโดยเฉลี่ย แต่ก็ปลอดภัยที่จะบอกว่าเรากำลังจัดการกับข้อมูลจำนวนมาก!
นี่เป็นระบบระดับโลกด้วย ดังนั้นเราจึงสรุปได้ว่าเราจะใช้อุปกรณ์ที่แตกต่างกันมากมาย ตั้งแต่อุปกรณ์พกพาไปจนถึงอุปกรณ์ฝังตัว บนเครือข่ายที่หลากหลาย ดังนั้นเราจะต้องออกแบบในเชิงป้องกันสำหรับสิ่งนี้
การออกแบบส่วนต่อประสานระบบ
เมื่อได้เรียนรู้เพิ่มเติมเล็กน้อยเกี่ยวกับระบบของเราแล้ว เราก็สามารถตัดสินใจได้ว่าต้องการโต้ตอบกับระบบอย่างไร การโต้ตอบมีสามประเด็นหลัก
- อัปโหลดวิดีโอ
- ดาวน์โหลดวิดีโอ
- ค้นหา
การอัปโหลดวิดีโอจะดำเนินการผ่าน HTTP สิ่งหนึ่งที่เราต้องระวังคือขนาดของไฟล์ ในสถานการณ์อื่น เราอาจใช้ "FTP" แต่เนื่องจากเรามีผู้ใช้แบบสุ่มบนอินเทอร์เน็ต นี่จึงไม่สมเหตุสมผลเลย
สิ่งที่ฉันอยากจะแนะนำให้ทำคือการสร้างแบบฟอร์มเริ่มต้นเพื่อส่งข้อมูลเมตาที่เกี่ยวข้องกับไฟล์ (ชื่อ แท็ก สิ่งใดก็ตามที่ไม่ใช่ตัววิดีโอ) ซึ่งจะส่งคืน GGUID ที่เกี่ยวข้องกับไฟล์
จากนั้นเราสามารถใช้ JavaScript File และ Blob APIs เพื่อ ตัดไฟล์วิดีโอและส่งคำขอบางส่วน โดยมีส่วนหัว Content-Range แสดงถึงช่วงไบต์ที่คำขอนี้เป็นตัวแทน ประเภทเนื้อหาของเราจะเป็น application/octet-stream
และเซิร์ฟเวอร์มีหน้าที่รับผิดชอบในการประกอบชิ้นส่วนต่างๆ เข้าด้วยกัน
ซึ่งหมายความว่าเราจำเป็นต้องมีจุดสิ้นสุดสำหรับการสร้างไฟล์ POST
ที่จุดสิ้นสุด /file
ซึ่งสร้างออบเจ็กต์ไฟล์ใหม่ที่มีข้อมูลเมตา และจุดสิ้นสุดอีกจุดหนึ่งที่ POST
file/{id}/chunk
ซึ่งอนุญาตให้ผู้ใช้สามารถโพสต์ส่วนข้อมูลได้
สิ่งที่เราคิดได้อีกอย่างก็คือการแฮชไฟล์บนไคลเอนต์ จากนั้นเปรียบเทียบแฮชหลังจากที่เราประกอบไฟล์บนเซิร์ฟเวอร์อีกครั้ง เพื่อให้แน่ใจว่าตรงกัน
การดาวน์โหลดสามารถใช้ "คำขอช่วง HTTP" ได้ ซึ่งช่วยให้เราสามารถขอบางส่วนของวิดีโอได้ในแต่ละครั้ง (ส่งคืน 206
) ซึ่งหมายความว่าเราสามารถขอส่วนวิดีโอแบบไดนามิกตามที่เราต้องการ การใช้ GET file/{id}/chunk
กับส่วนหัวของ Content-Range อาจเป็นวิธีแก้ปัญหาหนึ่ง
โชคดีที่การค้นหานั้นง่ายกว่าเล็กน้อย เราสามารถ GET
ถึง /search?title=<search title>
และรับรหัสตอบกลับตามปกติ
การออกแบบตัวแบบข้อมูล
ตอนนี้เรามีไอเดียแล้วว่าเราจะโต้ตอบกับระบบของเราอย่างไร ลองคิดถึงประเภทของข้อมูลที่เราต้องการจัดเก็บกัน บางส่วนจะขึ้นอยู่กับไบต์ของวิดีโอ และบางส่วนจะขึ้นอยู่กับข้อมูลเมตา
ขั้นแรกลองคิดถึงไฟล์. ไฟล์สามารถมีข้อมูลมากมายเก็บไว้รอบๆ ไฟล์ เช่น ชื่อ วันที่สร้าง ผู้ใช้ที่อัปโหลด จำนวนการเข้าชม เป็นต้น
ไฟล์
id BIGINT PRIMARY KEY title VARCHAR
ตอนนี้เราต้องคิดถึงไฟล์ชิ้นของเรา จำไว้ว่าเราจำเป็นต้องให้บริการกับเครือข่ายและอุปกรณ์มากมาย! ซึ่งหมายความว่าเราจะต้องการจัดเก็บชิ้นส่วนในคุณภาพและรูปแบบไฟล์ที่แตกต่างกันมากมาย ด้วยการมาถึงของพื้นที่จัดเก็บอ็อบเจ็กต์ เช่น AWS S3 เราสามารถอ้างอิงได้ว่าไฟล์ของเราอยู่ที่ใดใน S3
ก้อน
id BIGINT PRIMARY KEY file_id BIGINT FOREIGN KEY REFERENCES file(id) format VARCHAR quality BIGINT order BIGINT location VARCHAR
จากข้อมูลข้างต้น เราสามารถระบุได้ว่าไฟล์ชิ้นใดเป็นของไฟล์ รูปแบบของชิ้นข้อมูล ขนาดของชิ้นข้อมูล และบิตของไฟล์ที่ชิ้นส่วนนั้นเป็นตัวแทน
นี่เป็นแกนหลักของโมเดลข้อมูลของเรา มาดูการออกแบบเชิงตรรกะกันดีกว่า!
การออกแบบเชิงตรรกะ
เราสามารถอธิบายการออกแบบเชิงตรรกะเพื่อนำส่วนประกอบต่างๆ มารวมกันได้ เมื่อผู้ใช้ต้องการอัปโหลดไฟล์ พวกเขาจะส่งคำขอไปยังบริการไฟล์เพื่อสร้างข้อมูลเมตาของไฟล์ใหม่ จากนั้นเบราว์เซอร์จะแบ่งไฟล์ออกเป็นชิ้นๆ และอัปโหลดไปยังบริการเขียนไฟล์แบบก้อน
บริการแยกไฟล์นี้มีหน้าที่รวบรวมไฟล์จากไคลเอนต์ให้เป็นไฟล์เดียว ตรวจสอบ และแยกไฟล์ออกเป็นไฟล์ต่าง ๆ ที่เครื่องเล่นสื่อใช้งานได้มากขึ้น
จากที่นี่ เราจะยืนหยัดอยู่ในคิวเพื่อให้เรามีความยืดหยุ่นอีกชั้นหนึ่งในกรณีที่บริการเข้ารหัสไฟล์ล่ม ตอนนี้ข้อความตอบรับสามารถส่งคืนให้กับผู้ใช้ได้แล้ว เรามีไฟล์แล้ว เราแค่ต้องดำเนินการกับมัน
บริการเข้ารหัสไฟล์จะใช้ส่วนของไฟล์และแปลงเป็นรูปแบบและคุณภาพที่แตกต่างกันสำหรับบริการต่างๆ จุดที่น่าสนใจที่ควรทราบคือมีความแตกต่างระหว่างการเข้ารหัสและการแปลงรหัส
- การแปลงรหัส: การสร้างไฟล์ในขนาดต่างๆ
- การเข้ารหัส: การเข้ารหัสไฟล์อีกครั้งในรูปแบบอื่น
การเข้ารหัสครอบคลุมถึงการแปลงรหัส ซึ่งเป็นสาเหตุที่เราใช้คำนี้ในที่นี้
บริการนี้มีหน้าที่รับผิดชอบในการเขียนส่วนข้อมูลของเราลงในพื้นที่จัดเก็บ ตลอดจนอัปเดตข้อมูลเมตาของไฟล์ของเราด้วยตำแหน่งของไฟล์เหล่านั้น
คำขออ่านจะต้องดำเนินการผ่าน API Gateway เช่นกัน แต่จะถูกเปลี่ยนเส้นทางไปยังบริการอ่านกลุ่มไฟล์ของเราแทน หากคำขอดังกล่าวร้องขอให้สตรีมวิดีโอ หรือบริการไฟล์ของเราหากคำขอเหล่านั้นกำลังมองหาข้อมูลเมตา
ลูกค้าจะต้องรับผิดชอบในการพิจารณาว่าไฟล์ชิ้นใดที่พวกเขาต้องการ และส่งคำขอที่จำเป็นออกไปเพื่อโหลดส่วนถัดไป
ฟังก์ชั่นการค้นหาควรจะตรงไปตรงมา บริการไฟล์จะเพิ่มข้อมูลเมตาของไฟล์ลงในเครื่องมือค้นหา ดังนั้นบริการค้นหาจึงมีหน้าที่แปลงจากการสืบค้น URL ไปเป็นสิ่งที่เราใช้กับเครื่องมือค้นหาได้ จากนั้นจึงรวบรวมคำตอบ
การออกแบบทางกายภาพ
ตอนนี้เราได้กล่าวถึงแนวคิดคร่าว ๆ เกี่ยวกับวิธีการรวมแพลตฟอร์มของเราเข้าด้วยกันแล้ว มาทำให้เนื้อหาเป็นสิ่งที่จับต้องได้ในโลกแห่งความเป็นจริงกัน
แม้ว่าในขณะที่ฉันกำลังเขียนอยู่ ฉันก็ยังเห็นปัญหาหลายประการเกี่ยวกับการออกแบบนี้ อย่างไรก็ตาม มาสำรวจกันดีกว่าและเราสามารถปรับแต่งมันได้ในส่วนถัดไป
ในตอนแรก บริการแบบคงที่ทั้งหมดของเราใช้ AWS ECS มีข้อโต้แย้งว่าเราอาจใช้งานแบบไร้เซิร์ฟเวอร์โดยสิ้นเชิงได้ แต่ความรู้สึกของฉันคือเราไม่ต้องการกังวลเกี่ยวกับเวลาเริ่มต้นที่เย็น เกตเวย์ของเราคือ เกตเวย์ AWS API และคิวของเราใช้ SQS
เราจัดเก็บชิ้นส่วนของเราไว้ใน S3 และใช้ AWS Elemental MediaConvert สำหรับการเข้ารหัสของเรา เครื่องมือค้นหาคือ "Amazon OpenSearch"
การระบุและการแก้ไขคอขวด
เราได้กล่าวถึงการปรับปรุงประสิทธิภาพบางอย่างที่เราสามารถทำได้ ในตอนแรก ฉันกำลังมุ่งเน้นไปที่ปริมาณข้อมูลที่เราได้รับ เราจำเป็นต้องมีระบบที่ยืดหยุ่นซึ่งสามารถจัดการกับข้อมูลจำนวนมากได้แบบเรียลไทม์ ฟังดูเหมือนเป็นงานสตรีมมิ่ง
จากแผนภาพ คุณจะเห็นว่าตอนนี้ API Gateway ของเราเขียนไปยัง "Kinesis stream" ซึ่งจะพุชไปที่ "AWS EMR" (อาจเปิด Spark Streaming ไว้) เพื่อประมวลผลและจัดกลุ่มไฟล์ของเราใหม่
เนื่องจากข้อมูลเมตาของไฟล์ของเราจะไม่ค่อยเปลี่ยนแปลง เราจึงสามารถเพิ่มเลเยอร์แคชให้กับบริการการอ่านของเราได้ด้วย
นอกจากนี้เรายังสามารถใช้ "การสตรีมบิตเรตแบบปรับได้" ซึ่งครอบคลุมเป็นอย่างดีในบทความที่เชื่อมโยง ในโปรแกรมเปลี่ยนไฟล์ของเรา เราได้สร้างไฟล์ชิ้นเดียวกันแต่มีคุณภาพต่างกันออกไป การใช้เทคนิคนี้ทำให้เราสามารถส่งชิ้นส่วนคุณภาพที่แตกต่างกันตามปฏิกิริยา โดยขึ้นอยู่กับสถานะปัจจุบันของการเชื่อมต่อของสตรีมเมอร์
ส่วนสุดท้ายของการปรับให้เหมาะสมคือการเพิ่ม CDN เนื่องจากเราจะมีผู้ใช้ทั่วโลก เราจึงไม่ต้องการให้ทุกคนพยายามเข้าถึงวิดีโอของตนจากเซิร์ฟเวอร์ในสหราชอาณาจักร เป็นเรื่องสมเหตุสมผลที่จะพยายามเผยแพร่เนื้อหาของเราให้ใกล้กับจุดที่พวกเขาอยู่มากขึ้น โปรดทราบว่า Netflix มีวิธีแก้ไขปัญหาของตัวเองที่เรียกว่า "Open Connect" ซึ่งคุ้มค่าแก่การดู!
บทสรุป
โดยสรุป เราได้กล่าวถึงวิธีการออกแบบแพลตฟอร์มสไตล์ YouTube หรือ Netflix แล้ว ควรตระหนักว่ามี "เครื่องมือจำนวนหนึ่งที่ Netflix พัฒนาขึ้นมาโดยเฉพาะ" สำหรับปัญหานี้
ตัวอย่างบางส่วนได้แก่:
- Zuul: เกตเวย์แอปพลิเคชัน
- Hystrix (เลิกใช้แล้ว): เบรกเกอร์
- ยูเรก้า: การค้นพบบริการ
- ปลอมตัว: ตัวประสานไคลเอนต์ HTTP
ตรวจสอบพวกเขาออก!