您的位置:首页 > 运维架构 > Nginx

nginx设计解读--模块化设计及程序初始化

2015-07-27 11:53 766 查看

Nginx依赖的库如下:

[qxz@qiuxuezhong-test-dev001-sjhl tools]$ldd /usr/local/nginx/sbin/nginx

         linux-vdso.so.1=>  (0x00007fffbbfff000)

         libpthread.so.0=> /lib64/libpthread.so.0 (0x0000003267c00000)

         libcrypt.so.1=> /lib64/libcrypt.so.1 (0x0000003269800000)

         libpcre.so.1=> /usr/local/lib/libpcre.so.1 (0x00002b23b7b4a000)

         libcrypto.so.10=> /usr/lib64/libcrypto.so.10 (0x0000003e2b400000)

         libz.so.1=> /lib64/libz.so.1 (0x0000003268000000)

         libc.so.6=> /lib64/libc.so.6 (0x0000003267400000)

         /lib64/ld-linux-x86-64.so.2(0x0000003267000000)

         libfreebl3.so=> /usr/lib64/libfreebl3.so (0x0000003269c00000)

         libdl.so.2=> /lib64/libdl.so.2 (0x0000003267800000)

 

ngx_cycle_s包含了内存池、连接池、文件等,因此属于资源的管理者,应该是pbrpc中的RpcServer

 

struct ngx_cycle_s {

    void                  ****conf_ctx;

    ngx_pool_t               *pool;

 

    ngx_log_t                *log;

    ngx_log_t                 new_log;

 

    ngx_uint_t                log_use_stderr;  /* unsigned  log_use_stderr:1; */

 

    ngx_connection_t        **files;

    ngx_connection_t         *free_connections;

    ngx_uint_t                free_connection_n;

 

    ngx_queue_t               reusable_connections_queue;

 

    ngx_array_t               listening;

    ngx_array_t               paths;

    ngx_list_t                open_files;

    ngx_list_t                shared_memory;

 

    ngx_uint_t                connection_n;

    ngx_uint_t                files_n;

 

    ngx_connection_t         *connections;

    ngx_event_t              *read_events;

    ngx_event_t              *write_events;

 

    ngx_cycle_t              *old_cycle;

 

    ngx_str_t                 conf_file;

    ngx_str_t                 conf_param;

    ngx_str_t                 conf_prefix;

    ngx_str_t                 prefix;

    ngx_str_t                 lock_file;

    ngx_str_t                 hostname;

};

其中conf_ctx;为甚要用4级指针?

 

ngx_add_inherited_sockets函数中,查看了是否有环境变量NGINX,用于识别是否需要平滑升级。

Nginx注册模块是在main函数之前,

如下:

3 = 0

(gdb) watch ngx_max_module

Hardware watchpoint 2: ngx_max_module

(gdb) p ngx_modules[0]

$4 = (ngx_module_t *) 0x6806c0<ngx_core_module>

(gdb) p ngx_modules[1]

$5 = (ngx_module_t *) 0x680c60<ngx_errlog_module>

(gdb) p ngx_modules[2]

$6 = (ngx_module_t *) 0x6815c0<ngx_conf_module>

(gdb) p ngx_modules[4]

$7 = (ngx_module_t *) 0x681720<ngx_event_core_module>

(gdb) p ngx_modules[5]

$8 = (ngx_module_t *) 0x681e20<ngx_epoll_module>

(gdb) p ngx_modules[6]

$9 = (ngx_module_t *) 0x682060<ngx_regex_module>

(gdb) p ngx_modules[7]

$10 = (ngx_module_t *) 0x6821e0<ngx_http_module>

(gdb) p ngx_modules[8]

$11 = (ngx_module_t *) 0x6824c0<ngx_http_core_module>

(gdb) p ngx_modules[9]

$12 = (ngx_module_t *) 0x685ce0<ngx_http_log_module>

(gdb) p ngx_modules[11]

$13 = (ngx_module_t *) 0x6877a0<ngx_http_static_module>

(gdb) p ngx_modules[10]

