TechForge ની નવી માર્ગદર્શિકા ચેતવણી આપે છે કે ઘણા નવા માઈક્રોસર્વિસ પ્રોજેક્ટ્સ અંતે “ડિસ્ટ્રિબ્યુટેડ મોનોલિથ” (distributed monoliths) બની જાય છે, જે સ્કેલિંગના કોઈપણ ફાયદા વિના નેટવર્ક કોલ્સની લેટન્સી (latency) આપે છે. આ લેખ એન્જિનિયરિંગ ટીમોને એક મજબૂત મોનોલિથથી શરૂઆત કરવા અને જ્યારે સ્પષ્ટ સ્કેલિંગ અથવા માલિકીની જરૂરિયાતો ઊભી થાય ત્યારે જ તેને અલગ પાડવા માટે આગ્રહ કરે છે.

ટીમો શા માટે માઈક્રોસર્વિસ તરફ ઉતાવળ કરે છે

માઈક્રોસર્વિસનું આકર્ષણ સ્પષ્ટ છે: સ્વતંત્ર સેવાઓ, અલગ ડિપ્લોયમેન્ટ્સ, અને એપ્લિકેશનના દરેક ભાગને તેની પોતાની શરતો પર સ્કેલ કરવાની ખાતરી. સ્ટાર્ટ-અપ સંસ્કૃતિ અને તાજેતરની સફળતાની વાર્તાઓએ આ પેટર્નને આધુનિક એન્જિનિયરિંગના સન્માન તરીકે સ્થાપિત કરી છે. તેમ છતાં, મોનોલિથને ખૂબ વહેલા વિભાજિત કરવાથી ઘણીવાર એક નવો પ્રકારનો મોનોલિથ — ડઝનબંધ નેટવર્ક કરેલા ઘટકો — બની જાય છે. તેની કિંમત? વધુ લેટન્સી, મુશ્કેલ ડીબગિંગ અને વધુ ઓપરેશનલ ઓવરહેડ, જ્યારે મૂળ ફાયદાઓ પહોંચી બહાર રહે છે.

પ્રથમ ભૂલ: માત્ર નામ પૂરતા મોનોલિથથી શરૂઆત કરવી

ટીમો ઘણીવાર સિંગલ કોડબેઝ અને શેર કરેલા ડેટાબેઝને રાખીને સિસ્ટમને “માઈક્રો-સર્વિસ-આધારિત” તરીકે લેબલ કરે છે. પરિણામ એ શ્રેણીબદ્ધ ટાઈટલી કપલ્ડ (tightly coupled) મોડ્યુલ્સ છે જે હજુ પણ HTTP અથવા RPC દ્વારા એકબીજા સાથે વાત કરે છે. માર્ગદર્શિકા આને “ડિસ્ટ્રિબ્યુટેડ મોનોલિથ” કહે છે. તેની સમસ્યાઓ પરંપરાગત મોનોલિથ જેવી જ છે — ટાઈટ કપલિંગ અને બાકીના ભાગને અસર કર્યા વિના એક ભાગ બદલવામાં મુશ્કેલી — વત્તા નેટવર્ક હોપ્સ (network hops) માંથી વધારાની લેટન્સી.

તેના બદલે શું કરવું: સૌ પ્રથમ એક ક્લીન મોનોલિથ બનાવો. મોડ્યુલની સ્પષ્ટ સીમાઓ વ્યાખ્યાયિત કરો, ડેટા લેયરને એકીકૃત રાખો, અને ખાતરી કરો કે એપ્લિકેશનને સિંગલ યુનિટ તરીકે ટેસ્ટ અને ડિપ્લોય કરી શકાય છે. કોઈ મોડ્યુલને તેના પોતાના સર્વિસમાં ત્યારે જ અલગ કરો જ્યારે તેને સ્વતંત્ર સ્કેલિંગ અથવા અલગ ટીમની માલિકીની જરૂર હોય.

ટેકનિકલ લેયર વિરુદ્ધ બિઝનેસ કેપેબિલિટી દ્વારા વિભાજન

