9 पॉइंट द्वारा GN⁺ 2024-11-01 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • Robinhood Dropbox की आंतरिक load balancing सेवा है, जिसे 2020 में deploy किया गया था
  • यह servers के बीच internal traffic को route करके service load को संतुलित रूप से distribute करती है
  • Robinhood से पहले, Dropbox की अधिकांश सेवाएं backends के बीच असंतुलित load distribution की समस्या झेल रही थीं
  • hardware differences और पिछले load balancing algorithms की सीमाओं के कारण overloaded instances से reliability issues पैदा होते थे
  • इसे हल करने के लिए service fleet को जरूरत से ज्यादा provision करना पड़ता था, जिससे hardware cost बढ़ती थी

Robinhood की नई क्षमताएं

  • PID (Proportional-Integral-Derivative) controller का उपयोग करके load imbalance को और तेज़ी और प्रभावी तरीके से manage करना संभव हुआ
  • इससे infrastructure reliability में सुधार हुआ और hardware cost में उल्लेखनीय कमी आई
  • latest intelligent features को चलाने वाले बढ़ते AI workloads के साथ GPU resources की प्रभावी demand management पहले से कहीं अधिक महत्वपूर्ण हो गई है

Dropbox में load balancing की चुनौतियां

  • Dropbox का service discovery system दुनिया भर के कई data centers में फैले लाखों hosts तक scale कर सकता है
  • Dropbox की कुछ सेवाओं के पास millions of clients हैं, लेकिन हर client को सभी server instances से connect करने की अनुमति नहीं दी जा सकती
    • क्योंकि इससे servers पर बहुत अधिक memory pressure पड़ता है, और server restart के समय TLS handshake के कारण server overload हो सकता है
  • इसके बजाय, service discovery system हर client को connect करने के लिए servers का एक subset देता है
  • clients के लिए उपलब्ध सबसे अच्छा load balancing strategy यह है कि वे service discovery system से मिले address list पर round robin करें
    • लेकिन इस तरीके से हर server instance पर load काफी असंतुलित हो सकता है
    • subset size बढ़ाना एक आसान mitigation है, लेकिन इससे imbalance पूरी तरह खत्म नहीं होता और service owners के लिए बस एक और parameter जुड़ जाता है
  • इससे भी गहरी समस्या यह है कि अगर हर server को समान संख्या में requests भेजी जाएं, तब भी underlying hardware हर server पर अलग हो सकता है
    • यानी requests अलग-अलग hardware classes पर अलग मात्रा में resources consume करती हैं
  • मुख्य बात यह है कि clients के पास server load की visibility नहीं होती
  • पहले इस समस्या को हल करने के लिए यह कोशिश की गई थी कि servers response headers में load attach करें
    • clients address subset में सबसे कम loaded endpoint चुनकर खुद load balancing कर सकते थे
    • नतीजे promising थे, लेकिन फिर भी कुछ कमियां थीं
      • special load header के लिए server और client, दोनों तरफ code changes चाहिए थे, इसलिए इसे global level पर अपनाना मुश्किल था
      • नतीजे अच्छे थे, लेकिन पर्याप्त अच्छे नहीं थे

Robinhood बनाने का फैसला

  • 2019 में Robinhood बनाने का औपचारिक निर्णय लिया गया
  • यह नई सेवा मौजूदा internal service discovery system के ऊपर बनाई गई, जो servers से load information collect करती है और उसे routing information के साथ attach करती है
  • Robinhood Envoy की Endpoint Discovery Service का उपयोग करके load information को endpoint weights में integrate करता है, ताकि clients weighted round robin कर सकें
  • gRPC community Envoy xDS protocol अपना रही थी, इसलिए Robinhood Envoy और gRPC clients, दोनों के साथ compatible है
  • उस समय Dropbox की requirements को पूरा करने वाला कोई existing load balancing solution नहीं था, इसलिए नई सेवा बनाने का निर्णय लिया गया

