ഒരു സിങ്ക് (Sync) PHP ഡെവലപ്പർ എന്ന നിലയിൽ അസിങ്ക് (Async) PHP-യെ കുറിച്ച് ഞാൻ പഠിച്ച കാര്യങ്ങൾ
ഞാൻ വർഷങ്ങളോളം Laravel ഉപയോഗിച്ച് പ്രവർത്തിച്ചിട്ടുണ്ട്. ഞാൻ സിങ്ക് (sync) PHP ആണ് ഉപയോഗിച്ചിരുന്നത്. ഒരു റിക്വസ്റ്റ് വരുന്നു, ഒരു പ്രോസസ്സ് നടക്കുന്നു, തുടർന്ന് ഒരു റെസ്പോൺസ് പുറത്തേക്ക് പോകുന്നു. എനിക്ക് ഒരിക്കലും അസിങ്ക് (async) ആവശ്യമായി വന്നില്ല.
പിന്നീട് പുതിയ PHP 8.6 Polling API-യെ കുറിച്ച് ഞാൻ വായിച്ചു. PHP എങ്ങനെയാണ് ടാസ്ക്കുകൾ കൈകാര്യം ചെയ്യുന്നത് എന്നതിനെക്കുറിച്ചുള്ള എന്റെ കാഴ്ചപ്പാട് അത് മാറ്റിമറിച്ചു.
അസിങ്ക് എങ്ങനെയാണ് പ്രവർത്തിക്കുന്നത് എന്നതിന്റെ വിശദീകരണം താഴെ നൽകുന്നു.
Blocking I/O-യിലെ പ്രശ്നം
നിങ്ങൾ ഒരു API വിളിക്കുമ്പോൾ, നിങ്ങളുടെ കോഡ് കാത്തിരിക്കുന്നു.
ഉദാഹരണം: $response = Http::get('https://api.example.com');
ആ API 300ms എടുക്കുകയാണെങ്കിൽ, നിങ്ങളുടെ PHP പ്രോസസ്സ് ആ 300ms നേരം ഒന്നും ചെയ്യാതെ ഇരിക്കും. അത് ഒരു 'sleep state'-ൽ ആയിരിക്കും. ഇത് മെമ്മറി ഉപയോഗിക്കുകയും ഒരു വർക്കർ സ്ലോട്ട് (worker slot) കൈവശം വയ്ക്കുകയും ചെയ്യുന്നു. നിങ്ങളുടെ എല്ലാ വർക്കർമാരും സ്ലീപ്പ് അവസ്ഥയിലാണെങ്കിൽ, നിങ്ങളുടെ സെർവർ പുതിയ റിക്വസ്റ്റുകൾ സ്വീകരിക്കുന്നത് നിർത്തും.
അസിങ്ക് (Async) പരിഹാരം
ആ 300ms സമയത്തിനിടയിൽ മറ്റ് ജോലികൾ ചെയ്യാൻ അസിങ്ക് നിങ്ങളെ അനുവദിക്കുന്നു. കാത്തിരിക്കുന്നതിന് പകരം, നിങ്ങൾക്ക് മറ്റ് ടാസ്ക്കുകൾ പ്രവർത്തിപ്പിക്കാം.
എന്നാൽ ഡാറ്റ എപ്പോൾ എത്തുന്നു എന്ന് നിങ്ങൾ എങ്ങനെ അറിയും? ഇവിടെയാണ് കേർണൽ (kernel) പ്രസക്തമാകുന്നത്.
Polling-ന്റെ പരിണാമം
select() PHP 4 മുതൽ PHP-യിൽ
stream_select()ഉണ്ട്. ഇത് കേർണലിനോട് ചോദിക്കുന്നു: "ഈ സോക്കറ്റുകളിൽ (sockets) ഏതെങ്കിലും ഡാറ്റ തയ്യാറാണോ?" ഇതിലെ പ്രശ്നം 'rescan tax' ആണ്. നിങ്ങൾക്ക് 10,000 കണക്ഷനുകൾ ഉണ്ടെങ്കിൽ, ഓരോ തവണയും മുഴുവൻ ലിസ്റ്റും കേർണലിന് അയക്കേണ്ടി വരും. ഇത് സാവധാനത്തിലാകുകയും പരിധികളെ ബാധിക്കുകയും ചെയ്യുന്നു.epoll / kqueue ഇതൊരു കേർണൽ ഫീച്ചറാണ്, ഒരു ലാംഗ്വേജ് ഫീച്ചറല്ല. Linux ഉപയോഗിക്കുന്നത് epoll ആണ്. macOS ഉപയോഗിക്കുന്നത് kqueue ആണ്. മുഴുവൻ ലിസ്റ്റും സ്കാൻ ചെയ്യുന്നതിന് പകരം, കേർണൽ ഒരു 'ready-list' സൂക്ഷിക്കുന്നു. ഏത് പ്രത്യേക സോക്കറ്റുകളിലാണ് ഡാറ്റ ഉള്ളതെന്ന് അത് നിങ്ങളോട് പറയുന്നു. അധിക ചിലവില്ലാതെ ആയിരക്കണക്കിന് കണക്ഷനുകളിലേക്ക് ഇത് വ്യാപിപ്പിക്കാൻ (scale) സാധിക്കും.
Fibers (PHP 8.1) കോൾ സ്റ്റാക്കിലെ (call stack) എവിടെ വേണമെങ്കിലും ഒരു ഫംഗ്ഷൻ നിർത്തിവെക്കാൻ (pause) Fibers നിങ്ങളെ അനുവദിക്കുന്നു. ഒരു Fiber തനിയെ ഉണരില്ല. അത് നിർത്തിവെച്ച ഒരു YouTube വീഡിയോ പോലെയാണ്. അത് വീണ്ടും പ്രവർത്തിപ്പിക്കാൻ ആരോ ഒരാൾ
$fiber->resume()വിളിക്കണം.
വിട്ടുപോയ കണ്ണികൾ: PHP 8.6
Async I/O-യ്ക്ക് മൂന്ന് ഭാഗങ്ങൾ ആവശ്യമാണ്: • Pause: Fibers (ഇപ്പോൾ PHP കോറിലുണ്ട്) • Decide: The Event Loop (സാധാരണ PHP കോഡ്) • Know: Kernel Polling (വിട്ടുപോയ ഭാഗം)
പഴയ ടൂളുകളോ C എക്സ്റ്റൻഷനുകളോ ഉപയോഗിക്കാതെ, ഏത് സോക്കറ്റ് ആണ് തയ്യാറാണെന്ന് "അറിയാൻ" PHP-ക്ക് ഇതുവരെ ഒരു നേറ്റീവ് (native) മാർഗ്ഗമില്ലായിരുന്നു.
PHP 8.6 ഈ വിടവ് നികത്തുന്നു. ഇത് കോറിലേക്ക് ഒരു നേറ്റീവ് Polling API കൊണ്ടുവരുന്നു. ഇത് Linux-ൽ സ്വയമേവ epoll-ഉം Mac-ൽ kqueue-ഉം ഉപയോഗിക്കും.
മൊത്തത്തിലുള്ള കാഴ്ചപ്പാട്
അസിങ്ക് എന്നത് ഒരു മാന്ത്രികവിദ്യയല്ല. ഒരു ഫൈബറിൽ (Fiber) എപ്പോൾ resume() വിളിക്കണമെന്ന് തീരുമാനിക്കുന്ന ഒരു PHP കോഡ് മാത്രമാണ് ഇവന്റ് ലൂപ്പ് (event loop).
നിർത്തിവെക്കാനുള്ള (pause) കഴിവ് Fibers നൽകുന്നു. എപ്പോൾ വീണ്ടും തുടങ്ങണം (unpause) എന്ന് അറിയാനുള്ള ബുദ്ധി epoll നൽകുന്നു.
നിങ്ങൾ സിങ്ക് PHP മാത്രമേ ഉപയോഗിക്കുന്നുള്ളൂ എങ്കിൽ, ഇന്ന് നിങ്ങളുടെ Laravel ആപ്പുകളിൽ മാറ്റം വരുത്തേണ്ടതില്ല. എന്നാൽ ഈ മോഡൽ മനസ്സിലാക്കുന്നത് ReactPHP അല്ലെങ്കിൽ Amp പോലുള്ള അസിങ്ക് ലൈബ്രറികൾ എളുപ്പത്തിൽ പഠിക്കാൻ നിങ്ങളെ സഹായിക്കും.
വെറുതെ ഉപയോഗിക്കാതെ നിർമ്മിക്കാൻ പഠിക്കുക. ഇത് എങ്ങനെ പ്രവർത്തിക്കുന്നു എന്ന് കാണാൻ കോഡ് സ്വയം റൺ ചെയ്തു നോക്കൂ.