બીજી સામાન્ય ભૂલ ટેકનિકલ બાબતો — UI, બિઝનેસ લોજિક અથવા ડેટા એક્સેસ — મુજબ સેવાઓને વિભાજિત કરવાની છે. આ એક જ ઓપરેશન માટે વિનંતીને (request) સેવાઓની સાંકળમાંથી પસાર થવા માટે મજબૂર કરે છે, જેનાથી રિસ્પોન્સ ટાઈમ વધે છે અને નબળો ડિપેન્ડન્સી ગ્રાફ (dependency graph) બને છે.

વધુ સારો અભિગમ: "ઓર્ડર્સ", "પેમેન્ટ્સ" અથવા "ઇન્વેન્ટરી" જેવી બિઝનેસ કેપેબિલિટીઝની આસપાસ સેવાઓને ગોઠવો. દરેક કેપેબિલિટીને તેનો પોતાનો ડેટા અને પોતાનું API રાખવા દો, જેથી વિનંતીને લેયર્સ વચ્ચે કૂદકા મારવાની જરૂર ન પડે.

ડેટા માલિકી મહત્વની છે

જ્યારે બે સેવાઓ એક જ ડેટાબેઝ ટેબલમાં લખે છે, ત્યારે તેઓ હવે સ્વતંત્ર રહેતા નથી. માર્ગદર્શિકા ભાર મૂકે છે કે એક સર્વિસે ક્યારેય બીજી સર્વિસના ટેબલ્સને સીધા ક્વેરી (query) ન કરવા જોઈએ; તેણે હંમેશા તે સર્વિસના પબ્લિક API દ્વારા જ જવું જોઈએ. ડેટાબેઝ શેર કરવાથી સેવાઓ એકબીજા સાથે જોડાઈ જાય છે, આઇસોલેશન (isolation) ના હેતુને નિષ્ફળ બનાવે છે, અને સ્કીમા ફેરફારોને સંકલન માટે кошાળ બનાવી દે છે.

સિંક્રનસ HTTP એ યુનિવર્સલ સોલ્યુશન નથી

દરેક ઇન્ટરેક્શન માટે સિંક્રનસ HTTP પર નિર્ભર રહેવાથી આખી સિસ્ટમ એક સિંગલ ધીમી સર્વિસ સામે અસુરક્ષિત બની જાય છે. જો સર્વિસ A ક્લાયન્ટને વળતા પહેલા સર્વિસ B ના પ્રતિસાદની રાહ જોતી હોય, તો B માં થતો કોઈપણ ધીમો પડવો A માં અને અંતે યુઝર સુધી પહોંચે છે.

વૈકલ્પિક પેટર્ન: એવા કાર્યો માટે અસિંક્રનસ મેસેજિંગનો ઉપયોગ કરો જેને તાત્કાલિક જવાબની જરૂર નથી. મેસેજ ક્યુઝ અથવા બેકગ્રાઉન્ડ જોબ્સ સેવાઓને કામ સોંપવા અને પ્રોસેસિંગ ચાલુ રાખવા દે છે, જેનાથી સમગ્ર સિસ્ટમ વધુ રેઝિલિયન્ટ (resilient) રહે છે.

ઇવેન્ચ્યુઅલ ક consistancy (eventual consistency) સ્વીકારવી

પરંપરાગત રિલેશનલ ડેટાબેઝ તમને ACID ટ્રાન્ઝેક્શન આપે છે — Atomicity, Consistency, Isolation, Durability. સર્વિસ બાઉન્ડરીઝની પેલે પાર, આ ગેરંટીઓ અદૃશ્ય થઈ જાય છે. ટુ-ફેઝ કમિટ્સ (two-phase commits - એક પ્રોટોકોલ જે ડિસ્ટ્રિબ્યુટેડ ટ્રાન્ઝેક્શનને લોકલ ટ્રાન્ઝેક્શનની જેમ વર્તવા માટે પ્રયાસ કરે છે) ને લાગુ કરવાનો પ્રયાસ જટિલતા અને અસ્થિરતા તરફ દોરી જાય છે.

