A design and implementation to connect middleware supporting Internet service with mruby Ryosuke Matsumoto / Pepabo R&D Institute, GMO Pepabo, Inc. 2018.06.02 RubyKaigi2018 Design pattern for embedding mruby into middleware
• Chief engineer at GMO Pepabo, inc. • Chief researcher at Pepabo R&D Institute • Ph.D of Informatics, Kyoto University • my interests: Operation technology, Internet foundation technology, System programming, Highly integrated multi- tenant architecture, Hosting service, Cloud platform, C, mruby, Rust • Engineering => Technology <= Research 2 Ryosuke Matsumoto @matsumotory
• System management for network, OS and middleware • Hosting service, Cloud platform service • operation technology for middleware written by C • Apache, nginx, dovecot, postfix, sendmail, bind, proftp… • want to write operation tools for middleware using perl • want to write extension module for middleware • each middleware dependency • Apache module, nginx module, dovecot plugin…. 7 I’m a former web operation engineer
• mod_mruby / ngx_mruby (http server extension) • dovecot-mruby-plugin (imap server extension) • pmilter (milter server) • Trusterd HTTP/2 Web Server • h2o_mruby (Initial implementation with v1.4) • other system tools: rcon, capcon, pfds, virtualing, ab-mruby • developed the greatest number of mrbgem in mgem-list • also received Ph.D of informatics 12 my developed middleware with mruby
• middleware behavior scripting with mruby • middleware configuration as code • limit Ruby methods by mruby • dynamically control middleware by session parameters • cooperate with microservices • record a session data and utilize the data • implement Service Mesh functions • HTTP(S)ɾTCP/UDP stream 13 Why embed mruby into middleware
• consider several viewpoints • memory management (allocate/free/leak) • performance • usability, operation / development technology • strategy for multi process / multi threading • ʮmruby = mrb_stateʯ in this presentation 14 How embed mruby into middleware
• The basic strategy is embedding mruby into each thread • lock between threads in single mrb_state is complicated • A cost of creating mrb_state is much higher than creating thread • The cost becomes bottleneck each request to middleware • We want to create mrb_state on init phase of middleware • control only bytecode each request 19 considerations
• talk about design patterns for embedding mruby into middleware • try and error over and over again for 6 years • consider several viewpoints • memory management • performance • usability, operation / development technology 20 In this presentation
• Advantages • mruby scripts are executed completely independently • can save memory • Disadvantages • can’t pass objects to a request phase • can’t share objects with each other script 25 init: independent mrb_state
• Advantages • decrease a cost of creating mrb_state each script • can save memory • can share objects with each other script on init phase • Disadvantages • can’t pass objects to a request phase 28 init: share mrb_state
• Advantages • decrease a cost of creating mrb_state each script • can share objects with each other script on init phase • can pass objects to a request phase • use DB object which connect the DB at init phase • Disadvantages • use more memory than other init pattern • complicated memory management each request 31 init: share mrb_state with request phase
• Advantages • mruby scripts are executed completely independently • can manage memory easily and correctly • change script each request • Disadvantages • low performance because of creating mrb_state each request • can’t share objects with each other script each request 35 request: independent mrb_state
• Advantages • can share objects with each other script each request and init phase • change script each request • Disadvantages • slightly low performance because of compiling • memory management is very complicated because of compiling and freeing bytecode each request while sharing mrb_state 37 request: independent mrb_state
• Advantages • high performance • can share objects with each other script each request and init phase • Disadvantages • can’t change script each request • memory management is a bit complicated 39 request: independent mrb_state
• multi process model • share mrb_state and bytecode • mod_mruby, ngx_mruby, postfix-mruby, dovecot- mruby, trusterd HTTP/2 server • multi threading model • share mrb_state and bytecode • H2O, nghttpd • independent mrb_state • pmilter 46 Summary: each request pattern
• want to accept as many requests simultaneously as possible in single process/thread (C10k) • want to use multi cpu core sufficiently • process blocking operation in non-blocking mode • File I/O, Network I/O, sleep… • monitor I/O state and notify status change like epoll() • generally implement suitable event loop for middleware 48 non-blocking middleware
• mruby blocks middleware processing generally • bottleneck of performance when accepting multiple requests simultaneously • Other responses are delayed in proportion to the time of processing of mruby blocking 49 non-blocking middleware with mruby
blocking each request with mruby 51 SFRVFTU NSVCZ NSVCZ SFTQPOTF SFRVFTU SFRVFTU SFTQPOTF SFTQPOTF NSVCZ TFOESFTQPOTF SFDWSFRVFTU BUUIFTBNFUJNF Other responses are delayed in proportion to the time of processing of mruby blocking OPOCMPDLJOHNJEEMFXBSFMJLFOHJOYJOTJOHMFQSPDFTT
• change a blocking method of mruby to non-blocking • suspend mruby processing until the blocking method is completed • return to event loop of middleware from mruby • resume mruby processing by callback func in event loop 55 non-blocking middleware with mruby
• Why / How embed mruby into middleware • connect services dynamically and programmably • design pattern for embedding mruby into middleware • init /exit • each request • blocking / non-blocking • We will release ngx_mruby v2 in the near future • Happy hacking mruby! 71 Conclusion