Sans-IO: नेटवर्क सेवाओं के लिए प्रभावी Rust का रहस्य
(firezone.dev)- Firezone, Rust का उपयोग करके Android फ़ोन, MacOS कंप्यूटर और Linux सर्वर पर स्केलेबल और सुरक्षित remote access बनाता है
- यह
connlibनाम की connection library से network connections और WireGuard tunnels को manage करता है - कई iterations के बाद टीम sans-IO डिज़ाइन तक पहुँची, जो तेज़ और गहन testing, गहरी customization और उच्च reliability देती है
connlib Rust में लिखा गया है और sans-IO डिज़ाइन का पालन करता है
- Rust की speed और memory safety की वजह से यह network services बनाने के लिए उपयुक्त है
- इसमें
tokioruntime,tungsteniteWebSockets,boringtunWireGuard implementation, औरrustlsसे API traffic encryption का उपयोग होता है - sans-IO डिज़ाइन, कई जगह sockets के जरिए bytes भेजने और पाने के बजाय, protocol को एक pure state machine के रूप में implement करता है
Rust का asynchronous model और "function coloring" बहस
- async functions को केवल दूसरी async functions के भीतर ही call किया जा सकता है
- अगर कोई function async function की गहराई में है, तो उसे call करने वाली सभी functions भी async बनानी पड़ती हैं
- इससे उन लोगों के लिए समस्या हो सकती है जो ऐसा code लिखना चाहते हैं जो dependencies के async होने या न होने से स्वतंत्र रहे
sans-IO का परिचय
- sans-IO का मुख्य विचार OOP दुनिया के dependency inversion principle जैसा है
- policy (क्या करना है) implementation details (कैसे करना है) पर निर्भर नहीं होनी चाहिए
- डेटा transmit करने के बजाय
Transmitstruct को emit किया जाता है
dependency inversion का उपयोग
- डेटा transmit करने के बजाय
Transmitstruct को emit किया जाता है - event loop side effects को implement करता है और वास्तव में
UdpSocket::sendको call करता है
state machine
- STUN binding request के state machine diagram में
SentऔरReceived, ये दो states होती हैं StunBindingstruct और संबंधित functions को define करके state machine implement की जाती है
event loop
- event loop, state machine को चलाता है और
poll_transmitतथाhandle_inputका उपयोग करके डेटा प्रोसेस करता है
time abstraction
- time-based आवश्यकताओं को संभालने के लिए
poll_timeoutऔरhandle_timeoutAPI का उपयोग किया जाता है
sans-IO के आधारभूत सिद्धांत
- sans-IO डिज़ाइन dependencies के async होने या न होने का निर्णय application पर छोड़ देता है
- sans-IO डिज़ाइन composition को आसान बनाता है, flexible API देता है, testing को सरल करता है, और Rust की क्षमताओं के साथ अच्छी तरह मेल खाता है
आसान composition
StunBindingका API अधिकांश network protocols पर लागू किया जा सकता है- Firezone की
snownetlibrary, ICE और WireGuard को जोड़कर ऐसा "जादुई" IP tunnel देती है जो network setup की परवाह किए बिना काम करती है
flexible API
- event loop खुद लिखने से code tuning संभव होती है और maintenance आसान हो जाता है
तेज़ testing
- sans-IO code में side effects नहीं होते, इसलिए इसकी testing बहुत आसान होती है
- Firezone में reference state machine implement करके
connlibकी वास्तविक state से तुलना करने वाले tests किए जाते हैं
edge cases और IO failures
- sans-IO डिज़ाइन protocol implementation को वास्तविक IO side effects से अलग करता है, जिससे edge cases और error handling आसान हो जाती है
Rust + sans-IO: क्या यह परफेक्ट मेल है?
- Rust ownership और mutability को स्पष्ट रूप से model करता है, इसलिए यह sans-IO डिज़ाइन के साथ अच्छी तरह फिट बैठता है
- sans-IO डिज़ाइन state changes को व्यक्त करने के लिए
&mutका खुलकर उपयोग करता है, औरasyncRust के विपरीत केवल synchronous API का उपयोग करता है
कमियाँ
- event loop खुद लिखने पर subtle bugs आ सकते हैं
- sequential workflows में अधिक code की आवश्यकता हो सकती है
- Rust community में sans-IO डिज़ाइन अभी व्यापक रूप से उपयोग नहीं होता
निष्कर्ष
- sans-IO code शुरुआत में अपरिचित लग सकता है, लेकिन इसकी आदत पड़ने पर यह बहुत आनंददायक होता है
- Rust, state machines को model करने के लिए बेहतरीन tools देता है
- sans-IO डिज़ाइन error handling को input processing का हिस्सा बनने के लिए मजबूर करता है, इसलिए यह networking code लिखने का सही तरीका महसूस होता है
GN⁺ की राय
- sans-IO डिज़ाइन, Rust के ownership model के साथ अच्छी तरह मेल खाता है और network protocol implementation के लिए बहुत उपयुक्त है
- event loop खुद लिखने से code की flexibility बढ़ती है और maintenance आसान होता है
- testing आसान होने से reliable code लिखने में बड़ी मदद मिलती है
- लेकिन Rust community में इसके व्यापक उपयोग की कमी के कारण संबंधित libraries कम हो सकती हैं
- नई तकनीक अपनाते समय learning curve और community support को ध्यान में रखना चाहिए
1 टिप्पणियां
Hacker News राय
Rust में async/await सिंटैक्स आने से पहले state machine को मैन्युअली implement करना पड़ता था
VT100 लाइब्रेरी लिखते समय Rust के encapsulation pattern की समस्या समझ में आई
channels का इस्तेमाल करके data भेजने वाले design से तुलना
Haskell ecosystem में logic और execution को अलग करने का एक विचार मौजूद है
tokio::select!call को कैसे encapsulate किया गया, इसका ज़िक्र नहीं हैRust के async functions state machine में compile होते हैं
state को expose करने से async functions 'pure' हो सकते हैं
Firezone एक शानदार tool है
अच्छा होगा अगर compiler async code को अपने-आप sans io में convert कर सके
लेख और comments पढ़कर लगा कि शायद hexagonal या ports/adapters architecture style को फिर से खोज लिया गया है
यह जानने की जिज्ञासा है कि क्या असली traffic gateway से होकर गुजरता है, या उसका इस्तेमाल सिर्फ connection setup के लिए होता है