માર્ગદર્શિકા સાગા (sagas - વળતર આપતી ક્રિયાઓની શ્રેણી) અથવા આઉટબોક્સ પેટર્ન (outbox pattern - જ્યાં એક સર્વિસ લોકલ ટેબલમાં ઇવેન્ટ્સ લખે છે જે પછીથી પ્રકાશિત કરવામાં આવે છે) ની ભલામણ કરે છે. આ અભિગમો સ્વીકારે છે કે ડેટા કામચલાઉ ધોરણે સિંક (sync) માં ન હોઈ શકે અને તે ખામીઓને હેન્ડલ કરવા માટે બિઝનેસ લોજિક ડિઝાઇન કરે છે.

પહેલા દિવસથી જ નિષ્ફળતા માટે તૈયાર રહો

એક સર્વિસમાં રહેલી ભૂલ (bug) આખી સિસ્ટમને તોડી નાખવી જોઈએ નહીં. અનંતકાળ સુધી રાહ જોવાનું ટાળવા માટે ટાઈમઆઉટ (timeouts), કામચલાઉ નિષ્ફળતાઓને હેન્ડલ કરવા માટે બેક-ઓફ સાથે રીટ્રાય (retries with back-off), અને સર્વિસ રિકવર ન થાય ત્યાં સુધી નિષ્ફળ જતી સર્વિસને કોલ્સ કરવાનું બંધ કરતા સર્કિટ બ્રેકર્સ (circuit breakers) લાગુ કરો. પ્રોડક્શન આઉટેજ પછી આ સુરક્ષા કવચ ઉમેરવા ખૂબ મોડું છે; તે પ્રારંભિક ડિઝાઇનમાં જ હોવા જોઈએ.

ઓબ્ઝર્વેબિલિટી (Observability) અનિવાર્ય છે

ઘણા કન્ટેનર્સમાં વિખરાયેલા લોગ્સ સાથે ડિસ્ટ્રિબ્યુટેડ સિસ્ટમનું ડીબગિંગ કરવું લગભગ અશક્ય છે. સેન્ટ્રલાઈઝ્ડ લોગિંગ, એગ્રીગેટેડ મેટ્રિક્સ અને રિક્વેસ્ટ-લેવલ કોરિલેશન આઈડીઝ (correlation IDs) એન્જિનિયરોને સિંગલ યુઝર રિક્વેસ્ટને ટ્રેસ કરવામાં મદદ કરે છે જ્યારે તે અનેક સેવાઓમાંથી પસાર થાય છે. ટ્રેસિંગ ટૂલ્સ કોલ ગ્રાફને વિઝ્યુઅલાઈઝ કરે છે, જેનાથી પર્ફોર્મન્સ બોટલનેક (performance bottlenecks) અને નિષ્ફળતાઓને શોધવી સરળ બને છે.

શરૂઆતમાં ઇન્ફ્રાસ્ટ્રક્ચરને હળવું રાખો

Kubernetes શક્તિશાળી હોવા છતાં, તે શીખવામાં મુશ્કેલ છે અને તેના સંચાલનનો બોજ (operational overhead) વધારે છે. થોડીક સેવાઓ માટે, Docker Compose આખા સ્ટેકને સ્થાનિક રીતે (locally) ચલાવવા માટે પૂરતું ઓર્કેસ્ટ્રેશન પૂરું પાડે છે. જ્યારે ટ્રાફિક પેટર્ન, ડિપ્લોયમેન્ટની આવૃત્તિ અથવા ટીમનું કદ તેની માંગ કરે ત્યારે જ વધુ જટિલ પ્લેટફોર્મનો ઉપયોગ કરવો જોઈએ.

સેવાઓને ટીમની માલિકી સાથે સુસંગત બનાવો

Microservicesનો અમુક અંશે હેતુ એ હતો કે નાની, સ્વાયત્ત ટીમોને કોઈ સેવાના સંપૂર્ણ જીવનચક્ર (lifecycle) ની માલિકી મળે. જો એક જ ટીમ દસ સેવાઓ માટે જવાબદાર હોય, તો સંકલનનો ખર્ચ (coordination costs) નાટકીય રીતે વધે છે, જે તેના નિર્ધારિત ફાયદાઓને ઘટાડે છે. આ માર્ગદર્શિકા સૂચવે છે કે દસથી ઓછી વ્યક્તિઓની ટીમો માટે monolith વધુ સારું હોઈ શકે છે, જે મોડ્યુલર ડેવલપમેન્ટની સાથે સરળતા જાળવી રાખે છે.

