[nginx源码分析]server_name hash

server中的server_name形成hash,优化server_name查找

核心函数ngx_http_optimize_servers(ngx_conf_t*cf, ngx_http_core_main_conf_t* cmcf)

因为listen端口数据结构是[port,addr]二维数组,所以二层遍历,每一个port,每一个addr是该函数的主流程。

遍历addr是相同port下的addr,调用函数ngx_http_server_names

ngx_http_server_names(cf,cmcf, &addr[a])

函数首先ngx_hash_keys_array_init(&ha,NGX_HASH_LARGE)

这个函数是创建

typedef struct {
     ngx_uint_t        hsize;
 
     ngx_pool_t       *pool;
     ngx_pool_t       *temp_pool;   
     ngx_array_t       keys;//保存hash信息,value是该server_name的server上下文
     ngx_array_t      *keys_hash;   		//保存server_name

     ngx_array_t       dns_wc_head;//hash信息 
     ngx_array_t      *dns_wc_head_hash;//保存server_name

     ngx_array_t       dns_wc_tail; //hash信息
     ngx_array_t      *dns_wc_tail_hash;//保存server_name
} ngx_hash_keys_arrays_t;  

ngx_http_server_names函数首先构建server_name数组(数组类型为ngx_hash_key_t),包括绝对server_name和正则server_name,其中server正则可以是如下几种:

1.example.com

2*.example.com

3 www.example.*

构建server_name的hash信息,根据server_name类别分别保存到keys(绝对匹配)、dns_wc_head(1和2这两种类型) 、和dns_wc_tail(第三种类型),函数后面根据生成的这三个数组分表把这些信息保存

keys			  <=====>		addr->hash
dns_wc_head		<=====>		addr->wc_head
dns_wc_tail		<=====>		addr->wc_tail

回到函数ngx_http_optimize_servers

每一个端口都会盗用ngx_http_init_listening

函数ngx_http_init_listening遍历port下面的每一个addr,

调用ngx_http_add_listening(cf,&addr[i])首先创建和追加一个ngx_listening_t到cf->cycle->listening中去,也就是说cf->cycle->listening保存着该地址信息

ls->addr_ntop-1

ls->handler= ngx_http_init_connection//这里设置listening的回调函数

整个函数就是把addr里面的值保存到ngx_listening_t下面去。

ls->server= hport

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 (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;//指向虚拟name

         vn->names.hash = addr[i].hash;//addr的exact地址
         vn->names.wc_head = addr[i].wc_head;//正则head地址
         vn->names.wc_tail = addr[i].wc_tail;//正则tail地址
#if (NGX_PCRE)                                                                                                                                                                                                                         
         vn->nregex = addr[i].nregex;
         vn->regex = addr[i].regex;
#endif
     }

     return NGX_OK;

整个cycle->listening结构如下

ngx_init_cycle->ngx_open_listening_sockets

函数主要是遍历cycle->listenning的每一个需要监听的sock,调用socket api来完成sock初始化

1 socket

2 bind

3 listen

4 accept

然后就开始分析main主流程了





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值