Nginx Basics in OpenResty

Nginx version

The OpenResty version is much behind the standard Nginx version, so the functions supported by the newer Nginx may not be supported by OpenResty .

Nginx process model

After starting Nginx, we use ps to view related processes:

$ ps -ef --forest | grep nginx
root     32475     1  0 13:36 ?        00:00:00 nginx: master process /usr/sbin/nginx
                                                -c /etc/nginx/nginx.conf
nginx    32476 32475  0 13:36 ?        00:00:00  _ nginx: worker process
nginx    32477 32475  0 13:36 ?        00:00:00  _ nginx: worker process
nginx    32479 32475  0 13:36 ?        00:00:00  _ nginx: worker process
nginx    32480 32475  0 13:36 ?        00:00:00  _ nginx: worker process
nginx    32481 32475  0 13:36 ?        00:00:00  _ nginx: cache manager process
nginx    32482 32475  0 13:36 ?        00:00:00  _ nginx: cache loader process

Nginx has one and only one Master process to perform some high-privilege operations, such as reading configuration and binding ports, etc., but it is not responsible for processing requests, and the number of Worker processes is generally consistent with the number of logical cores of the host CPU. When Nginx starts or reloads, the Master process will fork out a set of Worker processes, which are independent of each other, a bit like the tabs of the Chrome browser, and a crash of one will not affect the others.

Formally such an architecture endows Nginx with the capability of binary hot upgrade.

Hot upgrade starts a new Master process and gradually shuts down Worker processes by sending USR2 and WINCH semaphores to the old Master process. At this time, if you need to roll back, you can still send the HUP semaphore to the old Master. If you are sure that you do not need to roll back, you can send the KILL semaphore to the old Master to exit.

Nginx architecture official document: https://www.nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale/

Nginx execution stage

Nginx has 11 execution stages, which can be seen from the source code https://github.com/nginx/nginx/blob/master/src/http/ngx_http_core_module.h :

typedef enum {
    NGX_HTTP_POST_READ_PHASE = 0,

    NGX_HTTP_SERVER_REWRITE_PHASE,

    NGX_HTTP_FIND_CONFIG_PHASE,
    NGX_HTTP_REWRITE_PHASE,
    NGX_HTTP_POST_REWRITE_PHASE,

    NGX_HTTP_PREACCESS_PHASE,

    NGX_HTTP_ACCESS_PHASE,
    NGX_HTTP_POST_ACCESS_PHASE,

    NGX_HTTP_PRECONTENT_PHASE,

    NGX_HTTP_CONTENT_PHASE,

    NGX_HTTP_LOG_PHASE
} ngx_http_phases;

The relationship between the command in OpenResty *_by_luaand the four phases of Nginx is as follows:

This is also a picture that needs to be compared at all times during OpenResty development.

  • init_by_luaExecuted when the Nginx Master process is created, that is, it will only be executed once in the entire Nginx life cycle

    init_by_luaLua modules and common read-only data are usually preloaded during the stage, which can take advantage of the COW (copy on write) feature of the operating system to save some memory .

    # this runs before forking out nginx worker processes:
    init_by_lua_block { require "cjson" }
    
    server {
        location = /api {
            content_by_lua_block {
                -- the following require() will just  return
                -- the alrady loaded module from package.loaded:
                ngx.say(require "cjson".encode{dog = 5, cat = 6})
            }
        }
    }
    
  • init_worker_by_luaExecuted when each Nginx Worker process is created, this anchor is often used to create timers (via ngx.timer.at Lua API).

    init_worker_by_lua '
        local delay = 3  -- in seconds
        local new_timer = ngx.timer.at
        local log = ngx.log
        local ERR = ngx.ERR
        local check
    
        check = function(premature)
            if not premature then
                -- do the health check or other routine work
                local ok, err = new_timer(delay, check)
                if not ok then
                    log(ERR, "failed to create timer: ", err)
                    return
                end
            end
        end
    
        local hdl, err = new_timer(delay, check)
        if not hdl then
            log(ERR, "failed to create timer: ", err)
            return
        end
    ';
    
  • set_by_lua

    The operation of the business code can usually set_by_luabe completed at each stage from the beginning, and it is recommended to split the business process according to different functions. set_by_luaDirectives are recommended for setting variables.

  • rewrite_by_lua

    Forward, redirect

  • access_by_lua

    access, permissions

  • content_by_lua

    Generate return content

  • header_filter_by_lua

    Response header filtering

  • body_filter_by_lua

    Response body filtering

  • log_by_lua

    logging

The OpenResty lua-nginx-module document https://github.com/openresty/lua-nginx-module/blob/master/README.markdown has a very detailed description of the usage of each directive.

In particular, pay attention to the Nginx context supported by each anchor , which is the scope of the directives in the Nginx configuration file. Directives written in unsupported contexts will cause OpenResty to fail to start.

OpenResty Development Principles

  • Configure nginx.conf as little as possible
  • Avoid using the cooperation of multiple instructions such as if, set, and rewrite
  • Try to use Lua script to control the behavior of Nginx

Guess you like

Origin blog.csdn.net/weixin_44388689/article/details/131320981