设为首页 收藏本站
查看: 1133|回复: 0

[经验分享] nginx 请求server与location配置定位

[复制链接]

尚未签到

发表于 2016-12-27 06:06:28 | 显示全部楼层 |阅读模式
首先先看一个图:


DSC0000.gif



DSC0001.gif






上图是nginx listen端口配置形成一个结构图,有几点需要提醒一下:



1. 每个端口会有一个ngx_http_port_t结构,相同端口配置会ngx_http_conf_addr_t结构存放到addrs变量中。



2. 并不是所有相同端口都要创建ngx_http_conf_addr_t,当出现listen addr:port配置时,如果addr跟之前

同一port配置也相同时,则不创建该结构,只是将该port所在的server conf,即cscf放到ngx_http_conf_addr_t结构的servers

数组中。若addr部分不同,也会创建一个新的ngx_http_conf_addr_t。



在所有解析完配置后,ngx_http_optimize_servers会做一些整理优化工作,最重要的是为后面开启端口监听做准备。



对于每个port,会调用ngx_http_init_listening:



static ngx_int_t
ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_port_t *port)
{
ngx_uint_t                 i, last, bind_wildcard;
ngx_listening_t           *ls;
ngx_http_port_t           *hport;
ngx_http_conf_addr_t      *addr;
addr = port->addrs.elts;
last = port->addrs.nelts;
// 同一个端口的配置,即 ngx_http_conf_addr_t会有作排序操作,下面的注释做了介绍   
// listen的配置还有不少细节,可以参考官方wiki: http:nginx.org/HttpCoreModule#listen
/*
* If there is a binding to an "*:port" then we need to bind() to
* the "*:port" only and ignore other implicit bindings.  The bindings
* have been already sorted: explicit bindings are on the start, then
* implicit bindings go, and wildcard binding is in the end.
*/   
// 查看该端口的配置里面有个出现通配情况的
if (addr[last - 1].opt.wildcard) {        
// 只把最后一个通配的设置为bind,这样前面的通配不具有bind标记      
// 对于bind的标记,典型的情况(已排序好的)是 :binded,nobind,wildcard(nobind),wildcard(binded)      
addr[last - 1].opt.bind = 1;
bind_wildcard = 1;
} else {
bind_wildcard = 0;
}
i = 0;
while (i < last) {
// 除了有通配的配置之外,还存在明确指出需要bind的配置,需要处理该配置     
// 什么情况下是明确指出要bind的,可参考函数ngx_http_core_listen
if (bind_wildcard && !addr.opt.bind) {
i++;
continue;
}
// 需要监听的port,分配一个ngx_listening_t结构
ls = ngx_http_add_listening(cf, &addr);
if (ls == NULL) {
return NGX_ERROR;
}
hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t));
if (hport == NULL) {
return NGX_ERROR;
}
ls->servers = hport;
if (i == last - 1) {            
// 到这里,就到了处理该结束的时候了,当last > 1意味着配置中存在nobind和         
//  wildcard的类型,即此时该端口被看做对应多个地址,对于这中情况的处理可以参考ngx_http_init_request           
hport->naddrs = last;
} else {           
// 当前port为明确需要bind的,naddrs为1的含义是该port被明确bind到某个地址
hport->naddrs = 1;           
// 下面addr++,从下一面port继续处理,即相对与addr来说,数组下边自然是从0开始啦
i = 0;
}
switch (ls->sockaddr->sa_family) {
default: /* AF_INET */
if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) {
return NGX_ERROR;
}
break;
}
// 一旦某个标记为bind的端口处理完,addr就从下一个开始
addr++;      
// 从下一个addr开始到结束的port个数
last--;
}
return NGX_OK;
}





然后我们看ngx_http_init_request函数:

if (port->naddrs > 1) {
// naddrs > 1的情况前面已经分析过了,最终要使用哪个地址,就通过ngx_connection_local_sockaddr
// 来处理了。
/*
* there are several addresses on this port and one of them
* is an "*:port" wildcard so getsockname() in ngx_http_server_addr()
* is required to determine a server address
*/
// 通过这个函数,实质上就是调用了getsockname,获得该连接的服务器端ip
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;
addr = port->addrs;
/* the last address is "*" */
// 如果与该port上其他非binded的某个配置,具有相同的ip,就是用它的配置,否则就用最后这个的配置
for (i = 0; i < port->naddrs - 1; i++) {
if (addr.addr == sin->sin_addr.s_addr) {
break;
}
}
addr_conf = &addr.conf;
break;
}
} else {
// naddrs == 1
switch (c->local_sockaddr->sa_family) {
default: /* AF_INET */
addr = port->addrs;
addr_conf = &addr[0].conf;
break;
}
}
// 上面的操作最主要的作用就是拿到cscf,即核心的server conf,ngx_http_core_srv_conf_t结构。
// 关于default_server,在ngx_http_add_address处理,第一次添加的port会设置default_server
// 为该port的当前cscf,同时在ngx_http_add_addresses中会针对相同addr:port的,修改一下
// default_server的指向,具体可以参考该函数。
cscf = addr_conf->default_server;
// 得到了cscf,剩下的就好说了。这样发往该端口的请求,它的相关配置就得到了,
r->main_conf = cscf->ctx->main_conf;
r->srv_conf = cscf->ctx->srv_conf;
r->loc_conf = cscf->ctx->loc_conf;






















在处理请求时,相关模块的配置通常通过一些宏来获得:
#define ngx_http_get_module_main_conf(r, module)    (r)->main_conf[module.ctx_index]
#define ngx_http_get_module_srv_conf(r, module)     (r)->srv_conf[module.ctx_index]
#define ngx_http_get_module_loc_conf(r, module)      (r)->loc_conf[module.ctx_index]



需要注意的是,这里获得配置都是http core的,特别是对于location的配置,不同的模块可能有自己的需求,所以才有了http处理阶段中NGX_HTTP_FIND_CONFIG_PHASE的出现,这个阶段的主要作用就是为了根据具体的url,在核心location配置中的static_locations及regex_locations来查找相应location的配置。具体地,可以参考ngx_http_core_find_location。在看这个之前,需要的了解的是nginx
location三叉树的结构。普通的location,一般指非正则的,都是放在static_locations管理的三叉树里,正则的配置则放到regex_locations链表里。明确了这些概念之后,函数的逻辑就很简单了。





















<!--192.168.1.236-->

上一篇:nginx http处理过程分析之细节


下一篇:nginx keepalive连接回收机制

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.iyunv.com/thread-319768-1-1.html 上篇帖子: 答复: [译]Nginx & Comet:低延迟信息推送 | [译]Nginx & Comet:低延迟信息推送 下篇帖子: nginx模块开发入门(九) -4 Filters
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表