વિરોધી દલીલ: જ્યારે microservices શ્રેષ્ઠ સાબિત થાય છે

આ માર્ગદર્શિકા એવો દાવો નથી કરતી કે microservices મૂળભૂત રીતે ખરાબ છે. એવા વાતાવરણમાં જ્યાં એપ્લિકેશનના વિવિધ ભાગોની સ્કેલિંગ જરૂરિયાતો તદ્દન અલગ હોય, અથવા જ્યાં નિયમનકારી મર્યાદાઓ કડક ડેટા આઇસોલેશનની માંગ કરતી હોય, ત્યાં આ પેટર્ન વાસ્તવિક મૂલ્ય પ્રદાન કરી શકે છે. મલ્ટિપલ પ્રોડક્ટ લાઇન ધરાવતી મોટી સંસ્થાઓને ઘણીવાર એવું જોવા મળે છે કે સ્વતંત્ર સેવાઓ ટીમો વચ્ચેના ઘર્ષણને ઘટાડે છે અને ઝડપી રિલીઝ સાયકલને સક્ષમ બનાવે છે.

મુખ્ય બાબત હેતુપૂર્ણતા (intentionality) છે. જો કોઈ ટીમ કોઈ ચોક્કસ ફીચર માટે પ્રતિ સેકન્ડ લાખો વિનંતીઓ (requests) હેન્ડલ કરવા માટે અથવા નવી પ્રોડક્ટ લાઇન અલગ બિઝનેસ યુનિટ દ્વારા સંચાલિત હોવી જોઈએ તે કારણસર microservices અપનાવે છે, તો વધેલી જટિલતા યોગ્ય છે. માર્ગદર્શિકાની ચેતવણીઓ એવા કિસ્સાઓને લક્ષ્ય બનાવે છે જ્યાં નિર્ણય નક્કર જરૂરિયાતોને બદલે માત્ર હાઇપ (hype) દ્વારા લેવામાં આવે છે.

આગળ શું ધ્યાન રાખવું

જેમ જેમ વધુ કંપનીઓ cloud-native સ્ટેક્સ અપનાવે છે, તેમ તેમ service mesh, distributed tracing અને automated canary deployments ની આસપાસના સાધનો વધુ પરિપક્વ બની રહ્યા છે. આ પ્રગતિઓ ઓપરેશનલ અવરોધો ઘટાડે છે પરંતુ માર્ગદર્શિકામાં હાઇલાઇટ કરવામાં આવેલી મૂળભૂત ડિઝાઇન પસંદગીઓને દૂર કરતી નથી. ટીમોએ observability platforms અને async messaging frameworks ના વિકાસ પર નજર રાખવી જોઈએ, પરંતુ તેઓ જે પણ સેવા શરૂ કરે તેના માટે સ્પષ્ટ કારણ સાથે જ શરૂઆત કરવી જોઈએ.

મુખ્ય સારાંશ

Microservices એ લક્ષ્ય પ્રાપ્ત કરવાનું એક સાધન છે, તે પોતે જ લક્ષ્ય નથી. સારી રીતે રચાયેલ monolithથી શરૂઆત કરો, દરેક સેવાને તેના ડેટાની સાચી માલિકી આપો, જ્યાં શક્ય હોય ત્યાં asynchronous communication નો ઉપયોગ કરો, અને કોડની પ્રથમ લાઇનથી જ resilience અને observability ને સામેલ કરો. જ્યારે બિઝનેસ કેસ સ્પષ્ટ હોય, ત્યારે જાણીજોઈને સેવાઓને અલગ કરો; અન્યથા, આર્કિટેક્ચરને સમસ્યાની જરૂરિયાત મુજબ સરળ રાખો.