Facebook Libra focus on Consensus (Part 2)
วันนี้เราจะมาศึกษาเรื่อง libra consensus กันต่อไปนะครับ อ้างอิงความเดิมจากตอนที่แล้วเรื่อง Facebook libra focus on Consensus (Part 1) และ Facebook Libra focus on create testnet-like ซึ่งเราได้รัน validators 4 node พร้อมกันเพื่อที่จะสามารถทำความเข้าใจขั้นตอนของการ consensus ได้อย่างถูกต้องต่อไป อย่างไรก็ตามเรามาสรุปความเข้าใจของ validators ทั้ง 4 node ที่เราสร้างกันอีกสักนิดนึงนะครับจะได้เห็นภาพเดียวกันชัดๆ
จากรูป overview system จะเห็นว่าเรามี validator ทั้งหมด 4 nodes ซึ่งทั้ง 4 nodes มีการเชื่อมต่อกันผ่าน port 6180 (validator network) นอกจากนี้เรายังมีการรัน client ที่ bash (ไม่ได้อยู่ใน docker) เพื่อ connect Node ไปที่ admission control ผ่าน port 8000 (IP address 172.18.0.13) แล้ว port 9101 (metrics) ล่ะเอาไว้ทำอะไร ? ดูจาก source code service_metrics.rs แล้วมีจำนวน request และจำนวน error ของแต่ละ gRPC server ดูแล้วน่าจะเป็นการวางแผนสำหรับ monitoring หรือ dashboard ที่จะดู healthy ของ node นั่นเองครับ
ในระหว่างเขียนบทความนี้ผมได้ทำการตรวจสอบ source code การใช้งาน port 9101 จึงพบว่ามีการสร้าง bench docker ที่จะทำการเชื่อมต่อไปที่ metrics_server_port เมื่อเร็วๆนี้ แต่มีการอ้างอิงถึง port 14297 (port เก่าที่ใช้อ้างอิงถึง metrics_server_port) จึงไม่รอช้าสร้าง PR#523 เพื่อช่วยป้องกันข้อผิดพลาดระหว่างทีมงานพัฒนา จากนั้นจึงทำการ build docker ทั้งหมดใหม่อีกครั้งเพื่อทดสอบ แต่ว่ายังไม่มีคำสั่ง run.sh เพื่อ run bench docker มาให้แฮะ… สงสัยว่าทีมงานพัฒนา libra จะยังทำงานส่วนนี้ไม่เสร็จ เพื่อไม่ให้เป็นการเสียเวลาเราค้างไว้ตรงนี้ก่อน แล้วปล่อยให้เขาทำงานของเขาไปก่อนละกันนะครับ 55+
อย่างไรก็ตาม เรากลับมาที่การทำความเข้าใจการ consensus กันต่อนะครับ โดยเริ่มด้วยการอ่าน log ที่ออกมาจาก validator (node IP 172.18.0.13) เพื่อเข้าใจภาพรวมของการทำงานกันก่อน
ตาม protocol แล้ว LocalPacemakerInner จะจัดการ ‘highest_certified_round’ ที่คอยเก็บข้อมูลจำนวนสูงสุดของ certified block ให้กับ validator ในแต่ละรอบการทำงาน (round) เมื่อมี QC (quorum certificate)ใหม่ที่มี round มากกว่าข้อมูล round ใน ‘highest_certified_round’ เจ้า local pacemaker จะเพิ่มค่า round และใช้ default timeout. *โดยปรกติแล้วทุกๆช่วงเวลา timeout local pacemaker จะเพิ่มค่า round และ doubles timeout.
เมื่อติดตาม source code ต่อไปจะเห็นว่า function process_outgoing_pacemaker_timeout ถูกเรียกเพราะว่ามีความต้องการส่ง message timeout เพื่อบอก replica หรือ node อื่นๆนั่นเอง ซึ่งในขั้นตอนนี้ replica จะหยุดการ vote สำหรับ round นี้และทำการ saves consensus state ของมันเองไว้ เหตุที่ต้องหยุดการ vote เพื่อให้มั่นใจว่า next proposer สามารถที่จะสร้าง proposal ที่สามารถจะทำการ vote ได้โดยทุกๆ replicas. ส่วนการ saving consensus state นั้นเพื่อให้มั่นใจว่าหาก restart, ทุกๆ replicas จะไม่ต้องเสียเวลาจัดการกับ rounds ก่อนหน้า
จุดที่น่าสนใจอีกจุดคือแล้วมันมีข้อความบอกว่า broadcasting new round to all replicas ว่าแต่มัน broadcasting อย่างไงกันนะ ?
Network component นั้นถูกออกแบบมาเพื่ออำนวยความสะดวกให้กับการทำ consensus และ shared mempool protocol โดยเฉพาะ ซึ่งมีการทำงานหลักๆ 2 อย่างคือ
- RPC: Remote Procedure Calls
- DirectSend: สำหรับการส่ง message ไปที่ผู้รับคนใดคนหนึ่ง ซึ่งเป็นการส่งโดยไม่จดจำ (fire-and-forget style)
ซึ่ง Network component ก็ถูกพัฒนาเป็น Actor model มี message คุยกันระหว่าง sub-components ด้วย tokio framwork อีกเช่นเคย ซึ่ง actor model มี sub-component ย่อยๆ ดังนี้
- Network provider: เป็น network API สำหรับ clients. มันจะคอย forwards requests จาก upstream clients ไปที่ downstream components และส่ง incoming RPC และ DirectSend requests ไปที่ upstream handler ที่เหมาะสม
- Peer Manager: คอยฟัง incoming connections และ dials จาก peers อื่นๆบน network. และมันจะช่วยแจ้งให้ components อื่นๆทราบเกี่ยวกับการ new/lost connections events และ demultiplexes incoming sub streams ไปให้ protocol handlers ที่เหมาะสมต่อไป
- Connectivity Manager: ทำให้มั่นใจว่าเราจะยังคงเชื่อมต่อกับแต่ละ node เฉพาะหากมันเป็น eligible member ของ network. ซึ่งมันจะได้รับ addresses ของ peers จาก discovery component และสั่ง dial/disconnect requests ไปที่ Peer Manager.
- Discovery: ใช้ push-style gossip สำหรับค้นพบ new peers และ updates addresses ของ existing peers. ทุกๆการ tick, มันจะทำการเปิด sub stream ใหม่ไปหา peer ที่ถูกสุ่มขึ้นมาและส่งสิ่งที่มันรับรู้ไปให้ peer. มันจะแจ้ง connectivity manager ให้ทราบหาก network มีการเปลี่ยนแปลงใดๆจาก inbound discovery messages.
- Health checker: จะทำการตรวจสอบ liveness เป็นช่วงเวลา (static timeout) เพื่อให้มั่นใจว่า peer/connections จะยังคงทำงานได้ดี
- Direct send: เปิดให้ ส่งหรือรับ messages ไปที่หรือมาถึง remote peers. ซึ่งมันจะแจ้ง upstream handler เมื่อมี inbound message.
- RPC: เปิดให้ ส่งหรือรับ RPC ไปที่หรือมาถึง peers อื่นๆ ซึ่งมันจะแจ้ง upstream handler เมื่อมี inbound RPC.
เอาล่ะครับหลังจากดูรายละเอียด Network component ที่คอยสนับสนุนขั้นตอนการทำงานของ Consensus กันจนพอเข้าใจบ้างแล้ว วันนี้ก็หมดเวลาอีกเช่นเคย หวังว่าจะเป็นประโยชน์ไม่มากก็น้อยครับ :)
บทความอื่นๆเกี่ยวกับการทำความเข้าใจ source code libra มีดังนี้ครับ
Facebook Libra on Windows is easy
Facebook Libra focus on account create
Facebook Libra focus on account mint
Facebook Libra focus on query balance
Facebook Libra focus on admission control (Part 1)
Facebook Libra focus on admission control (Part 2)
Facebook Libra focus on mempool