Robinhood के परिणाम

  • production environment में कई वर्षों के उपयोग के बाद इसने promising results दिखाए
  • कुछ large-scale services में fleet size को 25% तक घटाने में सफलता मिली, जिससे हर साल hardware cost में उल्लेखनीय बचत हुई
  • अत्यधिक उपयोग में आने वाली processes कम हुईं, जिससे reliability भी बेहतर हुई

Robinhood का architecture

  • हर data center में Robinhood instances deploy किए जाते हैं, और ये load balancing service, proxy, और routing database—इन तीन हिस्सों से मिलकर बने होते हैं

Load Balancing Service (LBS)

  • Robinhood का core
  • load information collect करना और endpoint weights के साथ routing information generate करना इसका काम है
  • कई instances एक ही समय पर किसी service के routing information को update करते हैं, इसलिए internal shard manager का उपयोग करके हर service के लिए primary worker assign किया जाता है
  • क्योंकि हर service स्वतंत्र है, LBS को service-by-service partition करके horizontally scale किया जा सकता है

Proxy

  • service की load information को data center के भीतर संबंधित LBS partition तक route करने का काम करता है
  • proxy का उपयोग करने से direct connections की संख्या भी कम की जा सकती है जो LBS process तक जाती हैं
    • proxy न हो तो हर LBS process को infrastructure के हर node से connect होना पड़ेगा
    • इसके बजाय LBS process केवल proxies से connect करते हैं, जिससे LBS पर memory pressure काफी कम हो जाता है
  • proxy केवल उसी data center के nodes से connect करते हैं, इसलिए इन्हें horizontally scale किया जा सकता है
  • यह pattern infrastructure के कई हिस्सों में services को बहुत अधिक TLS connections receive करने से बचाने के लिए इस्तेमाल होता है

Routing Database

  • यह ZooKeeper/etcd आधारित database services की routing information store करता है, जैसे host names, IP addresses, और LBS द्वारा generated weights
  • ZooKeeper और etcd node/key changes को real time में सभी watchers तक पहुंचा सकते हैं, और Dropbox के read-heavy service discovery use case के लिए बहुत उपयुक्त हैं
  • ZooKeeper/etcd द्वारा दी जाने वाली eventual consistency service discovery के लिए भी पर्याप्त है

Load Balancing Service को विस्तार से देखना

  • load balancing का लक्ष्य यह है कि सभी nodes की utilization average utilization के बराबर हो
  • PID controller का उपयोग करके हर node की utilization को average utilization के लगभग समान रखा जाता है
  • LBS हर node के लिए एक PID controller बनाता है और average utilization को setpoint के रूप में उपयोग करता है
  • LBS PID controller के output को endpoint weight के delta के रूप में उपयोग करता है और service के सभी endpoints के बीच weights को normalize करता है
  • नए node को average utilization तक converge करने में कुछ adjustment cycles लगते हैं, लेकिन PID controller load balancing के लिए बहुत प्रभावी है

LBS operation scenarios

  • LBS को इस तरह design किया गया है कि यह node restart से लेकर missing load reports तक, load balancing को प्रभावित करने वाले कई scenarios को handle कर सके
  • optimal performance बनाए रखने के लिए LBS ऐसे exception cases को handle करने की कई strategies लागू करता है

LBS startup

  • LBS load information और PID controller state को memory में रखता है
  • LBS restart के दौरान यह तुरंत weight updates शुरू नहीं करता, बल्कि load reports आने तक थोड़ी देर wait करता है
  • PID controller weights के मामले में, LBS routing database से endpoint weights पढ़कर उन्हें restore करता है

Cold Start nodes

  • service fleet में नए nodes अक्सर जुड़ते रहते हैं, इसलिए Thundering Herd समस्या को रोकना महत्वपूर्ण है
  • क्योंकि नए node की initial utilization आमतौर पर 0 होती है, LBS नए node का weight कम endpoint weight पर set करता है और PID controller को node को average utilization तक लाने देता है

