nginx stream udp

配置见github

upstream

upstream -> ngx_stream_upstream
server -> ngx_stream_upstream_server
    us = ngx_array_push(uscf->servers); ---> 上游信息写入到配置信息里

phases

nginx 配置块

typedef struct {
    ngx_stream_phase_engine_t      phase_engine; --->
    ngx_stream_phase_t             phases[NGX_STREAM_LOG_PHASE + 1]; --->
} ngx_stream_core_main_conf_t;
engine: --> phase_handler ---> checker
                                 |
                               handler
                                 |
                                next
typedef struct {
    ngx_stream_phase_handler_t    *handlers; --->array
} ngx_stream_phase_engine_t;
struct ngx_stream_phase_handler_s {
    ngx_stream_phase_handler_pt    checker;
    ngx_stream_handler_pt          handler;
    ngx_uint_t                     next;
};

phases:

typedef struct {
    ngx_array_t                    handlers; (ngx_stream_phase_handler_t)
} ngx_stream_phase_t;

session:

struct ngx_stream_session_s {
    ngx_int_t                      phase_handler;  --> pos int of phase_handler
};
    ph = cmcf->phase_engine.handlers; ---> *phase handler

    while (ph[s->phase_handler].checker) {

        rc = ph[s->phase_handler].checker(s, &ph[s->phase_handler]); --->执行checker

        if (rc == NGX_OK) {
            return;
        }
    }

typedef enum {
    NGX_STREAM_POST_ACCEPT_PHASE = 0,
    NGX_STREAM_PREACCESS_PHASE,
    NGX_STREAM_ACCESS_PHASE,
    NGX_STREAM_SSL_PHASE,
    NGX_STREAM_PREREAD_PHASE,
    NGX_STREAM_CONTENT_PHASE,
    NGX_STREAM_LOG_PHASE
} ngx_stream_phases;

conf 初始化

static ngx_command_t  ngx_stream_commands[] = {

    { ngx_string("stream"),
      NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
      ngx_stream_block,
      0,
      0,
      NULL },

      ngx_null_command
};
ngx_stream_block
    ngx_stream_init_phase_handlers
        checker = ngx_stream_core_generic_phase; -->
        ph->checker = ngx_stream_core_content_phase; -->
    ngx_stream_optimize_servers
        ls->handler = ngx_stream_init_connection; ---> 当listen成功时调用

ngx_stream_init_phase_handlers:

    cmcf->phase_engine.handlers = ph;
    n = 0;

    for (i = 0; i < NGX_STREAM_LOG_PHASE; i++) {
        h = cmcf->phases[i].handlers.elts; --> 去除配置时的临时信息

        switch (i) {
            ----- 这俩个阶段是不能配置的,走默认的checker
        case NGX_STREAM_PREREAD_PHASE:
            checker = ngx_stream_core_preread_phase;
            break; --->跳出switch,preread的checker固定的

            ----- 这俩个阶段是不能配置的,走默认的checker
        case NGX_STREAM_CONTENT_PHASE:
            ph->checker = ngx_stream_core_content_phase;
            n++;
            ph++; ---->挂载checker, 没修改next 并形成指针数组

            continue; -->下一个阶段 content处理完

        default:
            checker = ngx_stream_core_generic_phase;
        }

        n += cmcf->phases[i].handlers.nelts;

        for (j = cmcf->phases[i].handlers.nelts - 1; j >= 0; j--) {
            ph->checker = checker;
            ph->handler = h[j];
            ph->next = n; ---> n指向下一个phrase,非常精彩的设计,看半天才看懂
            ph++;
        }
    }
