GitHub Hot Board

GitHub Hot Board · Depo arşivi

matsumotory/ngx_mruby

ngx_mruby - A Fast and Memory-Efficient Web Server Extension Mechanism Using Scripting Language mruby for nginx (Bu açıklama depodan gelir.)

Veri tarihi October 22matsumotory

En iyi sıra

#36

Canlı Kilometre Taşları

997

Toplam yıldız

114

Toplam fork

1

Son 30 günde sıralama günü

Proje belgeleri

ngx_mruby

ngx_mruby: A Fast and Memory-Efficient Nginx Extension Mechanism Scripting with mruby.

Documents

Branch strategy

ngx_mruby has three long-lived code branches: master, next and v2.x (the gh-pages branch holds the site, ngx.mruby.org). Their names and roles stay as they are. master is the 2.x line until v3 is promoted to it, so that everyone who builds from the default branch keeps receiving the 2.x security fixes. v3 is developed on next and becomes master at v3.0.0 (the promotion). From then on, v2.x carries 2.x.

              until the promotion                 |  after the promotion
                                                  |
next    ---*alpha.1---*beta.1---*rc.1---*rc.N---+ |  - - ?
                                                 \
master  -*v2.7.0--*v2.7.x-- ... -----------o------M------*------*--- ... --> 3.x
         :        :                        :
v2.x    -*v2.7.0--*v2.7.x-- ... -----------o----------*------*------ ... --] 2.x

*  a release tag (v2.*, v3.*) or a pre-release tag (v3.0.0-*); v2.7.x stands
   for the 2.x releases after v2.7.0
o  the last 2.x commit on master
:  the same commit on both branches
M  the merge of next into master, tagged v3.0.0
?  what next becomes after the promotion is open (see the table below)
]  the end of 2.x support, twelve months after v3.0.0
The merges of master into next before the promotion are not drawn.
Branch Until the promotion After the promotion (v3.0.0)
master (default branch) The 2.x line: 2.x fixes, v2.* releases The 3.x line: v3.* releases
v2.x The same commits as master: a workflow copies every push to master to v2.x The 2.x line: stability and security fixes, v2.* releases
next Development of v3 and its pre-releases Open; the recommendation is to keep it for the development of 3.1 (see Promoting v3 to master)

Until the promotion, master is merged into next after 2.x fixes, so v3 has them too.

v3 is developed on next. Its pre-releases are tagged v3.0.0-alpha.N, v3.0.0-beta.N and v3.0.0-rc.N and are marked as pre-releases on GitHub. Section 6 of the v3 plan (docs/proposals/v3-plan.md on next) sets when the first pre-release of each kind is tagged:

  • v3.0.0-alpha.1: when the 2.x test suite passes on the new core of v3 and the sanitizers report nothing.
  • v3.0.0-beta.1: when the migration guide and the examples exist.
  • v3.0.0-rc.1: when the site and the examples are complete.

v3.0.0 is tagged when next is promoted to master, under the conditions in Promoting v3 to master. No date is set. At least one v3.0.0-rc.N comes first, and how long the last one stays out before v3.0.0 is still open. The pre-releases and releases appear on the releases page; to be notified of them, watch the repository with "Custom" and "Releases" selected.

For existing users

If you do not want anything to change, build from v2.x or from the latest v2.* release tag instead of master, and switch now:

git clone -b v2.x https://github.com/matsumotory/ngx_mruby.git     # the 2.x branch
git clone -b vX.Y.Z https://github.com/matsumotory/ngx_mruby.git   # or the latest v2.* release tag

A release tag does not receive fixes. If you pin one, move to each new 2.x release, because only the latest 2.x release is supported (see SECURITY.md), or pin v2.x, which receives the 2.x fixes as they are merged.

If you start using ngx_mruby now, the same applies: for production, build from v2.x or the latest v2.* release tag, and to try v3, track next.

Until the promotion, v2.x has the same commits as master, so pinning it does not change the code you build until then. At the promotion, master becomes v3.0.0, a new major version. Section 7 of the v3 plan already decides changes to its build requirements and behavior: mruby 4.1 instead of 3.3; nginx 1.30 (stable) and 1.31 (mainline) as the oldest supported versions, raised every April, so that users of older nginx (1.28, or the 1.26 and 1.24 packages of Linux distributions) stay on 2.x; OpenSSL 3.5 as the baseline with 1.1.1 and 3.0 dropped; auto-ssl removed from the default build; and the behavior changes of item 8: a Ruby API called outside the phase it is designed for raises an exception, an exception after rputs returns 500, Headers#delete matches the full header name, Nginx.return 200 with an empty body is allowed, and a body is sent with any status. The v3 migration guide will list each change.

The 2.x line (master until the promotion, then v2.x) puts compatibility first. It receives only stability fixes (crashes, hangs, leaks, and build fixes such as those for new nginx, OS, compiler or OpenSSL releases) and security fixes, and it changes behavior only as far as the fix of a defect requires. From the next release on, the release notes in docs/releases/ list each such change. 2.x stays supported for twelve months after v3.0.0 (see SECURITY.md).

Releases are tagged vX.Y.Z. If you contribute a fix, send 2.x fixes to master until the promotion and v3 work to next (see AGENTS.md).

Before upgrading, read the "Behavior changes: read before upgrading" section of every newer release in docs/releases/.

Please report security vulnerabilities privately as described in SECURITY.md.

What's ngx_mruby