Missing load reports

  • distributed systems environment में failures आम बात हैं
  • network congestion या hardware failure के कारण कुछ nodes की load reports में देरी हो सकती है या वे पहुंच ही नहीं सकतीं
  • weight update के दौरान LBS ऐसे nodes को skip कर देता है, इसलिए उन nodes के endpoint weights में बदलाव नहीं होता
  • लेकिन अगर बड़ी संख्या में load reports missing हों, तो average utilization calculation inaccurate हो सकती है
  • सुरक्षा के लिए, LBS इस स्थिति में weight update step को पूरी तरह skip कर देता है

Utilization metrics

  • CPU utilization Dropbox में सबसे व्यापक रूप से इस्तेमाल किया जाने वाला load balancing metric है
  • जिन services में CPU bottleneck नहीं है, उनके लिए in-flight requests की संख्या एक अच्छा वैकल्पिक measurement है
  • LBS को CPU और/या in-flight requests के आधार पर load balancing support करने के लिए implement किया गया है

Limitations

  • PID controller एक feedback loop बनाता है ताकि node utilization को target value (average utilization) के करीब रखा जा सके
  • जिन services में traffic बहुत कम हो, या बहुत high-latency requests हों जिन्हें minutes में measure किया जाता हो, वहां feedback बहुत कम मिलता है, इसलिए load balancing प्रभावी नहीं होता
  • high-latency requests वाली services को asynchronous होना चाहिए

Data centers के बीच routing

  • LBS instances data center के भीतर load balancing संभालते हैं
  • data centers के बीच routing के लिए अलग considerations होते हैं
    • उदाहरण के लिए, request round-trip time कम करने के लिए requests को सबसे नजदीकी data center तक route करना बेहतर होता है
  • इसके लिए locality configuration पेश की गई, जो target data centers के बीच traffic split को define करती है

लोड बैलेंसर परफ़ॉर्मेंस मूल्यांकन

  • लोड बैलेंसिंग परफ़ॉर्मेंस को max/avg अनुपात से मापा जाता है
    • यदि सेवा मालिक CPU-आधारित लोड बैलेंसिंग चुनता है, तो maxCPU/avgCPU को परफ़ॉर्मेंस मेट्रिक के रूप में इस्तेमाल किया जाता है
    • सेवा मालिक आम तौर पर नोड्स के बीच अधिकतम उपयोग दर के आधार पर सेवा को प्रोविजन करते हैं, क्योंकि लोड बैलेंसिंग का मुख्य उद्देश्य fleet size को कम करना है
  • PID controller लोड बैलेंसिंग रणनीति max/avg अनुपात को 1 के करीब बनाए रख सकती है

लोड बैलेंसिंग परफ़ॉर्मेंस मूल्यांकन ग्राफ

  • Envoy proxy clusters में सबसे बड़े cluster के max/avg CPU और p95/avg CPU को दिखाने वाला ग्राफ
    • PID controller-आधारित लोड बैलेंसिंग सक्षम करने के बाद दोनों मेट्रिक्स 1 के करीब गिर गए
    • max/avg अनुपात 1.26 से घटकर 1.01 हो गया, जो 20% सुधार दिखाता है
  • नोड-वार CPU उपयोग के quantile analysis को दिखाने वाला ग्राफ
    • PID controller-आधारित लोड बैलेंसिंग सक्षम करने के बाद max, p95, avg, p5 लगभग एक ही लाइन में मिल गए
  • database frontend clusters में सबसे बड़े cluster के max/avg CPU और p95/avg CPU को दिखाने वाला एक और ग्राफ
    • PID controller-आधारित लोड बैलेंसिंग सक्षम करने के बाद दोनों मेट्रिक्स 1 के करीब गिर गए
    • max/avg अनुपात 1.4 से घटकर 1.05 हो गया, जो 25% सुधार दिखाता है
  • नोड-वार CPU उपयोग के quantile analysis को दिखाने वाला एक और ग्राफ
    • PID controller-आधारित लोड बैलेंसिंग सक्षम करने के बाद max, p95, avg, p5 फिर से लगभग एक ही लाइन में मिल गए