static ngx_command_t  ngx_stream_proxy_commands[] = {

    { ngx_string("proxy_pass"),
      NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
      ngx_stream_proxy_pass,
      NGX_STREAM_SRV_CONF_OFFSET,
      0,
      NULL }, -->
ngx_stream_proxy_pass
    cscf->handler = ngx_stream_proxy_handler; --> content阶段会调用

t

typedef struct {
    ngx_stream_content_handler_pt  handler;
} ngx_stream_core_srv_conf_t;

配置时phases 数组怎么生成的?

listen成功时

ngx_event_recvmsg 生成connection connection用于listen
    ls->handler(c); ---> ngx_stream_init_connection
ngx_stream_init_connection 生成session session用于表示一个会话
    rev->handler = ngx_stream_session_handler; -->
ngx_stream_session_handler
    ngx_stream_core_run_phases
        rc = ph[s->phase_handler].checker(s, &ph[s->phase_handler]);
            ngx_stream_core_generic_phase * 2
                rc = ph->handler(s); 
            ngx_stream_core_content_phase
                cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module);
                cscf->handler(s);--> content会调用ngx_stream_proxy_handler

为什么从 0 , 1 , 直接跳到了content?

phase是按照顺序来的,串行

0: ngx_stream_limit_conn_handler –> declined 1: ngx_stream_access_handler –> declined

core_generic_phase:

    rc = ph->handler(s);

    if (rc == NGX_OK) {
        s->phase_handler = ph->next;  ----> session的phase 会被ph->next赋值 到下一个session
        return NGX_AGAIN;
    }

    if (rc == NGX_DECLINED) {
        s->phase_handler++; --> 处理这个阶段的下一个phrase
        return NGX_AGAIN;
    }

    if (rc == NGX_AGAIN || rc == NGX_DONE) {
        return NGX_OK; -------> 下次请求还是再这个阶段
    }

    if (rc == NGX_ERROR) {
        rc = NGX_STREAM_INTERNAL_SERVER_ERROR;
    }

ngx_stream_proxy_handler

    ngx_stream_upstream_create_round_robin_peer 
        s->upstream->peer.get = ngx_stream_upstream_get_round_robin_peer;
    c->write->handler = ngx_stream_proxy_downstream_handler;
    c->read->handler = ngx_stream_proxy_downstream_handler;
    ngx_stream_proxy_connect

bt rr peer:

#0  ngx_stream_upstream_get_round_robin_peer (pc=0xd62b40, data=0xd62cf0)
    at src/stream/ngx_stream_upstream_round_robin.c:429
#1  0x00000000004449d9 in ngx_event_connect_peer (pc=0xd62b40) at src/event/ngx_event_connect.c:34
#2  0x00000000004e0fa7 in ngx_stream_proxy_connect (s=0xd62990) at src/stream/ngx_stream_proxy_module.c:685
#3  0x00000000004e0a76 in ngx_stream_proxy_handler (s=0xd62990) at src/stream/ngx_stream_proxy_module.c:544
#4  0x00000000004db77c in ngx_stream_core_content_phase (s=0xd62990, ph=0xd6a380)
    at src/stream/ngx_stream_core_module.c:329
#5  0x00000000004db27d in ngx_stream_core_run_phases (s=0xd62990) at src/stream/ngx_stream_core_module.c:153
#6  0x00000000004dac9f in ngx_stream_session_handler (rev=0xd6d4f0) at src/stream/ngx_stream_handler.c:292
#7  0x00000000004da9a1 in ngx_stream_init_connection (c=0x7f3e8e997390) at src/stream/ngx_stream_handler.c:201
#8  0x00000000004443e2 in ngx_event_recvmsg (ev=0xd6d370) at src/event/ngx_event_accept.c:634
#9  0x0000000000451b67 in ngx_epoll_process_events (cycle=0xd5cf30, timer=6096, flags=1)
    at src/event/modules/ngx_epoll_module.c:902
#10 0x0000000000440819 in ngx_process_events_and_timers (cycle=0xd5cf30) at src/event/ngx_event.c:242
#11 0x000000000044f241 in ngx_worker_process_cycle (cycle=0xd5cf30, data=0x0) at src/os/unix/ngx_process_cycle.c:750
#12 0x000000000044ba4b in ngx_spawn_process (cycle=0xd5cf30, proc=0x44f15a <ngx_worker_process_cycle>, data=0x0,
    name=0x4f6373 "worker process", respawn=-3) at src/os/unix/ngx_process.c:199