$14 = (ngx_module_t *) 0x687000<ngx_http_upstream_module>

(gdb) p ngx_modules[12]

$15 = (ngx_module_t *) 0x689660<ngx_http_autoindex_module>

(gdb) p ngx_modules[13]

$16 = (ngx_module_t *) 0x6878c0<ngx_http_index_module>

(gdb) p ngx_modules[14]

$17 = (ngx_module_t *) 0x689860<ngx_http_auth_basic_module>

(gdb) p ngx_modules[1]

$18 = (ngx_module_t *) 0x680c60<ngx_errlog_module>

(gdb) p ngx_modules[15]

$19 = (ngx_module_t *) 0x689a40<ngx_http_access_module>

(gdb) p ngx_modules[16]

$20 = (ngx_module_t *) 0x689c20<ngx_http_limit_conn_module>

(gdb) p ngx_modules[17]

$21 = (ngx_module_t *) 0x689f60<ngx_http_limit_req_module>

(gdb) p ngx_modules[18]

$22 = (ngx_module_t *) 0x68a260<ngx_http_geo_module>

(gdb) p ngx_modules[19]

$23 = (ngx_module_t *) 0x68a3c0<ngx_http_map_module>

(gdb) p ngx_modules[20]

$24 = (ngx_module_t *) 0x68a5c0<ngx_http_split_clients_module>

(gdb) p ngx_modules[21]

$25 = (ngx_module_t *) 0x68a720<ngx_http_referer_module>

(gdb) p ngx_modules[22]

$26 = (ngx_module_t *) 0x68a920<ngx_http_rewrite_module>

(gdb) p ngx_modules[23]

$27 = (ngx_module_t *) 0x68bb00<ngx_http_proxy_module>

(gdb) p ngx_modules[24]

$28 = (ngx_module_t *) 0x68c940<ngx_http_fastcgi_module>

(gdb) p ngx_modules[25]

$29 = (ngx_module_t *) 0x68d580<ngx_http_uwsgi_module>

(gdb) p ngx_modules[26]

$30 = (ngx_module_t *) 0x68e140<ngx_http_scgi_module>

(gdb) p ngx_modules[27]

$31 = (ngx_module_t *) 0x68e340<ngx_http_memcached_module>

(gdb) p ngx_modules[28]

$32 = (ngx_module_t *) 0x68e720<ngx_http_empty_gif_module>

(gdb) p ngx_modules[29]

$33 = (ngx_module_t *) 0x68ea60<ngx_http_browser_module>

(gdb) p ngx_modules[30]

$34 = (ngx_module_t *) 0x68eca0<ngx_http_upstream_ip_hash_module>

(gdb) p ngx_modules[31]

$35 = (ngx_module_t *) 0x68ee00<ngx_http_upstream_least_conn_module>

(gdb) p ngx_modules[32]

$36 = (ngx_module_t *) 0x68efa0<ngx_http_upstream_keepalive_module>

(gdb) p ngx_modules[33]

$37 = (ngx_module_t *) 0x6858c0<ngx_http_write_filter_module>

(gdb) p ngx_modules[34]

$38 = (ngx_module_t *) 0x6857a0<ngx_http_header_filter_module>

(gdb) p ngx_modules[35]

$39 = (ngx_module_t *) 0x687a60<ngx_http_chunked_filter_module>

(gdb) p ngx_modules[36]

$40 = (ngx_module_t *) 0x687ca0<ngx_http_range_header_filter_module>

(gdb) p ngx_modules[37]

$41 = (ngx_module_t *) 0x6881e0<ngx_http_gzip_filter_module>

(gdb) p ngx_modules[50]

$42 = (ngx_module_t *) 0x326747a8a0<malloc>

(gdb) p ngx_modules[40]

$43 = (ngx_module_t *) 0x688ea0<ngx_http_charset_filter_module>

(gdb) p ngx_modules[45]

$44 = (ngx_module_t *) 0x688020<ngx_http_not_modified_filter_module>

(gdb) p ngx_modules[48]

$45 = (ngx_module_t *) 0x7fffffffe4f8

(gdb) p ngx_modules[47]