ngx_mruby is A Fast and Memory-Efficient TCP/UDP Load Balancing and Web Server Extension Mechanism Using Scripting Language mruby for nginx.

  • ngx_mruby is to provide an alternative to lua-nginx-module or mod_mruby of Apache httpd.
  • Unified Ruby Code between Apache(mod_mruby), nginx(ngx_mruby) and other Web server software(plan) for Web server extensions.
  • You can implement nginx modules by Ruby scripts on nginx!
  • You can implement some Web server software extensions by same Ruby code (as possible)
  • Supported nginx main-line and stable-line
  • Benchmark between ngx_mruby and lua-nginx-module
# location /proxy {
#   mruby_set $backend "/path/to/proxy.rb";
#   proxy_pass   http://$backend;
# }

backends = [
  "test1",
  "test2",
  "test3",
]

r = Redis.new "192.168.12.251", 6379
r.get backends[rand(backends.length)]

This example needs the Redis class of mruby-redis, and a running Redis server. The default build_config.rb builds mruby-redis again since 2.7.2; 2.7.1 left it out.

  • see examples
  • Sample of Unified Ruby Code between Apache(mod_mruby) and nginx(ngx_mruby) for Web server extensions
  • You can implement some Web server software extensions by same Ruby code (as possible)
# Unified Ruby Code between Apache(mod_mruby) and nginx(ngx_mruby)
# for Web server extensions.
#
# Apache httpd.conf by mod_mruby
#
# <Location /mruby>
#     mrubyHandlerMiddle "/path/to/unified_hello.rb"
# </Location>
#
# nginx nginx.conf by ngx_mruby
#
# location /mruby {
#     mruby_content_handler "/path/to/unified_hello.rb";
# }
#

Server = get_server_class

Server::rputs "Hello #{Server::module_name}/#{Server::module_version} world!"
# mod_mruby => "Hello mod_mruby/0.9.3 world!"
# ngx_mruby => "Hello ngx_mruby/0.0.1 world!"

ngx_mruby mod_mruby performance

※ hello world simple benchmark, see details of blog entry.

Abstract

As the increase of large-scale and complex Web services, not only the development of Web applications is required, but also the implementation of Web server extensions in many cases. Most Web server extensions are mainly implemented in the C language because of fast and memory-efficient behavior, but by writing extensions using a scripting language we can achieve better maintainability and productivity.

However, if the existing methods are primarily intended to enhance not the implementation of Web applications but the implementation of internal processing of the Web server, the problem remains in terms of speed, memory-efficiency and safety.

Therefore, we propose a fast and memory-efficient Web server extension mechanism using a scripting language. We designed an architecture where the server process creates a region in memory to save the state of the interpreter at the server process startup, and multiple scripts share this region to process the scripts quickly when new request are made.

The server process frees the global variables table, the exception flag and the byte-code which cause an increase of memory usage, in order to reduce the memory usage and extend safety by preventing interference between each script because of sharing the region. We implemented a mechanism that can extend the internal processing of nginx easily by Ruby scripts using nginx and the embeddable scripting language mruby. It's called "ngx_mruby".

What a worker keeps between requests

The abstract above describes the design of the paper. ngx_mruby today does not free the global variables table between scripts. nginx creates one mrb_state for the http {} block (and one for the stream {} block) while it reads the configuration, and runs the init code (mruby_init, mruby_stream_init) and the server configuration code (mruby_server_context_handler_code) in it before it starts the workers, in the master process. Each worker process gets its own copy when nginx forks it, and runs all the other mruby code of the block in that copy: the init_worker and exit_worker code and every handler and filter, in every server and location, for every client. A reload or a restart starts new workers with a new state.

Global variables, constants, instance variables of main (the self of handler code), methods defined with def, classes and modules with their constants, and what Userdata holds (it keeps its values in a global variable) stay in the worker from one request to the next. What one request leaves behind is seen by every later request that the same worker handles, also when the code raised an exception after it made the change. Each worker has its own copy, so one worker does not see the values of another. After each run, ngx_mruby clears the exception (mrb->exc); a script file without cache is read and compiled again for the next run, and inline code and cached scripts keep the byte-code compiled at startup. The garbage collector frees the objects that nothing refers to any more. Local variables do not stay: each run of handler code starts without them.

Do not keep the data of one request in global variables, constants, instance variables of main or Userdata, since the next request of the worker, from any client, sees it. Use local variables, and read and write the request through Nginx::Request, Nginx::Var, Nginx::Headers_in and Nginx::Headers_out (in stream {}, where code runs per session, Nginx::Stream::Connection). To pass data from one handler to a later handler of the same request, declare an nginx variable with set $name ""; and read and write it through Nginx::Var, or set the Userdata value in every request before it is read. A set in the location runs after mruby_rewrite_handler and empties the variable again, so declare a variable that a rewrite handler writes with set in the server {} block. Keep in globals and constants only what all requests of the worker are meant to share, such as settings that the init or init_worker code prepares. Nginx.remove_global_variable removes a global variable.

Contributions

This project exists thanks to all the people who contribute. We also welcome financial contributions in full transparency on our open collective.

Backers

Thank you to all our backers! 🙏 [Become a backer]

Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]

License

This project is under the MIT License:

Mevcut sıralamalar

  • 36

    Canlı Kilometre Taşları

    997 yıldız · 114 fork · Sonraki çizgiye Star

    Kilometre →

Son 30 gün grafiği

Toplam yıldız

Sıra grafiği

Aynı panoda komşu sıralar

← Sıralamalara dön