#13 0x000000000044e08b in ngx_start_worker_processes (cycle=0xd5cf30, n=1, type=-3)
    at src/os/unix/ngx_process_cycle.c:359
#14 0x000000000044d6a8 in ngx_master_process_cycle (cycle=0xd5cf30) at src/os/unix/ngx_process_cycle.c:131
#15 0x000000000040c68d in main (argc=1, argv=0x7fffac4158b8) at src/core/nginx.c:382

bt:


#0  ngx_stream_core_generic_phase (s=0xdc5480, ph=0xdd52c0) at src/stream/ngx_stream_core_module.c:173
#1  0x00000000004db27d in ngx_stream_core_run_phases (s=0xdc5480) at src/stream/ngx_stream_core_module.c:153
#2  0x00000000004dac9f in ngx_stream_session_handler (rev=0xdd83a0) at src/stream/ngx_stream_handler.c:292
#3  0x00000000004da9a1 in ngx_stream_init_connection (c=0x7ff22b7301d0) at src/stream/ngx_stream_handler.c:201
#4  0x00000000004443e2 in ngx_event_recvmsg (ev=0xdd82e0) at src/event/ngx_event_accept.c:634
#5  0x0000000000451b67 in ngx_epoll_process_events (cycle=0xdc7ea0, timer=18446744073709551615, flags=1)
    at src/event/modules/ngx_epoll_module.c:902
#6  0x0000000000440819 in ngx_process_events_and_timers (cycle=0xdc7ea0) at src/event/ngx_event.c:242
#7  0x000000000044f241 in ngx_worker_process_cycle (cycle=0xdc7ea0, data=0x0) at src/os/unix/ngx_process_cycle.c:750
#8  0x000000000044ba4b in ngx_spawn_process (cycle=0xdc7ea0, proc=0x44f15a <ngx_worker_process_cycle>, data=0x0,
    name=0x4f6373 "worker process", respawn=-3) at src/os/unix/ngx_process.c:199
#9  0x000000000044e08b in ngx_start_worker_processes (cycle=0xdc7ea0, n=1, type=-3)
    at src/os/unix/ngx_process_cycle.c:359
#10 0x000000000044d6a8 in ngx_master_process_cycle (cycle=0xdc7ea0) at src/os/unix/ngx_process_cycle.c:131
#11 0x000000000040c68d in main (argc=1, argv=0x7fff5d43ea28) at src/core/nginx.c:382
ngx_stream_proxy_pass
    cscf->handler = ngx_stream_proxy_handler; -->
