nginx 请求server与location配置定位
来源:互联网 发布:淘宝旺旺号怎么注册 编辑:程序博客网 时间:2024/06/06 18:24
首先先看一个图:
上图是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_tngx_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[i].opt.bind) { i++; continue; } // 需要监听的port,分配一个ngx_listening_t结构 ls = ngx_http_add_listening(cf, &addr[i]); 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[i].addr == sin->sin_addr.s_addr) { break; } } addr_conf = &addr[i].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]
#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链表里。明确了这些概念之后,函数的逻辑就很简单了。
- nginx 请求server与location配置定位
- nginx location 定位
- [nginx] location定位
- Nginx Location 语法,与简单配置
- nginx配置心得 location 与alias
- Nginx Location 语法,与简单配置
- Nginx Location 语法,与简单配置
- Nginx Location 语法,与简单配置
- Nginx Location 语法,与简单配置
- Nginx Location 语法,与简单配置
- Nginx Location 语法,与简单配置
- Nginx location 配置
- Nginx Location配置总结
- Nginx的location配置
- Nginx Location配置总结
- nginx location 配置选项
- Nginx Location配置总结
- Nginx Location配置总结
- SUID、SGID、STICKY简介
- 理解cookie和session机制
- 深入研究java.lang.ThreadLocal类
- access函数使用
- shell 编程之2>&1含义
- nginx 请求server与location配置定位
- 字与字节的区别
- ffmpeg编译时保留调试信息
- nohup命令
- onStartCommand方法返回的数值问题
- 如何计算地址线和数据线
- ARG_MAX
- POJ 3158 Kickdown(我的水题之路——齿轮盒子,读题失败)
- 第七节 存储过程 (含函数)
原创粉丝点击
热门IT博客
热门问题
老师的惩罚
人脸识别
我在镇武司摸鱼那些年
重生之率土为王
我在大康的咸鱼生活
盘龙之生命进化
天生仙种
凡人之先天五行
春回大明朝
姑娘不必设防,我是瞎子
正庚烷
庚辰
庚辰本
庚金
庚金女
开封府
王府美人
木府风云
帅府悍妇惹不起
我手机通冥府
总兵府旅游
总兵府
府兵
执掌地府百万兵
北府兵
腾冲和顺总兵府客栈
闻喜县王府宾馆
日本猪瘟疫情扩散到8府县
永年广府城
府城
王府城
海口府城
武鸣府城11山歌对唱
张家界大庸府城附近酒店
永年广府城门票多少钱
海口府城医院
府天作品
天波杨府
天波杨府旅游
府天
蒙自阳光天悦府
开封天波杨府
河南天波杨府
天津天房璟悦府
公子千秋 府天
千钧 府天
滨州天场瑞府
融创天朗珑府
承恩侯府 三十一天冬至
北京府学宾馆
府学小学学区房