ബെഞ്ച്മാർക്ക് കെണി
ബെഞ്ച്മാർക്ക് പോസ്റ്ററുകൾ ഒരിക്കലും പൂർണ്ണമായ ചിത്രം കാണിച്ചുതരുന്നില്ല. അവ ഒന്നിനും ഉപയോഗശൂന്യമായ ഒരു ഹാൻഡ്ലറാണ് അളക്കുന്നത്. ഒരു JSON Hello World അല്ലെങ്കിൽ ഒരു സ്റ്റാറ്റിക് സ്ട്രിംഗ്. അത്തരം ഒരു ശൂന്യതയിൽ, Fiber വ്യക്തമായി വിജയിക്കുന്നു. അത് Gin-നേക്കാൾ കൂടുതൽ റിക്വസ്റ്റുകൾ സെക്കൻഡിൽ കൈകാര്യം ചെയ്യുന്നു കൂടാതെ കുറഞ്ഞ മെമ്മറി മാത്രമേ ഉപയോഗിക്കുന്നുള്ളൂ. അത് യഥാർത്ഥ എഞ്ചിനീയറിംഗ് ആണ്. എന്നാൽ നിങ്ങളുടെ ആപ്ലിക്കേഷൻ ഒരു ശൂന്യതയല്ല.
ഞാൻ കെനിയയിൽ ഒരു റിയൽ-ടൈം സെക്യൂരിറ്റി ആപ്പ് നിർമ്മിക്കുകയാണ്. നൈറോബിയിലെയും മൊംബാസയിലെയും ഉപയോക്താക്കളിൽ നിന്ന് GPS കോർഡിനേറ്റുകൾ സ്വീകരിച്ച് കുറ്റകൃത്യങ്ങൾ നടക്കുന്ന സ്ഥലങ്ങളെക്കുറിച്ചോ റോഡപകടങ്ങളെക്കുറിച്ചോ ഉള്ള മുന്നറിയിപ്പുകൾ ഇത് നൽകുന്നു. ഇതിനർത്ഥം PostgreSQL റൈറ്റുകൾ, Firebase Cloud Messaging കോളുകൾ, കൂടാതെ റിവേഴ്സ് ജിയോകോഡിംഗ് ലുക്കപ്പുകൾ എന്നിവ ഉണ്ടെന്നാണ്. നിങ്ങളുടെ സ്റ്റാക്കിൽ നെറ്റ്വർക്ക് ഹോപ്പുകളും ഡാറ്റാബേസ് റൗണ്ട്-ട്രിപ്പുകളും ഉൾപ്പെടുമ്പോൾ, റൂട്ടിംഗിൽ നാനോസെക്കൻഡുകൾ ലാഭിക്കുന്ന ഒരു ഫ്രെയിംവർക്ക് ശ്രദ്ധിക്കപ്പെടില്ല. തടസ്സം (bottleneck) ഒരിക്കലും റൂട്ടർ ആയിരിക്കില്ല. അത് SMS ഗേറ്റ്വേ ടൈം ഔട്ട് ആകുന്നതാകാം. അല്ലെങ്കിൽ ഇൻസിഡന്റ് റിപ്പോർട്ടുകളുടെ ടേബിൾ സ്കാൻ ചെയ്യുന്ന PostGIS ക്വറിയാകാം. പ്രൊഡക്ഷനിൽ എത്തുന്നതുവരെ ഉയർന്ന ത്രൂപുട്ട് (throughput) ആകർഷകമായി തോന്നാം.
സ്റ്റാൻഡേർഡ് ലൈബ്രറിയോടുള്ള വിശ്വസ്തത
Gin നേരിട്ട് net/http-ൽ നിർമ്മിച്ചതാണ്. അത് കേൾക്കുന്നതിനേക്കാൾ പ്രാധാന്യമുള്ള കാര്യമാണ്.
എല്ലാ Go ഡെവലപ്പർമാർക്കും net/http അറിയാം. ഡീബഗ്ഗിംഗ് പരിചിതമായ സ്റ്റാക്ക് ട്രാസുകൾ പിന്തുടരുന്നു. അഞ്ച് വർഷം മുമ്പ് എഴുതിയ മിഡിൽവെയറുകൾ പോലും യാതൊരു പ്രയാസവുമില്ലാതെ ഉപയോഗിക്കാം. Go ഡോക്യുമെന്റേഷൻ പറയുന്നതുപോലെ തന്നെ റിക്വസ്റ്റ്, റെസ്പോൺസ് ഒബ്ജക്റ്റുകൾ പ്രവർത്തിക്കുന്നു. ഭാഷയോട് (language) ചേർന്നുനിൽക്കുന്നതുകൊണ്ട് Gin പ്രവചിക്കാവുന്ന രീതിയിൽ (predictable) പ്രവർത്തിക്കുന്നു.
Fiber ആ അടിസ്ഥാനത്തിന് പകരം zero-allocation പെർഫോമൻസിനായി ഒപ്റ്റിമൈസ് ചെയ്ത fasthttp എന്ന കസ്റ്റം HTTP എഞ്ചിൻ ഉപയോഗിക്കുന്നു. അത് കൈവരിക്കാൻ, അത് Request/Response Pooling ഉപയോഗിക്കുന്നു. ഓരോ റിക്വസ്റ്റിന് ശേഷവും ഗാർബേജ് കളക്ടർ മെമ്മറി തിരിച്ചുപിടിക്കാൻ അനുവദിക്കുന്നതിന് പകരം, Fiber മെമ്മറി ബ്ലോക്കുകൾ റീസൈക്കിൾ ചെയ്യുന്നു. അത് അവ ക്ലീൻ ചെയ്ത് അടുത്ത കണക്ഷന് കൈമാറുന്നു. ആ വിദ്യയാണ് വേഗതയുടെ കാരണം. എന്നാൽ അത് അപകടത്തിന്റെ കാരണവുമാണ്.
വീണ്ടും ഉപയോഗിക്കുന്ന മെമ്മറിയുടെ മറഞ്ഞിരിക്കുന്ന അപകടം
തിയറി അനുസരിച്ച് പൂളിംഗ് സുരക്ഷിതമായി തോന്നാം. എന്നാൽ പ്രായോഗികമായി, അത് ഒരു സൂക്ഷ്മമായ കരാർ മുന്നോട്ടുവെക്കുന്നു: നിങ്ങളുടെ ഹാൻഡ്ലർ റിട്ടേൺ ചെയ്തതിന് ശേഷം റിക്വസ്റ്റ് ഡാറ്റയുടെ ഒരു റഫറൻസും നിങ്ങൾ സൂക്ഷിക്കരുത്. ഒരു goroutine റിക്വസ്റ്റിനേക്കാൾ കൂടുതൽ സമയം നിലനിൽക്കുകയോ, അല്ലെങ്കിൽ പിന്നീട് പ്രോസസ്സ് ചെയ്യുന്നതിനായി റിക്വസ്റ്റ് ബോഡിയുടെ ഒരു സ്ലൈസ് നിങ്ങൾ എടുക്കുകയോ ചെയ്താൽ, Fiber ആ മെമ്മറി തിരിച്ചുപിടിച്ച് അടുത്ത ഉപയോക്താവിന് നൽകും.
ഇതിന്റെ ഫലം ഡാറ്റാ മലിനീകരണമാണ് (contamination). ഈ ബഗ്ഗ് ഒരു യൂണിറ്റ് ടെസ്റ്റിൽ കാണില്ല. നൈറോബിയിലെ ഒരു ഡ്രൈവറുടെ GPS കോർഡിനേറ്റ് പെട്ടെന്ന് കിസുമുവിലെ മാപ്പിൽ പ്രത്യക്ഷപ്പെടുന്നത് പോലെയാണ് ഇത് സംഭവിക്കുന്നത്. ഒരു ഉപയോക്താവിന്റെ JWT ടോക്കൺ മറ്റൊരു ഉപയോക്താവിന്റെ കോൺടെക്സ്റ്റിലേക്ക് ചോരുന്നത് പോലെ ഇത് കാണപ്പെടുന്നു. ഇവ താൽക്കാലികമായ പരാജയങ്ങളാണ് (temporal failures). ലോഗിംഗ് ചേർക്കുമ്പോൾ ഇവ അപ്രത്യക്ഷമാകും, കാരണം ലോഗിംഗ് ചെയ്യുന്നത് പുതിയ മെമ്മറി അനുവദിക്കുകയും സമയക്രമം മാറ്റുകയും ചെയ്യുന്നു. അവസാനം നിങ്ങൾ വെറുതെ നിഴലുകളെ പിൻതുടരുകയാണ് ചെയ്യുന്നത്.
Gin-ൽ, സ്റ്റാൻഡേർഡ് ലൈബ്രറി ഒരു പുതിയ റിക്വസ്റ്റ് ഒബ്ജക്റ്റ് അനുവദിക്കുന്നു. മലിനമാക്കാൻ അവിടെ ഒരു പൂൾ ഇല്ല. യഥാർത്ഥ സുരക്ഷയുമായി ബന്ധപ്പെട്ട സ്ഥലങ്ങൾ കൈകാര്യം ചെയ്യുമ്പോൾ ആ സുരക്ഷ വളരെ പ്രധാനമാണ്.
ഇക്കോസിസ്റ്റം ഗ്രാവിറ്റി
കമ്പാറ്റിബിലിറ്റിയുടെ (compatibility) ഒരു നിശബ്ദമായ വില കൂടിയുണ്ട്.
മിക്ക Go മിഡിൽവെയറുകളും net/http ആണ് പ്രതീക്ഷിക്കുന്നത്. JWT വാലിഡ