ngx_stream_proxy_handler
    ngx_stream_proxy_connect
        ngx_stream_proxy_init_upstream
            ngx_stream_proxy_process
                rc = ngx_stream_top_filter(s, *out, from_upstream); --> ngx_stream_write_filter 
                if (!c->read->delayed && !pc->read->delayed) {
                    ngx_add_timer(c->write, pscf->timeout);
ngx_stream_write_filter
    chain = c->send_chain(c, *out, 0); ---> ngx_udp_unix_sendmsg_chain
ngx_udp_unix_sendmsg_chain
    ngx_sendmsg

write_filter


static ngx_stream_module_t  ngx_stream_write_filter_module_ctx = {
    NULL,                                  /* preconfiguration */
    ngx_stream_write_filter_init,          /* postconfiguration */

    NULL,                                  /* create main configuration */
    NULL,                                  /* init main configuration */

    NULL,                                  /* create server configuration */
    NULL                                   /* merge server configuration */
};
static ngx_int_t
ngx_stream_write_filter_init(ngx_conf_t *cf)
{
    ngx_stream_top_filter = ngx_stream_write_filter;

    return NGX_OK;
}

timer作用?

log

2018/03/22 15:11:42 [debug] 23661#0: epoll: fd:5 ev:0001 d:00007FE8B7ACA010 2018/03/22 15:11:42 [debug] 23661#0: recvmsg on 0.0.0.0:9000, ready: 0
2018/03/22 15:11:42 [debug] 23661#0: posix_memalign: 0000000001B20210:256 @16
2018/03/22 15:11:42 [debug] 23661#0: posix_memalign: 0000000001B20410:256 @16
2018/03/22 15:11:42 [debug] 23661#0: *73 recvmsg: 127.0.0.1:36477 fd:5 n:10
2018/03/22 15:11:42 [info] 23661#0: *73 udp client 127.0.0.1:36477 connected to 0.0.0.0:9000
2018/03/22 15:11:42 [debug] 23661#0: *73 posix_memalign: 0000000001B20520:256 @16
2018/03/22 15:11:42 [debug] 23661#0: *73 generic phase: 0 ----->
2018/03/22 15:11:42 [debug] 23661#0: *73 generic phase: 1 ----->
2018/03/22 15:11:42 [debug] 23661#0: *73 proxy connection handler --->content
2018/03/22 15:11:42 [debug] 23661#0: *73 malloc: 0000000001B20630:384
2018/03/22 15:11:42 [debug] 23661#0: *73 posix_memalign: 0000000001B28670:256 @16
2018/03/22 15:11:42 [debug] 23661#0: *73 get rr peer, try: 1
2018/03/22 15:11:42 [debug] 23661#0: *73 dgram socket 3
2018/03/22 15:11:42 [debug] 23661#0: *73 epoll add connection: fd:3 ev:80002005
2018/03/22 15:11:42 [debug] 23661#0: *73 connect to 0.0.0.0:9002, fd:3 #74
2018/03/22 15:11:42 [debug] 23661#0: *73 connected
2018/03/22 15:11:42 [debug] 23661#0: *73 proxy connect: 0 -----> ngx_stream_proxy_connect
2018/03/22 15:11:42 [info] 23661#0: *73 udp proxy 127.0.0.1:51843 connected to 0.0.0.0:9002 -->ngx_stream_proxy_init_upstream
2018/03/22 15:11:42 [debug] 23661#0: *73 malloc: 0000000001B63300:16384 -->ngx_alloc
2018/03/22 15:11:42 [debug] 23661#0: *73 stream proxy add preread buffer: 10
2018/03/22 15:11:42 [debug] 23661#0: *73 write new buf t:1 f:0 0000000001B202D0, pos 0000000001B202D0, size: 10 file: 0, size: 0 -->write_filter
2018/03/22 15:11:42 [debug] 23661#0: *73 stream write filter: l:1 f:1 s:10
2018/03/22 15:11:42 [debug] 23661#0: *73 sendmsg: 10 of 10 --->ngx_sendmsg
2018/03/22 15:11:42 [debug] 23661#0: *73 stream write filter 0000000000000000 --->write_filter
2018/03/22 15:11:42 [debug] 23661#0: *73 event timer add: 5: 20000:1521702722071 -->add_timer
2018/03/22 15:11:42 [debug] 23661#0: timer delta: 289305
2018/03/22 15:11:42 [debug] 23661#0: worker cycle
2018/03/22 15:11:42 [debug] 23661#0: epoll timer: 20000
2018/03/22 15:11:42 [debug] 23661#0: epoll: fd:3 ev:0004 d:00007FE8B7ACA9B1
2018/03/22 15:11:42 [debug] 23661#0: *73 event timer: 5, old: 1521702722071, new: 1521702722072
2018/03/22 15:11:42 [debug] 23661#0: timer delta: 1
2018/03/22 15:11:42 [debug] 23661#0: worker cycle
2018/03/22 15:11:42 [debug] 23661#0: epoll timer: 19999

godep 迁移到dep 的坑

godep 做了一个策略,就是如果没用到这个项目的某个文件,这个文件是不加入vendor的。 dep则会添加所有的文件

hugo bug?

用hugo折腾blog有个bug?当date时间在当前时间后,就不显示了。。。