Config Aggregator बनाने की वजह

  • Robinhood सेवा मालिकों को चुनने के लिए कई विकल्प देता है और बदलावों को dynamically लागू भी कर सकता है
  • सेवा मालिक codebase के भीतर service directory में सेवा के लिए Robinhood configuration बनाते और अपडेट करते हैं
  • ये settings configuration management service में स्टोर की जाती हैं, जो Robinhood configuration में बदलावों को real time में प्राप्त करने के लिए एक सुविधाजनक library है
  • लेकिन कुछ समस्याओं के कारण codebase से Robinhood के mega configuration को नियमित रूप से build और push करना संभव नहीं था
    • यदि configuration push के जरिए बदलाव आते हैं, तो rollback button दबाना जोखिम भरा होता है
      • क्योंकि यह पता नहीं होता कि पिछली push के बाद कितनी अन्य सेवाएँ बदल चुकी हैं
    • Robinhood को संभालने वाली टीम हर mega configuration push की भी जिम्मेदार होती है
      • इसका मतलब है कि Robinhood टीम को हर बदले हुए configuration push में शामिल होना पड़ता है, जो engineering time की बर्बादी है
      • क्योंकि ज़्यादातर incidents सेवा मालिक खुद हल कर सकते हैं
    • संभावित जोखिम को कम करने के लिए हर push को कई data centers में deploy करने में कई घंटे लगते हैं
  • इन समस्याओं को हल करने के लिए Config Aggregator नाम की एक और छोटी service बनाई गई

Config Aggregator

  • Config Aggregator सभी service-specific configurations को इकट्ठा करता है और LBS द्वारा इस्तेमाल किए जाने वाले mega configuration को बनाता है
  • Config Aggregator service-specific configurations को monitor करता है और बदलावों को real time में mega configuration तक propagate करता है
  • Config Aggregator एक tombstone फीचर भी देता है, ताकि किसी service की Robinhood configuration गलती से delete न हो जाए
    • यदि कोई सेवा मालिक Robinhood configuration से service हटाने वाला बदलाव push करता है, तो Config Aggregator service entry को तुरंत हटाने के बजाय उसे tombstone के रूप में mark करता है
    • वास्तविक removal कुछ दिनों बाद होता है
    • यह फीचर Robinhood configuration और अन्य routing configurations (जैसे Envoy configuration) के अलग-अलग push cycles से पैदा होने वाली race condition को भी हल करता है
  • configuration management service की कमी यह है कि इसमें अभी version control नहीं है
  • इस स्थिति के लिए कि LBS configuration को किसी known good state में वापस ले जाना पड़े, mega configuration का समय-समय पर backup लिया जाता है

Migration रणनीति

  • एक ही बार में लोड बैलेंसिंग रणनीति बदलना जोखिम भरा हो सकता है
  • यही वजह है कि Robinhood में किसी service के लिए कई लोड बैलेंसिंग रणनीतियाँ configure की जा सकती हैं
  • Dropbox में percentage-based feature gate है, इसलिए एक hybrid strategy लागू की गई, जिसमें client endpoint weight के रूप में दोनों लोड बैलेंसिंग रणनीतियों से बने weights का weighted sum इस्तेमाल करते हैं
  • इससे सभी clients endpoint के लिए एक ही weight allocation देखते हुए नई लोड बैलेंसिंग रणनीति पर धीरे-धीरे migrate कर सकते हैं

सीखी गई बातें

  • Robinhood को design और implement करते समय क्या काम करता है और क्या नहीं, इस बारे में कुछ अहम सबक मिले
  • simplicity को प्राथमिकता देकर, client changes को न्यूनतम रखकर, और शुरुआत से migration की योजना बनाकर, LBS के development और deployment को सरल बनाया जा सका और महंगी गलतियों से बचा जा सका

