Discord เปิดตัวมาตั้งแต่ปี 2015 โดยสองหนุ่ม Jason Citron กับ Stan Vishnevskiy เป็นคนก่อตั้ง แอพนี้เจ๋งตรงที่เราสามารถสลับไปมาระหว่างแชทข้อความ คุยเสียง หรือวิดีโอคอลได้แบบไม่มีสะดุด ทำให้รู้สึกเหมือนคุยกันแบบธรรมชาติมากๆ ตอนนี้มีคนใช้ทั่วโลกมากกว่า 100 ล้านคนต่อเดือนเลยนะ แต่ละวันมีคนคุยกันบน Discord รวมกันเป็นเวลา 4 พันล้านนาที ผ่าน server กว่า 6.7 ล้านแห่งเลย โคตรเยอะ!
จริงๆ แล้ว Discord ใช้ภาษาที่ชื่อ Elixir เป็นหัวใจหลักของระบบแชทตั้งแต่วันแรกเลย ตอนที่เริ่มใช้ Discord ยังเป็นแค่บริษัทเล็กๆ ที่กำลังพยายามสร้างธุรกิจให้อยู่รอด มีคำถามและความท้าทายเยอะแยะเต็มไปหมด แต่ Elixir นี่แหละที่ช่วยให้พวกเขามีความยืดหยุ่นพอที่จะเติบโตและขยายระบบให้รองรับคนใช้จำนวนมหาศาลได้
เริ่มต้นด้วยภาษาอะไรบ้าง??
ในปี 2015 Discord เลือกใช้ภาษาหลักๆ สองตัว คือ Elixir กับ Python โดยให้ Elixir ดูแลส่วนที่เรียกว่า WebSocket gateway ซึ่งทำหน้าที่ส่งข้อความและอัพเดทข้อมูลแบบเรียลไทม์ ส่วน Python ก็ดูแลในส่วนของ API
ทุกวันนี้ API ที่เขียนด้วย Python เป็นแบบ monolith (แบบก้อนใหญ่ก้อนเดียว) ในขณะที่ระบบ Elixir แยกออกเป็นบริการย่อยๆ ประมาณ 20 services,
Mark Smith จากทีม Discord อธิบายง่ายๆ ว่า: "เพราะ services ที่ใช้ Elixir ต้องรับมือกับข้อมูลเข้าออกเยอะกว่า เราเลยออกแบบให้แต่ละ services สามารถ scale ได้อิสระจากกัน"
Discord ยังได้ลองเล่นกับภาษาอื่นๆ ด้วย เช่น Go กับ Rust แต่ผลลัพธ์ต่างกันมาก พวกเขาเลิกใช้ Go ไปเลยหลังจากลองไม่นาน แต่กลับพบว่า Rust เข้ากับทีมได้ดี โดยเฉพาะความสามารถในการทำงานร่วมกับ Elixir และ Python ได้อย่างราบรื่น
รองรับการสื่อสารระดับใหญ่ได้ไง??
การสื่อสารที่มีประสิทธิภาพสำคัญมากเมื่อต้องรองรับคนเป็นล้านที่เชื่อมต่อพร้อมกัน ลองนึกภาพ server ดังๆ อย่าง Fortnite หรือ Minecraft ที่มีสมาชิกเกือบ 600,000 คน ในบางช่วงอาจมีคนออนไลน์พร้อมกันมากกว่า 200,000 คนใน server เดียว ถ้ามีคนเปลี่ยนชื่อผู้ใช้ Discord ต้องส่งข้อมูลนี้ไปให้ทุกคนที่กำลังออนไลน์อยู่ทราบ
ตัวเลขการใช้งานน่าทึ่งมาก ๆ นะ มีคนใช้พร้อมกันมากกว่า 12 ล้านคนในทุก server รวมกัน มีการส่งข้อมูล WebSocket มากกว่า 26 ล้าน event ต่อวินาทีไปยังผู้ใช้ และทั้งหมดนี้ขับเคลื่อนด้วย Elixir ทั้งนั้น
"In terms of real time communication, the Erlang VM is the best tool for the job."
"ถ้าพูดถึงการสื่อสารแบบเรียลไทม์ Erlang VM คือเครื่องมือที่เจ๋งที่สุดเลย!"
— Jake Heinz, วิศวกรซอฟต์แวร์อาวุโส
เมื่อมีคนถามว่า "ทำไมถึงเลือก Elixir?" Jake Heinz ตอบตรงๆ ว่า: "สำหรับการสื่อสารแบบเรียลไทม์ Erlang VM คือตัวที่ใช่ที่สุด มันยืดหยุ่นมาก มีเครื่องมือดีๆ และเหมาะมากสำหรับสร้างระบบแบบกระจาย"
ในแง่เทคนิค ภาษานี้เข้ากับงานได้ดีมาก แต่ก็ยังเป็นการเสี่ยงในปี 2015 เพราะ "Elixir เวอร์ชัน 1.0 เพิ่งออกมาหมาดๆ เราเลยไม่รู้ว่าภาษานี้จะไปทางไหน แต่โชคดีมาก เราชอบมากกับทิศทางที่ภาษานี้พัฒนาและชุมชนที่เติบโตขึ้นมา"
ทีมที่ดูแลระบบแชท
เพื่อรองรับระบบข้อความแชททั้งหมด Discord ใช้คลัสเตอร์เครื่อง Elixir ประมาณ 400-500 เครื่อง แต่รู้อะไรไหม มันเจ๋งตรงที่ทีมโครงสร้างพื้นฐานแชทของ Discord มี software engineer แค่ 5 คนเท่านั้น! ใช่แล้ว วิศวกรแค่ 5 คนดูแลบริการ Elixir มากกว่า 20 บริการที่รองรับคนใช้หลายล้านคนพร้อมกัน และส่งข้อความเป็นสิบๆ ล้านข้อความต่อวินาที
Discord ยังใช้ Elixir ในส่วนควบคุมของระบบเสียงและวิดีโอด้วย (เรียกว่า signaling) ซึ่งทำให้ผู้ใช้สามารถสื่อสารกันได้ ส่วนการส่งข้อมูลมีเดียใช้ C++ ทั้งหมดนี้ทำงานบนเครื่องมากกว่า 1,000 เครื่อง
บริการ Elixir ต่างๆ สื่อสารกันผ่าน Distributed Erlang ซึ่งเป็นโปรโตคอลการสื่อสารที่มากับ Erlang Virtual Machine ปกติแล้ว Distributed Erlang จะสร้างเครือข่ายแบบ fully meshed (ทุกโหนดเชื่อมต่อกับทุกโหนด) แต่คุณก็ตั้งค่าให้ Erlang VM ปล่อยให้คุณจัดการเครือข่ายเองได้ โดยใช้ตัวเลือก -connect_all false ทีม Discord ใช้ตัวเลือกนี้เพื่อสร้างเครือข่ายแบบ partially meshed และใช้ etcd ในการค้นหาบริการและจัดการการตั้งค่าที่ใช้ร่วมกัน
นักพัฒนาในทีมแชทไม่ได้เป็นคนเดียวที่ยุ่งกับโค้ด Elixir, Mark Smith บอกว่านี่เป็นส่วนสำคัญของวัฒนธรรม Discord: "เราไม่ได้แบ่งแยกการทำงาน นักพัฒนา Python อาจต้องมาแก้โค้ด Elixir บ้างเวลาทำฟีเจอร์ใหม่ เราจะวางแผนฟีเจอร์ด้วยกัน ดูความต้องการในการรองรับขนาด แล้วพวกเขาก็ทำ pull request มา เราก็จะรีวิวและช่วยปรับแก้ให้"
ชุมชนและความท้าทาย
เพื่อให้ทำงานได้ในขนาดนี้ Discord ได้เรียนรู้วิธีใช้พลังของ Erlang VM ชุมชน และรู้ว่าเมื่อไหร่ที่ควรหาทางแก้เอง
ตัวอย่างเช่น Discord ใช้ Cowboy สำหรับจัดการการเชื่อมต่อ WebSocket และ TCP server เพื่อจัดการกับข้อมูลที่ทะลักเข้ามาและควบคุมโหลด เช่น back-pressure และ load-shedding พวกเขาใช้ GenStage ซึ่งเคยพูดถึงในรายละเอียดมาแล้ว
บางครั้ง บริษัทกับชุมชนก็ช่วยเหลือกัน เช่นตอนที่ Discord ใช้โปรเจค Rustler ซึ่งเป็นตัวเชื่อมระหว่าง Elixir กับ Rust เพื่อรองรับผู้ใช้ที่ออนไลน์พร้อมกัน 11 ล้านคน พวกเขาใช้ Rustler เพื่อเชื่อมโครงสร้างข้อมูลที่สร้างใน Rust เข้ากับบริการ Elixir โดยตรง
แต่ทีมยืนยันชัดเจนว่าตัวหลักคือแพลตฟอร์ม Erlang ทุกครั้งที่ต้องพัฒนาระบบให้ดีขึ้น พวกเขาไม่เคยรู้สึกว่าเทคโนโลยีเป็นอุปสรรค ตรงกันข้าม engineer สามารถสร้างโซลูชันที่มีประสิทธิภาพรองรับขนาดของ Discord ได้เสมอ ส่วนมากใช้โค้ดแค่ไม่กี่ร้อยบรรทัด และ Discord ก็มักจะแบ่งปันโปรเจคเหล่านี้กลับคืนสู่ชุมชนด้วย อย่างเช่น Manifold และ ZenMonitor
ทีม Discord ปรับตัวเร็วมากเมื่อมีปัญหา เช่น พวกเขาเคยลองใช้ Mnesia ในการผลิตสองครั้ง (Mnesia เป็นฐานข้อมูลที่มากับไลบรารีมาตรฐานของ Erlang) พวกเขาลองทั้งโหมดถาวรและโหมดหน่วยความจำ แต่โหนดฐานข้อมูลมักจะตามไม่ทันเมื่อเกิดปัญหา บางครั้งก็ไม่สามารถกลับมาทันเลย สุดท้ายเลยเลิกใช้ Mnesia ไปเลย แล้วสร้างฟังก์ชันที่ต้องการด้วยเครื่องมือพื้นฐานของ Erlang อย่าง GenServer และ ETS แทน ปัจจุบันพวกเขาแก้ปัญหาพวกนี้ได้ภายใน 2-3 วินาทีเท่านั้น
การเชี่ยวชาญ Elixir
เชื่อมั้ย? ไม่มีวิศวกรคนไหนในทีมแชทที่มีประสบการณ์กับ Elixir มาก่อนเข้าบริษัทเลย ทุกคนเรียนรู้ไปพร้อมกับการทำงาน Matt Nowack กับ Daisy Zhou เล่าว่าตอนแรกพวกเขางงมากว่าบริการทั้งหมดสื่อสารกันยังไง Matt บอกว่า: "ตอนแรกมันยากมากที่จะเชื่อการรับประกันที่ Erlang VM ให้ไว้ ฉันกังวลเรื่อง data races กับปัญหาการทำงานพร้อมกันที่จริงๆ แล้วมันเกิดขึ้นไม่ได้เลย"
แต่สุดท้ายพวกเขาก็เชื่อใจระบบและพบว่าตัวเองทำงานได้มีประสิทธิภาพและพึ่งพาแพลตฟอร์มได้มากขึ้น Matt เสริมว่า: "เครื่องมือตรวจสอบของ Erlang VM เยี่ยมมาก เราดู process ไหนในคลัสเตอร์ก็ได้และดูคิวข้อความของมัน เราใช้ remote shell เชื่อมต่อกับโหนดไหนก็ได้และแก้บั๊กระบบไลฟ์ได้เลย พวกนี้ช่วยเรามาหลายครั้งมากๆ"
การทำงานในขนาดของ Discord เพิ่มความท้าทายในการเรียนรู้ภาษา เพราะต้องคุ้นเคยกับแนวคิด concurrency, distribution และ fault-tolerance ทุกวันนี้ framework อย่าง Nerves และ Phoenix ช่วยจัดการเรื่องพวกนี้ให้นักพัฒนา แต่โครงสร้างพื้นฐานก็ยังมีให้ engineer ที่ต้องการสร้าง stack เองอย่างทีม Discord
Jake สรุปว่า Elixir และ Erlang VM สำคัญกับ Discord ขนาดไหนและเปลี่ยนตัวเขาเองยังไง: "สิ่งที่เราทำใน Discord จะเป็นไปไม่ได้ถ้าไม่มี Elixir มันทำไม่ได้ด้วย Node หรือ Python แน่ๆ เราไม่มีทางสร้างระบบนี้ด้วยวิศวกรแค่ 5 คนถ้าใช้ C++ การเรียนรู้ Elixir เปลี่ยนวิธีคิดและการแก้ปัญหาซอฟต์แวร์ของฉันไปเลย มันให้มุมมองใหม่และวิธีแก้ปัญหาแบบใหม่ที่ฉันไม่เคยนึกถึงมาก่อน"