`
cloudtech
  • 浏览: 4647819 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

nginx 请求server与location配置定位

 
阅读更多
首先先看一个图:



上图是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[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]

需要注意的是,这里获得配置都是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.237-->
分享到:
评论

相关推荐

    nginx的server和location匹配规则

    Nginx 服务器和 Location 匹配规则 Nginx 配置文件主要由 events、http、server、...Server 块和 Location 块的匹配规则是 Nginx 配置文件中非常重要的一部分,对于虚拟主机和 URL 匹配特定位置的设置起着关键作用。

    ngnix的简单转发请求之server和location配置详解

    简单梳理一下nginx中关于server 和location的配置. 比如URL:www.mask_dev2.com:9999/login/ server管的前半部分,即:www.mask_dev2.com:9999 location管的是后半部分,即:/login/ 一个nginx可以配置多个...

    nginx 配置跨域失效修复的方法示例

    nginx 配置跨域不生效 如下配置 server { listen 80; server_name localhost; # 接口转发 location /api/ { # 允许请求地址跨域 * 做为通配符 add_header 'Access-Control-Allow-Origin' '*'; # 设置请求...

    深入理解Nginx中Server和Location的匹配逻辑

    Nginx在决定请求由哪个server块执行时,主要关注的是server块中的listen和server_name两个字段 listen指令 listen字段定义server响应的ip和端口,如果没有明确配置listen字段,默认监听0.0.0.0:80(root)或者0.0.0.0:...

    nginx负载均衡配置-windows.docx

    在 location 块中,我们可以配置 URL 路由规则,使用 proxy_pass 指令将请求代理到 upstream 服务器。这里我们还可以配置 proxy_set_header 指令来设置 HTTP 头信息。 本文档提供了一个完整的 Nginx 负载均衡配置...

    nginx安装与配置详细资料+weblogic集群配置

    下面是 Nginx 安装与配置的详细资料。 一、Nginx 安装步骤 1.1 下载介质 在安装 Nginx 之前,需要下载 Nginx 及其相关组件。根据项目的需要选择需要安装的组件,实际环境一般会考虑需要支持 gzip 压缩和 rewrite ...

    Nginx配置http转https以及https访问http静态资源.docx

    在第一个server块中,我们使用了location指令来配置静态资源的访问。其中,/位置用于配置网站的根目录,add_header指令用于添加Content-Security-Policy头,以便升级不安全的请求。proxy_pass指令用于将请求代理到...

    nginx location 配置 正则表达式实例详解

    •location 是在 server 块中配置,用来通过匹配接收的uri来实现分类处理不同的请求,如反向代理,取静态文件等 •location 在 server 块中可以有多个,且是有顺序的,会被第一个匹配的 location 处理 •localtion ...

    nginx 详细配置

    Nginx 详细配置 Nginx 是一款流行的开源 Web 服务器软件,常用于构建高性能的 Web 应用。相比 Apache,Nginx 有着更好的负载均衡性能。本文将详细讲解 Nginx 的配置,帮助读者更好地理解和应用 Nginx。 一、基础...

    Web服务器三剑客运维配置实战 Nginx+JVM+Tomcat+HTTP协议.zip

    ├─2.13 Nginx进阶基础-常见配置-location.mp4 ├─3.01 Nginx进阶配置提升-预定义变量及日志详解.mp4 ├─3.02 Nginx进阶配置提升-日志切割及升级.mp4 ├─3.03 Nginx进阶-配置提升-Nginx错误页面.mp4 ├─3.04 ...

    nginx配置文件详解.docx

    Nginx 配置文件详解 Nginx 配置文件是 Nginx 服务器的核心组件之一,负责控制 Nginx 服务器的行为和性能。本文将详细解释 Nginx 配置文件的结构和各个组件的作用。 全局配置 Nginx 配置文件的第一部分是全局配置...

    nginx 301 302重定向跳转配置.docx

    Nginx 的 IF 条件判断可以在 `server` 和 `location` 块中使用,条件可以是正则表达式、文件和目录判断、return 代码等。 例如,以下配置使用 IF 条件判断来重定向用户使用 IE 浏览器的请求: ``` if ($...

    把windows本地静态资源通过nginx发布

    Nginx virtual host 配置用于配置虚拟主机,例如 server_name、listen、root、index 等指令。 知识点 5: Nginx location 配置 location 配置用于配置 URL 到文件系统的映射关系。例如,location / { root /nginx-...

    Nginx配置反向代理.doc

    Nginx 配置反向代理是指通过 Nginx 服务器将请求转发到多个内部服务器,以实现负载均衡和高可用性。反向代理服务器决定哪台服务器提供服务,而不是直接提供服务,而是将请求转发到内部服务器。 Nginx 实现反向代理...

    linux-nginx代理配置

    Linux Nginx 代理配置 Linux Nginx 代理配置是将 Nginx 服务器作为反向代理,代理其他服务器的服务,常用于负载均衡、缓存、安全性提高等目的。本文将详细介绍 Linux Nginx 代理配置的步骤和相关技术细节。 Nginx ...

    nginx 多个location转发任意请求或访问静态资源文件的实现

    本文主要介绍了nginx 多个location转发任意请求或访问静态资源文件的实现,分享给大家,具体如下: server { #监听的端口 listen 80; #监听的域名 server_name localhost; #监听带后缀的url location ^~\.txt...

    Nginx学习笔记

    Nginx 是一个流行的开源 Web 服务器软件,能够处理高并发请求,常用于搭建高性能的 Web 服务器。本文将对 Nginx 的安装、配置、日志管理等方面进行详细的介绍。 一、Nginx 的安装 Nginx 的安装可以通过源代码编译...

    Nginx反向代理以及配置优化.docx

    在这个示例配置中,Nginx服务器充当反向代理服务器,将客户端的请求转发到后端服务器。同时,Nginx服务器还提供了日志记录、缓存、负载均衡等功能。 这个示例配置展示了Nginx反向代理的基本配置和优化,旨在提高...

    docker 安装 wordpress,通过nginx反向代理,绑定域名,配置https

    我们需要配置 Nginx 反向代理,以便访问 WordPress 站点。我们可以在 nginx.conf 文件中添加以下配置: ``` server { listen 80; server_name ikeguang.com; location / { proxy_pass http://localhost:8080; ...

Global site tag (gtag.js) - Google Analytics