configuration जितना संभव हो उतना सरल होना चाहिए

  • Robinhood ने सेवा मालिकों के लिए configure किए जा सकने वाले कई विकल्प पेश किए
  • लेकिन ज़्यादातर मामलों में उन्हें सिर्फ दिया गया default setting ही चाहिए होता है
  • अच्छा और सरल default configuration (या उससे भी बेहतर, बिल्कुल configuration न होना) बहुत सारा engineering time बचा सकता है

client बदलाव भी सरल ही रखें

  • internal clients में बदलाव rollout करने में कई महीने लग सकते हैं
    • ज़्यादातर deployments हर हफ्ते push होते हैं, लेकिन कई deployments महीने में एक बार या कई सालों तक बिल्कुल deploy नहीं होते
  • जितने ज़्यादा बदलाव LBS में ले जाए जा सकें, उतना बेहतर है
    • उदाहरण के लिए, शुरुआत में client design में weighted round robin इस्तेमाल करने का फैसला किया गया था, और उसके बाद इसे बदला नहीं गया
    • इससे गति काफ़ी बढ़ गई
  • ज़्यादातर बदलाव LBS तक सीमित रखने से reliability risk भी घटता है
    • क्योंकि ज़रूरत पड़ने पर LBS के बदलावों को कुछ ही मिनटों में rollback किया जा सकता है

migration की योजना project design चरण में ही बनानी चाहिए

  • migration में बहुत बड़ी मात्रा में engineering time लगता है
  • इसमें stability risk भी होते हैं जिन पर विचार करना पड़ता है
  • यह मज़ेदार काम नहीं है, लेकिन बहुत महत्वपूर्ण है
  • नई service design करते समय, मौजूदा use cases को नई service में सहज रूप से migrate करने का तरीका जितनी जल्दी हो सके सोचना चाहिए
  • सेवा मालिकों से जितनी ज़्यादा चीज़ें माँगी जाएँगी, migration उतना ही दुःस्वप्न बन जाएगा
    • खासकर core infrastructure components के मामले में यह और भी सही है
  • Robinhood का migration process शुरुआत से अच्छी तरह design नहीं किया गया था, इसलिए process को फिर से implement करने और configuration को फिर से design करने में अपेक्षा से कहीं अधिक समय लगा
  • migration के लिए आवश्यक engineering time सफलता का एक मुख्य संकेतक होना चाहिए

Robinhood का प्रभाव

  • production environment में लगभग 1 साल के बाद अब यह कहा जा सकता है कि Robinhood के नवीनतम iteration ने Dropbox की लंबे समय से चली आ रही लोड बैलेंसिंग चुनौतियों को प्रभावी ढंग से हल किया
  • इसके core PID controller algorithm ने उत्साहजनक नतीजे दिखाए और सबसे बड़ी सेवाओं में उल्लेखनीय परफ़ॉर्मेंस सुधार दिखाया
  • Dropbox के पैमाने पर लोड बैलेंसिंग service को design और operate करने के बारे में मूल्यवान insights मिले

टिप्पणियाँ

  1. मान लें कि N, M, s क्रमशः servers की संख्या, clients की संख्या, और address subset के आकार को दर्शाते हैं। किसी server से जुड़ने वाले clients की संख्या binomial distribution B(M, s/n) के sample का अनुसरण करती है। जैसा पहले बताया गया, clients service discovery द्वारा दिए गए address set पर simple round robin करते हैं। इसलिए यदि हर client लगभग समान मात्रा में requests भेजता है, तो server-side load distribution binomial distribution के समान होता है।

  2. मौजूदा service discovery system को बढ़ाकर gRPC xDS protocol (A27) का समर्थन किया जाता है। इस ब्लॉग के लिखे जाने की तारीख तक gRPC clients control plane के endpoint weights के लिए weighted round robin का समर्थन नहीं करते थे, इसलिए earliest deadline first scheduling पर आधारित एक custom weighted round robin picker लागू किया गया।

  3. एक दिलचस्प मामला सामने आया जिसमें service कभी-कभी degraded I/O के कारण अटक जाती थी। ऐसी स्थिति में उस node का CPU कम बना रहता है, और LBS node का weight बढ़ाकर CPU को औसत तक लाने की कोशिश करता है, जिससे dead spiral शुरू हो जाती है। समाधान के रूप में CPU और in-flight requests के maximum को load measurement की तरह इस्तेमाल कर सेवा को balance किया गया।