$46 = (ngx_module_t *) 0x0

 

这么多模块是怎么初始化的?

是在make命令自动生成的文件ngx_modules.c中

ngx_module_t *ngx_modules[] = {

    &ngx_core_module,

    &ngx_errlog_module,

    &ngx_conf_module,

    &ngx_events_module,

    &ngx_event_core_module,

    &ngx_epoll_module,

    &ngx_regex_module,

    &ngx_http_module,

    &ngx_http_core_module,

    &ngx_http_log_module,

    &ngx_http_upstream_module,

    &ngx_http_static_module,

    &ngx_http_autoindex_module,

    &ngx_http_index_module,

    &ngx_http_auth_basic_module,

    &ngx_http_access_module,

    &ngx_http_limit_conn_module,

    &ngx_http_limit_req_module,

    &ngx_http_geo_module,

    &ngx_http_map_module,

    &ngx_http_split_clients_module,

    &ngx_http_referer_module,

    &ngx_http_rewrite_module,

    &ngx_http_proxy_module,

    &ngx_http_fastcgi_module,

    &ngx_http_uwsgi_module,

    &ngx_http_scgi_module,

    &ngx_http_memcached_module,

    &ngx_http_empty_gif_module,

    &ngx_http_browser_module,

    &ngx_http_upstream_ip_hash_module,

    &ngx_http_upstream_least_conn_module,

    &ngx_http_upstream_keepalive_module,

    &ngx_http_write_filter_module,

    &ngx_http_header_filter_module,

    &ngx_http_chunked_filter_module,

    &ngx_http_range_header_filter_module,

    &ngx_http_gzip_filter_module,

    &ngx_http_postpone_filter_module,

    &ngx_http_ssi_filter_module,

    &ngx_http_charset_filter_module,

    &ngx_http_userid_filter_module,

    &ngx_http_headers_filter_module,

    &ngx_http_copy_filter_module,

    &ngx_http_range_body_filter_module,

    &ngx_http_not_modified_filter_module,

    NULL

};

 

nginx模块化

ngx_listening_s相当于pbrpc中的acceptor,用于监听网络连接请求,创建新的连接。

 

配置模块相当于配置文件解析模块,在pbrpc中,配置文件直接使用proto定义的。配置模块的解析函数:ngx_conf_parse,其中会依据配置的命令,调用相应cmd中的handler函数。

 

模块的定义如下:

struct ngx_module_s {

    ngx_uint_t            ctx_index;

    ngx_uint_t            index;

 

    ngx_uint_t            spare0;

    ngx_uint_t            spare1;

    ngx_uint_t            spare2;

    ngx_uint_t            spare3;

 

    ngx_uint_t            version;

 

    void                 *ctx;

    ngx_command_t        *commands;

    ngx_uint_t            type;

 

    ngx_int_t           (*init_master)(ngx_log_t *log);

 

    ngx_int_t           (*init_module)(ngx_cycle_t *cycle);

 

    ngx_int_t           (*init_process)(ngx_cycle_t *cycle);

    ngx_int_t           (*init_thread)(ngx_cycle_t *cycle);

    void                (*exit_thread)(ngx_cycle_t *cycle);

    void                (*exit_process)(ngx_cycle_t *cycle);

 

    void                (*exit_master)(ngx_cycle_t *cycle);

 

    uintptr_t             spare_hook0;

    uintptr_t             spare_hook1;

    uintptr_t             spare_hook2;

    uintptr_t             spare_hook3;

    uintptr_t             spare_hook4;

    uintptr_t             spare_hook5;

    uintptr_t             spare_hook6;

    uintptr_t             spare_hook7;

};

 

 

 

在ngx_spawn_process

中使用了folk的系统调用,子进程返回后调用了ngx_worker_process_cycle。

ngx_process_events_and_timers是事件处理函数。

 

struct ngx_listening_s {

    ngx_socket_t        fd;

 

    struct sockaddr    *sockaddr;

    socklen_t           socklen;    /* size of sockaddr */

    size_t              addr_text_max_len;

    ngx_str_t           addr_text;

 

