ngx_mruby v2における ノンブロッキングなmruby実行の実装詳細

ngx_mruby v2における ノンブロッキングなmruby実行の実装詳細

RubyWouldConference2018にてngx_mruby v2のノンブロッキングインターフェースについてトークしました。

1b838da2065660793d5b26f2cdc32de7?s=128

Kazuhiko Yamashita

November 05, 2018
Tweet

Transcript

  1. ʙ͋Εͬʁ࡞ऀɾɾɾ͋Εͬʁʁʁฤʙ !QZBNB(.01FQBCP *OD 3VCZ8PVME$POGFSFODF OHY@NSVCZWʹ͓͚Δ ϊϯϒϩοΩϯάͳNSVCZ࣮ߦͷ ࣮૷ৄࡉ

  2. γχΞɾϓϦϯγύϧΤϯδχΞ ࢁԼ࿨඙!QZBNB ϗεςΟϯάࣄۀ෦νʔϑςΫχΧϧϦʔυ IUUQTUFOTOBQPODPN

  3. ϗεςΟϯάࣄۀ &$ࢧԉࣄۀ ϋϯυϝΠυɾͦͷଞࣄۀ

  4. ೥ ϩϦϙοϓʂϨϯλϧαʔόαʔϏεఏڙ։࢝ ೥ ೥ ೥ ϔςϜϧαʔϏεఏڙ։࢝ 1ࢁ͕ϖύϘʹೖࣾʂʂ̍ ೥݄೔ ࣛࣇౡݝग़ਫࢢʹ͓͍ͯ1ࢁര஀ʂʂ̍ ೥

    ݱࡏɾ૑ۀ೥໨ ϜʔϜʔυϝΠϯαʔϏεఏڙ։࢝
  5. 45/4 -JOVY/444FSWFS TUOTKQ

  6. 45/4

  7. ࠓ೔࿩͢͜ͱ wOHY@NSVCZ wOHJOYͷجຊ wOHY@NSVCZWͷ՝୊ wOHY@NSVCZWʹ͓͚ΔϊϯϒϩοΩϯάॲཧ

  8. લఏ wOHJOYͷΠϕϯτϞδϡʔϧ͸FQPMMલఏͰ࿩͠·͢ w3VCZͷ࿩Λ͠·͕͢ɺ3VCZߏจͷ࿩͸͋·Γग़͖ͯ ·ͤΜ

  9. OHY@NSVCZ "'BTUBOE.FNPSZ&⒏DJFOU8FC4FSWFS&YUFOTJPO.FDIBOJTN 6TJOH4DSJQUJOH-BOHVBHFNSVCZGPSOHJOY IUUQOHYNSVCZPSH

  10. OHY@NSVCZWʹίϯτϦϏϡʔτ

  11. None
  12. 

  13. OHY@NSVCZ NSVCZ@TTM@IBOETIBLF@IBOEMFS@DPEF TTMOHJOY44-OFX DFSUJpDBUF@EBUB'JMFSFBE QBUIUP\TTMTFSWFSOBNF^DSU  LFZ@EBUB'JMFSFBE QBUIUP\TTMTFSWFSOBNF^LFZ  TTMDFSUJpDBUF@EBUBDFSUJpDBUF@EBUB

    TTMDFSUJpDBUF@LFZ@EBUBLFZ@EBUB  OHJOYͷ͋ΒΏΔΠϕϯτʹϑοΫͯ͠ɺNSVCZͷίʔυΛ࣮ߦ͠ɺ ϓϥΨϒϧʹτϥϑΟοΫίϯτϩʔϧग़དྷΔ
  14. ϖύϘͷࣄྫ ಈతূ໌ॻ؅ཧ ਺ඦສυϝΠϯͷূ໌ॻΛ.Z42-Ͱ؅ཧ ίϯςϯπΩϟογϡ ΩϟογϡϙϦγʔΛ)551"1*ܦ༝Ͱऔಘ͠ɺOHJOYͷ Ωϟογϡͷ0/ɾ0''Λίϯτϩʔϧ

  15. OHJOY  NSVCZ

  16. Πϕϯτۦಈ ඇಉظ*0 OHJOY

  17. Πϕϯτۦಈ OHJOY FQPMM FWFOU FWFOU FWFOU DMJFOU DMJFOU DMJFOU BDDFQU

    BDDFQU BDDFQU FQPMM@XBJU  ઀ଓ΍ϨεϙϯεΛ*0Πϕϯτͱͯ͠ॲཧ͢Δ IUUQTMJOVYKNPTEOKQIUNM-%1@NBOQBHFTNBOFQPMM@XBJUIUNM
  18. ඇಉظ*0શͯ͸ϑΝΠϧͰ͋Δ OHJOY FQPMM FWFOU FWFOU FWFOU DMJFOU DMJFOU DMJFOU BDDFQU

    BDDFQU BDDFQU FQPMM@XBJU  ϑΝΠϧσΟεΫϦϓλͦΕͧΕΛϒϩοΫͤͣ FQPMMͰඇಉظʹ*0ॲཧΛߦ͏ GE GE GE
  19. OHJOYXPSLFS OHJOY FQPMM FWFOU FWFOU FWFOU DMJFOU DMJFOU DMJFOU BDDFQU

    BDDFQU BDDFQU FQPMM@XBJU  ΫϥΠΞϯτ͔ΒͷϦΫΤετ͸XPSLFS͕ॲཧ XPSLFS XPSLFS NBTUFS FQPMM@XBJU 
  20. OHY@NSVCZ OHJOY FQPMM FWFOU FWFOU FWFOU DMJFOU DMJFOU DMJFOU BDDFQU

    BDDFQU BDDFQU FQPMM@XBJU  )551ϦΫΤετ࣌ͷNSVCZ࣮ߦ΋XPSLFSͰߦΘΕΔ XPSLFS XPSLFS NBTUFS MPDBUJPOIFBEFST\ NSVCZ@DPOUFOU@IBOEMFS@DPEF SOHJOY3FRVFTUOFX SDPOUFOU@UZQFUFYUIUNM OHJOYSQVUTIFBEFST\SIFBEFST@JOBMM^CSCS  ^
  21. OHY@NSVCZͷ՝୊ SFRVFTU SFRVFTU SFRVFTU NSVCZ NSVCZ NSVCZ SFTQPOTF SFTQPOTF SFTQPOTF

    XPSLFS XPSLFS͋ͨΓͷNSVCZ࣮ߦͰඇಉظ*0͕ϒϩοΫ͞ΕΔ
  22. ࠓ೔ͷओ୊ SFRVFTU SFRVFTU SFRVFTU NSVCZ NSVCZ NSVCZ SFTQPOTF SFTQPOTF SFTQPOTF

    XPSLFS ͜͏ͳͬͨʂʂ͍̍ͯ͏࿩Λ͠·͢
  23. Ϧιʔε͕͏·͘׆༻Ͱ͖ͳ͍έʔε container.boot! loop do break if container.boot? sleep 1000 end

    OHY@NSVCZ͔ΒίϯςφϓϩηεΛىಈ͠ɺ ىಈ׬ྃΛTMFFQͰ଴ͭΑ͋͘Δॲཧ
  24. ՝୊Λղܾ͢ΔϊϯϒϩοΩϯάΠϯλʔϑΣʔε /HJOY"TZODTMFFQ /HJOY"TZOD)551TVC@SFRVFTU

  25. /HJOY"TZODTMFFQ

  26. /HJOY"TZODTMFFQ SFRVFTU SFRVFTU NSVCZ SFTQPOTF SFTQPOTF MPPQEP  CSFBLJGDPOUBJOFSCPPU 

     /HJOY"TZODTMFFQ FOE NSVCZ TMFFQ TMFFQ࣌ʹNSVCZͷϒϩοΫΛ։์͢Δ
  27. /HJOY"TZODTMFFQ wOHYFWFOUMPPQ wOHY@BEE@UJNFS w'JCFS

  28. OHJOYFWFOUMPPQ pOEUJNFS FQPMM@XBJU FYFDFWFOU IBOEMFS FYFDUJNFS IBOEMFS ௚ۙͰൃՐ͢ΔλΠϚʔΛ୳͢ *0ΠϕϯτΛ଴ͭ *0ΠϕϯτͷϋϯυϥΛ࣮ߦ͢Δ

    λΠϚʔͷϋϯυϥΛ࣮ߦ͢Δ
  29. OHJOYFWFOUIBOEMFS wOHJOYͰ͸FWFOUʹIBOEMFSΛఆٛग़དྷΔ wUJNFSͷIBOEMFS͸ίʔϧόοΫͷΑ͏ͳΠϝʔδ wϢʔβʔͷ೚ҙͷΦϒδΣΫτΛ֨ೲɺऔΓग़͢͜ͱ ͕Մೳ

  30. OHY@BEE@UJNFS ev = (ngx_event_t *)p; ev->handler = ngx_mrb_timer_handler; ev->data =

    re; ngx_add_timer(ev, (ngx_msec_t)timer); FWEBUBʹNSC@TUBUFͳͲ3VCZͷ৘ใΛอ࣋͠ɺ IBOEMFS࣮ߦ࣌ʹऔΓग़͠ɺ3VCZΛ࣮ߦ͢Δ
  31. 3VCZͷίϯςΩετ͸Ͳ͏ͳΔ͔ʁ puts "1" Nginx::Async.sleep 1000 puts "2" /HJOY"TZODTMFFQ͕࣮ߦ͞Εɺ QVUT͕࣮ߦ͞Εͯ͠·͏ ˠ3VCZͷॲཧΛఀࢭ͢Δඞཁ͕͋Δ

  32. 'JCFS

  33. 'JCFS fiber = Fiber.new { puts 'Ruby is' Fiber.yield puts

    'Good' } fiber.resume fiber.resume ͍ΘΏΔίϧʔνϯͰɺ'JCFSZJFMEͷ࣌఺Ͱ ॲཧΛఀࢭͤ͞Δ͜ͱ͕ग़དྷΔɻ 'JCFSSFTVNFʹΑͬͯॲཧΛ࠶։
  34. 3VCZJT (PPE

  35. OHY@NSVCZ'JCFS *NBHF MPDBUJPOIFBEFST\ NSVCZ@DPOUFOU@IBOEMFS@DPEF QVUT /HJOY"TZODTMFFQ QVUT  ^ MPDBUJPOIFBEFST\

    NSVCZ@DPOUFOU@IBOEMFS@DPEF 'JCFSOFXEP QVUT /HJOY"TZODTMFFQ QVUT FOE  3VCZͷίʔυΛ'JCFSͰ҉໧తʹแΉ
  36. OHY@NSVCZ'JCFS *NBHF EFG@OHY@NSC@QSFQBSF@pCFS OHJOY@IBOEMFS  pCFS@IBOEMFS'JCFSOFX\OHJOY@IBOEMFSDBMM^ MBNCEBEP SFTVMUpCFS@IBOEMFSSFTVNF <pCFS@IBOEMFSBMJWF SFTVMU>

    FOE FOE 'JCFSΛ͞Βʹ1SPDͰแΉ
  37. /HJOY"TZODTMFFQ class Async class << self def sleep(*args) __sleep(*args) Fiber.yield

    end end end @@TMFFQ UJNFS࡞Δϝιου ಺Ͱ 'JCMFSΠϯελϯεΛ$ͷίϯςΩετʹ อଘ͠ɺOHJOYͷλΠϚʔϋϯυϥʔʹઃఆޙɺ 'JCFSZJFMEͰ3VCZΛఀࢭ
  38. OHY@BEE@UJNFS OHY@NSVCZ@UJNFS @IBOEFS 'JCFSZJFME 'JCFSSFTVNF 'JCFSΦϒδΣΫτΛίʔϧόοΫؔ਺ͷϙΠϯλͱڞʹ λΠϚʔʹηοτ λΠϚʔηοτ࣌఺Ͱ3VCZͷίϯςΩετΛఀࢭ͠ɺOHJOYͷ ΠϕϯτϧʔϓΛ࠶։ λΠϚʔΠϕϯτൃՐ࣌ʹ࣮ߦ͞ΕɺλΠϚʔΠϕϯτ͔Β

    3VCZͷίϯςΩετΛऔΓग़͢ 3VCZͷ࣮ߦΛ࠶։͢Δ /HJOY"TZOD4MFFQ
  39. /HJOY"TZOD)551TVC@SFRVFTU

  40. OHY@IUUQ@TVCSFRVFTU location / { # subrequest } location /subreqest {

    puts "hello" } # http://localhost/ => hello ͋ΔϩέʔγϣϯʹདྷͨϦΫΤετΛ ଞͷϩέʔγϣϯʹϦΫΤετͨ݁͠ՌͰ Ԡ౴͢ΔΑ͏ͳ࢖͍ํ
  41. SFRVFTU SFRVFTU NSVCZ SFTQPOTF SFTQPOTF NSVCZ ϦΫΤετΛ౤͛ΔͱϒϩοΫΛ։์͠ɺ Ϩεϙϯε࣌ʹίʔϧόοΫΛड͚औΓ࠶։ TVCSFRFTU 3FRVFTU

    3FTQPOTF /HJOY"TZOD)551TVC@SFRVFTU
  42. /HJOY"TZOD)551TVC@SFRVFTU3FEJT location / { # subrequest /redis } location /redis

    { puts redis get key } 3FEJTͷϦΫΤετ଴ͪ࣌ؒ΍ ֎෦"1*ΛOHY@NSVCZͰ࣮ߦ͢Δ Α͋͘Δέʔε
  43. /HJOY"TZOD)551TVC@SFRVFTU def sub_request(location, query_param = nil) if query_param.is_a?(Hash) __sub_request(location, ::nginx::Utils....)

    elsif query_param.is_a?(String) __sub_request(location, query_param) elsea __sub_request(location) end Fiber.yield end TMFFQͱಉ͘͡ɺ@@TVC@SFRVFTUͰ ίʔϧόοΫΛઃఆ͠ɺ'JCFSZJFME
  44. /HJOY"TZOD)551TVC@SFRVFTU ps->handler = ngx_mrb_async_http_sub_request_done; ps->data = actx; if (ngx_http_subrequest(r, actx->uri,

    args, &sr, ps, NGX_HTTP_SUBREQUEST_IN_MEMORY) != NGX_OK) { mrb_raise(mrb, E_RUNTIME_ERROR, "ngx_http_subrequest failed for http_sub_rquest method"); } ίʔϧόοΫΛઃఆ͠ɺαϒϦΫΤετΛ࣮ߦ͢Δ
  45. /HJOY"TZOD)551TVC@SFRVFTU static ngx_int_t ngx_mrb_async_http_sub_request_done(ngx_http_request_t *sr, void *data, ngx_int_t rc) {

    ngx_mrb_async_http_ctx_t *actx = data; ngx_mrb_reentrant_t *re = actx->re; ngx_http_mruby_ctx_t *ctx; re->r = sr->parent; ... ίʔϧόοΫͰฦ٫͞ΕΔOHY@IUUQ@SFRVFTU@Uߏ଄ମ˞͔Β͸ αϒϦΫΤετͷϨεϙϯεϘσΟ΍ϔομ͕औಘͰ͖ͳ͍ ˞֤ΠϕϯτͰ࣋ͪճΒΕΔɺϦΫΤετͷ৘ใ
  46. XBJUJOHTVCSFRVFTU pOBMJ[FCPEZpMUFS /HJOY"TZOD)551TVC@SFRVFTU NBJOSFRVFTU OHY@IUUQ@SFRVFTU@U TVCSFRVFTU OHY@IUUQ@SFRVFTU@U PUIFSFWFOU OHY@IUUQ@SFRVFTU@UNBJO pOJTISFRVFTU

    NSVCZ αϒϦΫΤετͷϨεϙϯε͸ɺϝΠϯϦΫΤετͷ ώʔϓʹॻ͍ͯ͋͛Δඞཁ͕͋Δ
  47. /HJOY"TZOD)551TVC@SFRVFTU location /async_http_sub_request { mruby_rewrite_handler_code ' Nginx::Async::HTTP.sub_request "/sub_req_dst" res =

    Nginx::Async::HTTP.last_response nginx.rputs res.body '; } Ϩεϙϯεͷड͚औΓ͸ϝΠϯϦΫΤετͷ(FUUFSΛ௨ͯ͠ɺ αϒϦΫΤετ͕ॻ͍ͨώʔϓͷ஋Λऔಘ
  48. ੑೳධՁ

  49. IUUQTICNBUTVNPUPSKQFOUSZ

  50. ଌఆ؀ڥ w.BD#PPL1SP.JE w$16()[*OUFM$PSFJ w.FNPSZ(# w7JSUVBM#PY w$16$PSF w.FNPSZ(# w046CVOUV9FOJBM

  51. TMFFQNTFD SFUVSO MPDBUJPO" CMPDLJOH IUUQSFRVFTU MPDBUJPO# OPOCMPDLJOH IUUQSFRVFTU BC $

    ab -n 10000 -c 100 http://127.0.0.1:58080/ PSJHJOʹ)551ϦΫΤετ͢Δ؀ڥ IUUQSFRVFTU IUUQSFRVFTU
  52. OPOCMPDLJOH͕ഒఔ౓ߴ଎Ͱ͋Δ CMPDLJOHIUUQSFRVFTU OPOCMPDLJOHIUUQSFRVFTU 3FRVFTUTQFSTFDPOE<TFD> NFBO  5JNFQFSSFRVFTU<NT> 5JNFQFSSFRVFTU<NT> 5SBOTGFSSBUF<,CZUFTTFD>SFDFJWFE 3FRVFTUTQFSTFDPOE<TFD>

    NFBO  5JNFQFSSFRVFTU<NT> 5JNFQFSSFRVFTU<NT> 5SBOTGFSSBUF<,CZUFTTFD>SFDFJWFE
  53. ࠷ޙʹ

  54. NSVCZ࠷ߴʂʂ̍ NSVCZʹΑͬͯΤϯδχΞͱͯ͠ɺ Ұஈਂ͘જΕΔΑ͏ʹͳͬͨ

  55. 5IBOLZPV ࠷৽ͷ࠾༻৘ใΛνΣοΫˠ !QC@SFDSVJU