GN⁺ की राय

  • Robinhood, Dropbox की load balancing चुनौतियों को प्रभावी ढंग से हल करने वाली एक बेहतरीन सेवा लगती है। PID controller का उपयोग विशेष रूप से प्रभावशाली है।
  • यह एक अच्छा उदाहरण है जो दिखाता है कि बहुत बड़े पैमाने की global infrastructure में load balancing कितना कठिन काम है। hardware के अंतर, असंतुलित load distribution, network congestion जैसी कई बातों पर विचार करना पड़ता है।
  • यह महत्वपूर्ण लगता है कि सभी components को इस तरह design किया जाए कि वे आपस में जैविक रूप से जुड़े हुए तरीके से काम करें। LBS, proxy, और routing DB अलग-अलग हैं, लेकिन real time में एक-दूसरे के साथ घनिष्ठ रूप से interact करते हैं।
  • load balancing performance का मात्रात्मक मूल्यांकन करने और सुधारों को visualize करने वाले graphs प्रभावशाली हैं। खासकर max/avg अनुपात को 1 के करीब बनाए रखना fleet size optimization के लिए महत्वपूर्ण है, यह बात बहुत अच्छी तरह दिखाई गई है।
  • Config Aggregator को पेश करके service-specific configuration को अलग करना भी एक अच्छा विचार लगता है। इससे service owners अपने बदलावों को स्वतंत्र रूप से manage कर सकते हैं।
  • tombstone जैसे safety mechanism रखना भी बारीकी से सोचा गया पहलू है। गलती से configuration delete होने से बचाना महत्वपूर्ण है।
  • migration strategy से जुड़े सबक भी उपयोगी लगते हैं। अगर शुरुआत से migration को ध्यान में न रखा जाए, तो बाद में बहुत समय खर्च हो सकता है।
  • कुल मिलाकर Robinhood, Dropbox के पैमाने पर load balancing के लिए एक व्यवस्थित और परिष्कृत solution लगता है। बड़े पैमाने की infrastructure रखने वाली दूसरी कंपनियों के लिए भी यह एक संदर्भ योग्य उदाहरण है।

मिलते-जुलते solutions:

  • AWS का Elastic Load Balancing(ELB) और Google Cloud का Cloud Load Balancing भी बड़े पैमाने की load balancing के लिए managed services प्रदान करते हैं।
  • Kubernetes के मामले में उसका अपना load balancer (kube-proxy) होता है, लेकिन Istio या Linkerd जैसे service mesh solutions का उपयोग करने पर अधिक शक्तिशाली load balancing और traffic management features मिल सकते हैं।
  • Netflix का Zuul और Lyft का Envoy भी proxy-based load balancing features प्रदान करते हैं।

अपनाने से पहले विचार करने योग्य बातें:

  • मौजूदा infrastructure और services के साथ compatibility की पुष्टि करना ज़रूरी है। अगर migration की आवश्यकता हो, तो उसके लिए रणनीति बनानी चाहिए।
  • performance और stability पर पड़ने वाले प्रभाव का पर्याप्त परीक्षण और monitoring करना चाहिए। load balancing logic में bug घातक हो सकते हैं।
  • टीम की क्षमता को ध्यान में रखकर adoption की सीमा और गति तय करनी चाहिए। जल्दबाज़ी में सब जगह लागू करने से बेहतर है चरणबद्ध अपनाना।
  • लंबे समय में लगातार optimization और improvement करते रहने का प्रयास आवश्यक है। load balancing algorithm को परिस्थितियों के अनुसार tune करना और bottlenecks हटाने जैसी गतिविधियाँ मददगार होंगी।

1 टिप्पणियां

 
kbumsik 2024-11-01

सॉफ्टवेयर वाली तरफ PID controller का ज़िक्र सुनना दिलचस्प है haha