અઠવાડિયાઓ સુધી, Elevare Digital માં એક cron job નિયમિત સમયે જાગતું હતું, તેની ક્યુ (queue) તપાસતું હતું અને સફળતાનો લોગ નોંધતું હતું. તેણે બરાબર શૂન્ય ડ્રાફ્ટ મંજૂર કર્યા. ઓગણીસ કન્ટેન્ટના ટુકડાઓ રાહ જોઈ રહ્યા હતા. ટીમને આ બાબત પછીથી ખબર પડી, જ્યારે આ શાંત અંતરાલ એક વિચિત્રતામાંથી નાના બેકલોગમાં ફેરવાઈ ગયો હતો. કંઈ પણ ક્રેશ થયું નહોતું. કોઈ પેજિંગ એલર્ટ્સ (paging alerts) આવ્યા નહોતા. સિસ્ટમ ટેકનિકલી સ્વસ્થ હતી પરંતુ કાર્યાત્મક રીતે મૃત હતી.
આ સ્વાયત્ત પાઇપલાઇન્સ (autonomous pipelines) નો શાંત ભય છે. જ્યારે તમે લૂપમાંથી માનવીને દૂર કરો છો, ત્યારે તમે તે વ્યક્તિને પણ દૂર કરો છો જે નોંધે છે કે કંઈ થઈ રહ્યું નથી.
પોતાની મેળે ચાલતી પાઇપલાઇન
Elevare Digital સંપૂર્ણ રીતે સ્વચાલિત કન્ટેન્ટ વર્કફ્લો ચલાવે છે. સોફ્ટવેર એજન્ટો ડ્રાફ્ટ બનાવે છે. એક શેડ્યૂલ કરેલ એપ્રૂવર cron ગેટકીપર તરીકે કામ કરે છે, જે તે ડ્રાફ્ટની સમીક્ષા કરે છે અને મંજૂર થયેલ આઇટમ્સને સીધી પબ્લિશિંગ માટે મોકલે છે. કોઈ પણ માનવી દરેક બેચને મંજૂરી આપવા માટે ડેશબોર્ડ ખોલતું નથી. આ આખી પ્રક્રિયાનો હેતુ એ છે કે જ્યારે ટીમ અન્ય સમસ્યાઓ પર ધ્યાન આપે, ત્યારે મશીન કંટાળાજનક કામ સંભાળી લે.
આ મોડેલ હેઠળ, વિશ્વાસ એ તમારો પ્રાથમિક ઇન્ટરફેસ બની જાય છે. તમે શેડ્યૂલર પર વિશ્વાસ કરો છો કે તે સમયસર ચાલશે. તમે જોબ ચાલશે તેના પર વિશ્વાસ કરો છો. તમે એક્ઝિટ કોડ (exit code) પર વિશ્વાસ કરો છો. જ્યારે લોગ્સમાં 200 OK પ્રતિસાદોનો સતત હાર્ટબીટ દેખાય છે, ત્યારે તમે માની લો છો કે કામ આગળ વધી રહ્યું છે. અઠવાડિયાઓ સુધી, તે હાર્ટબીટ પરફેક્ટ હતી. cron દરેક વખતે સમયસર ચાલતું હતું. તેણે ફક્ત ક્યારેય વાસ્તવિક કામ કર્યું નહોતું.
ઓગણીસ ડ્રાફ્ટ અને કોઈ એલાર્મ નહીં
આ શોધ અકસ્માતે થઈ હતી. કોઈએ અંતે નોંધ્યું કે પબ્લિશિંગ ક્યુ શાંત થઈ ગઈ હતી, અથવા કદાચ તેમણે ડાઉનસ્ટ્રીમ મેટ્રિક તપાસ્યું અને ત્યાં ફ્લેટલાઇન (flatline) જોઈ. તેમને જે મળ્યું તે હતું ઓગણીસ ડ્રાફ્ટનો સંગ્રહ જે સંપૂર્ણપણે અસ્પૃશ્ય પડ્યા હતા. એપ્રૂવર નિયમિત રીતે ચાલતું હતું, દરરોજ સફળતાનો લોગ નોંધતું હતું, પરંતુ તેમાંથી એક પણ પ્રોસેસ કર્યું નહોતું.
મેન્યુઅલ વર્કફ્લોમાં, માનવીય રિવ્યુઅર પહેલા જ દિવસે ખાલી ઇનબોક્સ અથવા પેન્ડિંગ આઇટમ્સનો ઢગલો જોઈ ગયો હોત. ઓટોમેટેડ વર્ઝનમાં, પ્રવૃત્તિનો અભાવ બરાબર કામના અભાવ જેવો જ દેખાતો હતો. cron ને નિરાશ કરવા માટે કોઈ મેનેજર નહોતો. તે ફક્ત સમયસર હાજરી પુરાવતું હતું અને વહેલું ઘરે જતું રહેતું હતું.
બે બગ્સ, એક ખાલી પરિણામ
આ નિષ્ફળતાના બે કારણો હતા. તેમાંથી એક પણ સિન્ટેક્સ એરર, ટાઇમઆઉટ અથવા ડિપેન્ડન્સી આઉટેજ નહોતું. બંને સેમેન્ટિક ભૂલો (semantic mistakes) હતી જે ક્વેરી એન્જિનની નજરમાં ઓગણીસ માન્ય રો (rows) ને શૂન્યમાં ફેરવી દીધી હતી.
પ્રથમ, ટાઇપ મિસમેચ (type mismatch). ડ્રાફ્ટ બનાવનાર એજન્ટે article તરીકે ટેગ કરેલા રેકોર્ડ્સ લખ્યા હતા. એપ્રૂવર cron એ ખાસ કરીને thread પ્રકારો માટે ક્વેરી કરી હતી. આ એ પ્રકારનું વિચલન (drift) છે જે ત્યારે થાય છે જ્યારે ઉત્પાદકો (producers) અને ગ્રાહકો (consumers) સમાંતર ટ્રેક પર વિકસે છે. એક ટીમે—અથવા એક એજન્ટે—નિર્ણય લીધો કે આ આઉટપુટ એક આર્ટિકલ છે. બીજાએ ગ્રાહક તરીકે એવું માનીને લખ્યું કે તે થ્રેડ્સ (threads) લેશે. કોઈ ટાઇપ સિસ્ટમે કમ્પાઇલ-ટાઇમ એરર આપી નહોતી કારણ કે આ સંભવતઃ લૂઝ સ્ટ્રિંગ ટેગ્સ હતા, કદાચ JSON ફીલ્ડ્સ અથવા અનએનફોર્સ્ડ varchar વેલ્યુઝ. ડેટાબેસે ફક્ત કોઈ મેચ શોધી નહોતી અને ખાલી સેટ રિટર્ન કર્યો હતો. એન્જિન માટે તે એરર કન્ડિશન નથી. તે ખોટા પ્રશ્નનો સાચો જવાબ છે.
બીજું, એપ્રૂવરની ક્વેરીમાં એક ઇનર જોઈન (inner join) એ આખી રો ને શાંતિથી ગળી લીધી. જો ક્વેરીએ ડ્રાફ્ટ ટેબલને અન્ય ટેબલ સાથે જોડ્યું હોય—કદાચ મેટાડેટા, સ્ટેટસ ફ્લેગ્સ અથવા રાઉટિંગ નિયમો માટે લુકઅપ—અને જોઇન કન્ડિશન નિષ્ફળ ગઈ હોય, તો ઇનર જોઈને બરાબર તેની ડિઝાઇન મુજબ જ વર્તન કર્યું. તેણે બિન-મેચિંગ રો ને બાકાત કરી દીધી. પરિણામ સેટમાં કોઈ અનાથ (orphan) રો દેખાયા નહીં. કોઈ નલ્સ (nulls) એ સમસ્યા સૂચવી નહીં. ઓગણીસ ડ્રાફ્ટ ક્વેરીમાંથી ગળણીમાંથી પસાર થતા પાણીની જેમ નીકળી ગયા, અને એપ્લિકેશન લેયરને એક શુદ્ધ, ખાલી લિસ્ટ મળ્યું.
કારણ કે ક્વેરીએ કોઈ રો રિટર્ન કરી નહોતી, ફંક્શન ક્લીનલી એક્ઝિટ થયું. કોઈ એક્સેપ્શન ઉપર આવ્યા નહીં. HTTP પ્રતિસાદ 200 OK હતો. cron એ સફળતા નોંધાવી અને ફરીથી સૂઈ ગયું.
'Processed Zero' નો જાળ
અહીં સમસ્યાનું મુખ્ય કારણ છે. ક્યુ-આધારિત સિસ્ટમમાં, કન્ઝ્યુમર ઘણીવાર પ્રોસેસ કરવા માટે શૂન્ય રો મેળવે છે. ક્યુ ખાલી થઈ જાય છે. વર્કર ઝડપથી કામ પૂરું કરે છે. લોગમાં processed: 0 લખેલું આવે છે અને ટીમ તેને સારા સમાચાર તરીકે વાંચે છે: આપણે માંગ મુજબ કામ કરી રહ્યા છીએ. તે એક હેલ્ધી સ્ટેટ છે.
પરંતુ processed: 0 બે તદ્દન અલગ વાસ્તવિકતાઓ દર્શાવે છે:
- હેલ્ધી સ્ટેટ (Healthy state): શૂન્ય પ્રોસેસ થયા કારણ કે શૂન્ય પેન્ડિંગ છે. ક્યુ ખાલી છે. સિસ્ટમ ડિઝાઇન મુજબ આઈડલ (idle) છે.
- બ્રોકન સ્ટેટ (Broken state): શૂન્ય પ્રોસેસ થયા કારણ કે કન્ઝ્યુમર કામ જોઈ શકતો નથી. ક્યુમાં ઓગણીસ રો છે. સિસ્ટમ અંધ છે, આઈડલ નથી.
ક્યુ ડેપ્થ (queue depth) પર સ્વતંત્ર તપાસ વિના, આ બંને સ્ટેટ્સ સમાન ટેલિમેટ્રી આપે છે. તેઓ ડેશબોર્ડ્સમાં સમાન દેખાય છે, લોગ એગ્રીગેટર્સમાં સમાન લાગે છે, અને PagerDuty માં સમાન શાંતિ પેદા કરે છે. તમે એવી મોનિટરિંગ વ્યૂહરચના બનાવી છે જે ત્યારે જ પકડે છે જ્યારે વર્કર ચીસ પાડે છે, જ્યારે તે કામના ઢગલા પાસેથી ચૂપચાપ પસાર થઈ જાય છે ત્યારે નહીં.
અંતર ઘટાડવું
Elevare Digital એ તેઓ શું મોનિટર કરે છે તેમાં ફેરફાર કરીને સમસ્યાનું નિરાકરણ કર્યું. તેઓ માત્ર એરર રેટ (error rates) અને સક્સેસ સ્ટેટસ (success statuses) પર નિર્ભર રહેવાનું બંધ કરી દીધું. તેના બદલે, તેઓ ઉપલબ્ધ કામ અને પૂર્ણ થયેલા કામ વચ્ચેના તફાવત (gap) પર એલર્ટ આપવાનું શરૂ કર્યું.
દરેક બેચ પછી, તેઓ હવે એક સરળ ઇન્વેરિયન્ટ ચેક (invariant check) ચલાવે છે:
- જો processed 0 હોય અને pending rows 0 કરતા વધારે હોય, તો હાઈ સેવરિટી એલર્ટ (high severity alert) ટ્રિગર કરો.
આ નિયમ જાણીજોઈને કારણ વિશે નિરપેક્ષ (agnostic) રાખવામાં આવ્યો છે. તે એ વાતની ચિંતા કરતો નથી કે ભૂલ ખરાબ ફિલ્ટરને કારણે હતી, બ્રોકન જોઈન (broken join) ને કારણે હતી, કે પછી કોઈ ભૂલથી ટાઈપ થયેલ enum સ્ટ્રિંગને કારણે હતી. તેને ફક્ત એટલી જ ચિંતા છે કે કામ ઉપલબ્ધ છે અને કોઈ કામ થયું નથી. આ મોનિટરિંગને “શું પ્રોસેસે ફરિયાદ કરી?” થી બદલીને “શું કામ આગળ વધ્યું?” પર લઈ જાય છે.
આને ટેકો આપવા માટે, તેઓ ક્યુ ડેપ્થ (queue depth) ને માત્ર સ્પોટ-ચેક તરીકે નહીં, પરંતુ સમય જતાં ટ્રેક કરવામાં આવતા ફર્સ્ટ-ક્લાસ મેટ્રિક તરીકે ગણે છે. જો કન્ઝ્યુમર સતત સક્સેસ રિપોર્ટ કરતો હોય અને પ્રોડ્યુસર સતત રોઝ (rows) ઉમેરતો રહેતો હોય, તો ડેપ્થ ટ્રેન્ડ એક સ્પષ્ટ પુરાવો (smoking gun) બની જાય છે. એક સ્ટેટિક સ્નેપશોટ ખોટું હોઈ શકે છે, પરંતુ વધતો જતો બેકલોગ (backlog) ક્યારેય ખોટો હોતો નથી.
ઓટોનોમસ સિસ્ટમ્સ માટેના પાઠ
Elevare ની આ ઘટના કોઈપણ વ્યક્તિ જે હેન્ડ્સ-ઓફ પાઇપલાઇન્સ (hands-off pipelines) ચલાવે છે તેના માટે કેટલાક વ્યવહારુ નિયમો ધરાવે છે.
સ્કેન કરેલી રોઝ (scanned rows) ને પ્રોસેસ કરેલી રોઝથી અલગ લોગ કરો. કન્ઝ્યુમર કદાચ એવી ક્વેરી એક્ઝિક્યુટ કરી શકે છે જે ચાલીસ રોઝને સ્પર્શે છે, ખરાબ માપદંડો દ્વારા તે તમામ ફિલ્ટર કરી નાખે છે, અને processed: 0 રિપોર્ટ કરે છે. જો તમે ફક્ત અંતિમ કાઉન્ટ લોગ કરો છો, તો તમે તે છુપી પ્રક્રિયા (ghost interaction) ચૂકી જશો. સ્કેન કરેલી રોઝનું મેટ્રિક દર્શાવે છે કે વર્કર આવ્યો હતો, કામ જોયું અને મૂંઝવણમાં ત્યાંથી ચાલ્યો ગયો. સ્કેન કરેલી અને પ્રોસેસ કરેલી રોઝ વચ્ચેનો આ તફાવત ઘણીવાર તમારો સૌથી વહેલો સંકેત હોય છે.
ક્યુ ડેપ્થને ટાઈમ-સીરીઝ (time-series) તરીકે ટ્રેક કરો. જે ક્યુ કામચલાઉ ધોરણે ખાલી હોય તે ઠીક છે. પરંતુ જે ક્યુ વર્કર્સ 'ગ્રીન' (સક્રિય) હોવા છતાં સતત વધતી જાય છે તે યોગ્ય નથી. ડેપ્થને કન્ઝ્યુમર થ્રુપુટ (consumer throughput) સામે પ્લોટ કરો. જ્યારે આ બંને અલગ પડે, ત્યારે તરત જ તપાસ કરો, ભલે દરેક હેલ્થ ચેક પાસ થઈ રહ્યા હોય.
કન્ઝ્યુમર્સનું પરીક્ષણ માત્ર મોક્સ (mocks) સામે નહીં, પણ વાસ્તવિક પ્રોડ્યુસર આઉટપુટ સામે કરો. મોક કરેલા ડેટા સાથેના યુનિટ ટેસ્ટ ટેસ્ટરની ધારણાઓ ધરાવે છે. જો મોક ફેક્ટરી thread પ્રકારો બનાવે છે અને કન્ઝ્યુમર thread પ્રકારોની અપેક્ષા રાખે છે, તો તમારા ટેસ્ટ પાસ થશે જ્યારે પ્રોડક્શનમાં નિષ્ફળતા આવશે. એવા ઇન્ટિગ્રેશન ટેસ્ટ ચલાવો જે પ્રોડ્યુસરના આઉટપુટમાંથી વાસ્તવિક રેકોર્ડ્સ ખેંચે છે. ખાતરી કરો કે કન્ઝ્યુમર ખરેખર તે જોઈ શકે છે જે પ્રોડ્યુસર લખે છે.
ડેટા પ્રકારો અને enum વેલ્યુઝને કરાર (contracts) તરીકે ગણો. JSON બ્લોબમાં લૂઝ સ્ટ્રિંગ ટેગ્સ ત્યાં સુધી અનુકૂળ છે જ્યાં સુધી તે અદ્રશ્ય નિષ્ફળતાના બિંદુઓ ન બની જાય. સ્કીમા (schemas) સ્પષ્ટ રીતે વ્યાખ્યાયિત કરો. કોન્સ્ટન્ટ્સ (constants) શેર કરો. પ્રોડ્યુસર અને કન્ઝ્યુમર વચ્ચેના જોડાણ બિંદુ પર પેલોડ્સ (payloads) ને વેલિડેટ કરો. જો કરાર તૂટે છે, તો સિસ્ટમ સીમા (boundary) પર સ્પષ્ટ રીતે નિષ્ફળ જવી જોઈએ, WHERE ક્લોઝની અંદર શાંતિથી નહીં.
મુખ્ય નિષ્કર્ષ
ઓટોનોમસ સિસ્ટમ્સ માણસોની જેમ નિષ્ફળ જતી નથી. તેઓ બીમાર હોવાનું કહીને રજા નથી લેતા, દર વખતે એક્સેપ્શન (exceptions) ફેંકતા નથી, અથવા સ્પષ્ટ ક્રેશ ડમ્પ (crash dumps) છોડતા નથી. તેઓ 200 OK રિટર્ન કરે છે અને ઇન્વેન્ટરીને બગડવા દે છે. જો તમારા એલર્ટ્સ ફક્ત ચીસો સાંભળવા માટે જ સજ્જ હોય, તો તમે સૌથી મોંઘી નિષ્ફળતાઓ ચૂકી જશો—એવી નિષ્ફળતાઓ જ્યાં બધું બરાબર લાગે છે અને કંઈ જ થતું નથી.
તમારા ઓબ્ઝર્વેબિલિટી (observability) ને તફાવત (gap) પર નજર રાખવા માટે ડિઝાઇન કરો. જે કામ અંદર આવે છે તેની સરખામણી બહાર નીકળતા કામ સાથે કરો. જ્યારે આ બંને હવે મેળ ખાતા ન હોય, ત્યારે માની લો કે મશીન તમને જૂઠું બોલી રહ્યું છે. કારણ કે ક્યારેક, એક પરફેક્ટ સક્સેસ લોગ એ એવી સિસ્ટમનું એકમાત્ર લક્ષણ હોય છે જે સંપૂર્ણપણે અંધ થઈ ગઈ છે.
