IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    nginx模块开发(43)—网络初始化之listen(下)

    cjhust发表于 2015-01-13 14:32:43
    love 0

    ngx_http_add_listening

    static ngx_listening_t *

    ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr)

    {

    ngx_listening_t *ls;

    ngx_http_core_loc_conf_t *clcf;

    ngx_http_core_srv_conf_t *cscf;

    ls = ngx_create_listening(cf, &addr-;>opt.u.sockaddr, addr->opt.socklen);

    if (ls == NULL) {

    return NULL;

    }

    ls->addr_ntop = 1;

    ls->handler = ngx_http_init_connection;

    cscf = addr->default_server;

    ls->pool_size = cscf->connection_pool_size;

    ls->post_accept_timeout = cscf->client_header_timeout;

    clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index];

    ls->logp = clcf->error_log;

    ls->log.data = &ls-;>addr_text;

    ls->log.handler = ngx_accept_log_error;

    ls->backlog = addr->opt.backlog;

    ls->rcvbuf = addr->opt.rcvbuf;

    ls->sndbuf = addr->opt.sndbuf;

    ls->keepalive = addr->opt.so_keepalive;

    return ls;

    }

    ngx_create_listening

    ngx_listening_t *

    ngx_create_listening(ngx_conf_t *cf, void *sockaddr, socklen_t socklen)

    {

    size_t len;

    ngx_listening_t *ls;

    struct sockaddr *sa;

    u_char text[NGX_SOCKADDR_STRLEN];

    ls = ngx_array_push(&cf-;>cycle->listening);

    if (ls == NULL) {

    return NULL;

    }

    ngx_memzero(ls, sizeof(ngx_listening_t));

    sa = ngx_palloc(cf->pool, socklen);

    if (sa == NULL) {

    return NULL;

    }

    ngx_memcpy(sa, sockaddr, socklen);

    ls->sockaddr = sa;

    ls->socklen = socklen;

    len = ngx_sock_ntop(sa, socklen, text, NGX_SOCKADDR_STRLEN, 1);

    ls->addr_text.len = len;

    switch (ls->sockaddr->sa_family) {

    case AF_INET:

    ls->addr_text_max_len = NGX_INET_ADDRSTRLEN;

    break;

    default:

    ls->addr_text_max_len = NGX_SOCKADDR_STRLEN;

    break;

    }

    ls->addr_text.data = ngx_pnalloc(cf->pool, len);

    if (ls->addr_text.data == NULL) {

    return NULL;

    }

    ngx_memcpy(ls->addr_text.data, text, len);

    ls->fd = (ngx_socket_t) -1;

    ls->type = SOCK_STREAM;

    ls->backlog = NGX_LISTEN_BACKLOG; //511

    ls->rcvbuf = -1;

    ls->sndbuf = -1;

    return ls;

    }

    ngx_http_add_addrs

    static ngx_int_t

    ngx_http_add_addrs(ngx_conf_t *cf, ngx_http_port_t *hport,

    ngx_http_conf_addr_t *addr)

    {

    ngx_uint_t i;

    ngx_http_in_addr_t *addrs;

    struct sockaddr_in *sin;

    ngx_http_virtual_names_t *vn;

    hport->addrs = ngx_pcalloc(cf->pool,

    hport->naddrs * sizeof(ngx_http_in_addr_t));

    if (hport->addrs == NULL) {

    return NGX_ERROR;

    }

    addrs = hport->addrs;

    for (i = 0; i < hport->naddrs; i++) {

    sin = &addr;[i].opt.u.sockaddr_in;

    addrs[i].addr = sin->sin_addr.s_addr;

    addrs[i].conf.default_server = addr[i].default_server;

    #if (NGX_HTTP_SSL)

    addrs[i].conf.ssl = addr[i].opt.ssl;

    #endif

    #if (NGX_HTTP_SPDY)

    addrs[i].conf.spdy = addr[i].opt.spdy;

    #endif

    addrs[i].conf.proxy_protocol = addr[i].opt.proxy_protocol;

    if (addr[i].hash.buckets == NULL

    && (addr[i].wc_head == NULL

    || addr[i].wc_head->hash.buckets == NULL)

    && (addr[i].wc_tail == NULL

    || addr[i].wc_tail->hash.buckets == NULL)

    #if (NGX_PCRE)

    && addr[i].nregex == 0

    #endif

    )

    {

    continue;

    }

    vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));

    if (vn == NULL) {

    return NGX_ERROR;

    }

    addrs[i].conf.virtual_names = vn;

    vn->names.hash = addr[i].hash;

    vn->names.wc_head = addr[i].wc_head;

    vn->names.wc_tail = addr[i].wc_tail;

    #if (NGX_PCRE)

    vn->nregex = addr[i].nregex;

    vn->regex = addr[i].regex;

    #endif

    }

    return NGX_OK;

    }

    ngx_init_cycle

    if (old_cycle->listening.nelts) {

    ls = old_cycle->listening.elts;

    for (i = 0; i < old_cycle->listening.nelts; i++) {

    ls[i].remain = 0;

    }

    nls = cycle->listening.elts;

    for (n = 0; n < cycle->listening.nelts; n++) {

    for (i = 0; i < old_cycle->listening.nelts; i++) {

    if (ls[i].ignore) {

    continue;

    }

    //地址相同

    if (ngx_cmp_sockaddr(nls[n].sockaddr, nls[n].socklen,

    ls[i].sockaddr, ls[i].socklen, 1)

    == NGX_OK)

    {

    nls[n].fd = ls[i].fd;

    nls[n].previous = &ls;[i];

    ls[i].remain = 1; //当remain=1时,old_cycle不需要close fd()

    if (ls[i].backlog != nls[n].backlog) {

    nls[n].listen = 1; //backlog不同的时候,会在configure_listening_sockets中重新listen(fd, backlog)

    }

    break;

    }

    }

    if (nls[n].fd == (ngx_socket_t) -1) {

    nls[n].open = 1;

    }

    }

    } else {

    ls = cycle->listening.elts;

    for (i = 0; i < cycle->listening.nelts; i++) {

    ls[i].open = 1;

    }

    }

    if (ngx_open_listening_sockets(cycle) != NGX_OK) {

    goto failed;

    }

    ….

    ls = old_cycle->listening.elts;

    for (i = 0; i < old_cycle->listening.nelts; i++) {

    if (ls[i].remain || ls[i].fd == (ngx_socket_t) -1) {

    continue;

    }

    if (ngx_close_socket(ls[i].fd) == -1) {

    ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,

    ngx_close_socket_n " listening socket on %V failed",

    &ls;[i].addr_text);

    }

    }

    ngx_open_listening_sockets

    ngx_int_t

    ngx_open_listening_sockets(ngx_cycle_t *cycle)

    {

    int reuseaddr;

    ngx_uint_t i, tries, failed;

    ngx_err_t err;

    ngx_log_t *log;

    ngx_socket_t s;

    ngx_listening_t *ls;

    reuseaddr = 1;

    #if (NGX_SUPPRESS_WARN)

    failed = 0;

    #endif

    log = cycle->log;

    /* TODO: configurable try number */

    for (tries = 5; tries; tries--) {

    failed = 0;

    /* for each listening socket */

    ls = cycle->listening.elts;

    for (i = 0; i < cycle->listening.nelts; i++) {

    if (ls[i].ignore) { //和inherited_sockets有关

    continue;

    }

    if (ls[i].fd != (ngx_socket_t) -1) {

    continue;

    }

    if (ls[i].inherited) {

    continue;

    }

    s = ngx_socket(ls[i].sockaddr->sa_family, ls[i].type, 0);

    if (s == (ngx_socket_t) -1) {

    ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,

    ngx_socket_n " %V failed", &ls;[i].addr_text);

    return NGX_ERROR;

    }

    if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,

    (const void *) &reuseaddr;, sizeof(int))

    == -1)

    {

    ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,

    "setsockopt(SO_REUSEADDR) %V failed",

    &ls;[i].addr_text);

    if (ngx_close_socket(s) == -1) {

    ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,

    ngx_close_socket_n " %V failed",

    &ls;[i].addr_text);

    }

    return NGX_ERROR;

    }

    if (!(ngx_event_flags & NGX_USE_AIO_EVENT)) {

    if (ngx_nonblocking(s) == -1) {

    ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,

    ngx_nonblocking_n " %V failed",

    &ls;[i].addr_text);

    if (ngx_close_socket(s) == -1) {

    ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,

    ngx_close_socket_n " %V failed",

    &ls;[i].addr_text);

    }

    return NGX_ERROR;

    }

    }

    if (bind(s, ls[i].sockaddr, ls[i].socklen) == -1) {

    err = ngx_socket_errno;

    if (err == NGX_EADDRINUSE && ngx_test_config) {

    continue;

    }

    ngx_log_error(NGX_LOG_EMERG, log, err,

    "bind() to %V failed", &ls;[i].addr_text);

    if (ngx_close_socket(s) == -1) {

    ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,

    ngx_close_socket_n " %V failed",

    &ls;[i].addr_text);

    }

    if (err != NGX_EADDRINUSE) {

    return NGX_ERROR;

    }

    failed = 1;

    continue;

    }

    //如listen 80和listen 1.1.1.1:80 共用一个listening,即共用一个backlog

    if (listen(s, ls[i].backlog) == -1) {

    ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,

    "listen() to %V, backlog %d failed",

    &ls;[i].addr_text, ls[i].backlog);

    if (ngx_close_socket(s) == -1) {

    ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,

    ngx_close_socket_n " %V failed",

    &ls;[i].addr_text);

    }

    return NGX_ERROR;

    }

    ls[i].listen = 1;

    ls[i].fd = s;

    }

    if (!failed) {

    break;

    }

    /* TODO: delay configurable */

    ngx_log_error(NGX_LOG_NOTICE, log, 0,

    "try again to bind() after 500ms");

    ngx_msleep(500);

    }

    if (failed) {

    ngx_log_error(NGX_LOG_EMERG, log, 0, "still could not bind()");

    return NGX_ERROR;

    }

    return NGX_OK;

    }

    ngx_configure_listening_sockets

    void

    ngx_configure_listening_sockets(ngx_cycle_t *cycle)

    {

    int value;

    ngx_uint_t i;

    ngx_listening_t *ls;

    ls = cycle->listening.elts;

    for (i = 0; i < cycle->listening.nelts; i++) {

    ls[i].log = *ls[i].logp;

    。。。

    if (ls[i].keepalive) {

    value = (ls[i].keepalive == 1) ? 1 : 0;

    if (setsockopt(ls[i].fd, SOL_SOCKET, SO_KEEPALIVE,

    (const void *) &value;, sizeof(int))

    == -1)

    {

    ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,

    "setsockopt(SO_KEEPALIVE, %d) %V failed, ignored",

    value, &ls;[i].addr_text);

    }

    }

    if (ls[i].listen) {

    /* change backlog via listen() */

    if (listen(ls[i].fd, ls[i].backlog) == -1) {

    ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,

    "listen() to %V, backlog %d failed, ignored",

    &ls;[i].addr_text, ls[i].backlog);

    }

    }

    }

    return;

    }

    ngx_http_init_connection

    函数功能:ngx_event_accept后的ls->handler= ngx_http_init_connection。

    void

    ngx_http_init_connection(ngx_connection_t *c)

    {

    ngx_uint_t i;

    ngx_event_t *rev;

    struct sockaddr_in *sin;

    ngx_http_port_t *port;

    ngx_http_in_addr_t *addr;

    ngx_http_log_ctx_t *ctx;

    ngx_http_connection_t *hc;

    hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t));

    if (hc == NULL) {

    ngx_http_close_connection(c);

    return;

    }

    c->data = hc;

    /* find the server configuration for the address:port */

    port = c->listening->servers; /*ngx_http_port_t */

    if (port->naddrs > 1) {

    if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) {

    ngx_http_close_connection(c);

    return;

    }

    switch (c->local_sockaddr->sa_family) {

    default: /* AF_INET */

    sin = (struct sockaddr_in *) c->local_sockaddr; //here

    addr = port->addrs;

    for (i = 0; i < port->naddrs - 1; i++) {

    if (addr[i].addr == sin->sin_addr.s_addr) {

    break;

    }

    }

    hc->addr_conf = &addr;[i].conf;

    break;

    }

    } else {

    switch (c->local_sockaddr->sa_family) {

    default: /* AF_INET */

    addr = port->addrs;

    hc->addr_conf = &addr;[0].conf;

    break;

    }

    }

    …

    rev = c->read;

    rev->handler = ngx_http_wait_request_handler; //普通request_handler

    c->write->handler = ngx_http_empty_handler;

    #if (NGX_HTTP_SPDY)

    if (hc->addr_conf->spdy) {

    rev->handler = ngx_http_spdy_init; //spdy request_handler

    }

    #endif

    …

    if (rev->ready) {

    /* the deferred accept(), rtsig, aio, iocp */

    if (ngx_use_accept_mutex) {

    ngx_post_event(rev, &ngx;_posted_events);

    return;

    }

    rev->handler(rev);

    return;

    }

    ngx_add_timer(rev, c->listening->post_accept_timeout);

    ngx_reusable_connection(c, 1);

    if (ngx_handle_read_event(rev, 0) != NGX_OK) {

    ngx_http_close_connection(c);

    return;

    }

    }

    4、参考资料

    http://www.cnblogs.com/chengxuyuancc/p/3789216.html

    SLB 7层负载均衡“HUNG”问题追查:

    http://www.cnblogs.com/aliyuncc/p/3863070.html



沪ICP备19023445号-2号
友情链接