    int                 type;

 

    int                 backlog;

    int                 rcvbuf;

    int                 sndbuf;

#if (NGX_HAVE_KEEPALIVE_TUNABLE)

    int                 keepidle;

    int                 keepintvl;

    int                 keepcnt;

#endif

 

    /* handler of accepted connection */

    ngx_connection_handler_pt   handler;

 

    void               *servers;  /* array of ngx_http_in_addr_t, for example */

 

    ngx_log_t           log;

    ngx_log_t          *logp;

 

    size_t              pool_size;

    /* should be here because of the AcceptEx() preread */

    size_t              post_accept_buffer_size;

    /* should be here because of the deferred accept */

    ngx_msec_t          post_accept_timeout;

 

    ngx_listening_t    *previous;

    ngx_connection_t   *connection;

 

    unsigned            open:1;

    unsigned            remain:1;

    unsigned            ignore:1;

 

    unsigned            bound:1;       /* already bound */

    unsigned            inherited:1;   /* inherited from previous process */

    unsigned            nonblocking_accept:1;

    unsigned            listen:1;

    unsigned            nonblocking:1;

    unsigned            shared:1;    /* shared between threads or processes */

    unsigned            addr_ntop:1;

 

#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)

    unsigned            ipv6only:1;

#endif

    unsigned            keepalive:2;

 

#if (NGX_HAVE_DEFERRED_ACCEPT)

    unsigned            deferred_accept:1;

    unsigned            delete_deferred:1;

    unsigned            add_deferred:1;

#ifdef SO_ACCEPTFILTER

    char               *accept_filter;

#endif

#endif

#if (NGX_HAVE_SETFIB)

    int                 setfib;

#endif

 

#if (NGX_HAVE_TCP_FASTOPEN)

    int                 fastopen;

#endif

 

};

 

 

为什么需要性能链表?多个监听端口

Ngx_connection_s相当于Tcp_connection

 

struct ngx_connection_s {

    void               *data;

    ngx_event_t        *read;

    ngx_event_t        *write;

 

    ngx_socket_t        fd;

 

    ngx_recv_pt         recv;

    ngx_send_pt         send;

    ngx_recv_chain_pt   recv_chain;

    ngx_send_chain_pt   send_chain;

 

    ngx_listening_t    *listening;

 

    off_t               sent;

 

    ngx_log_t          *log;

 

    ngx_pool_t         *pool;

 

    struct sockaddr    *sockaddr;

    socklen_t           socklen;

    ngx_str_t           addr_text;

 

    ngx_str_t           proxy_protocol_addr;

 

#if (NGX_SSL)

    ngx_ssl_connection_t  *ssl;

#endif

 

    struct sockaddr    *local_sockaddr;

    socklen_t           local_socklen;

 

    ngx_buf_t          *buffer;

 

    ngx_queue_t         queue;

 

    ngx_atomic_uint_t   number;

 

    ngx_uint_t          requests;

 

    unsigned            buffered:8;

 

    unsigned            log_error:3;     /* ngx_connection_log_error_e */

 

    unsigned            unexpected_eof:1;

    unsigned            timedout:1;

    unsigned            error:1;

    unsigned            destroyed:1;

 

    unsigned            idle:1;

    unsigned            reusable:1;

    unsigned            close:1;

 

    unsigned            sendfile:1;

    unsigned            sndlowat:1;

    unsigned            tcp_nodelay:2;   /* ngx_connection_tcp_nodelay_e */

    unsigned            tcp_nopush:2;    /* ngx_connection_tcp_nopush_e */

 

    unsigned            need_last_buf:1;

 

#if (NGX_HAVE_IOCP)

    unsigned            accept_context_updated:1;

#endif

 

#if (NGX_HAVE_AIO_SENDFILE)

    unsigned            aio_sendfile:1;

    unsigned            busy_count:2;

    ngx_buf_t          *busy_sendfile;

#endif

 

#if (NGX_THREADS)

    ngx_atomic_t        lock;

#endif

};

 

 

参考:
http://blog.csdn.net/livelylittlefish/article/details/6571497
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: