Nginx HTTP模块篇 Nginx接收HTTP请求的流程 (八)-张柏沛IT博客

正文内容

Nginx HTTP模块篇 Nginx接收HTTP请求的流程 (八)

栏目:Linux 发布时间:2020-02-14 18:09 浏览量:225

Nginx的配置块嵌套

main
http{
    upstream {...}
    split_clients {...}
    map {...}
    geo {...}
    server {
        if () {...}
        location {
            limit_except {...}
        }
        location {
            location {...}
        }
    }
    server {...}
}

 

http 配置块之外的部分我们称之为main,像事件模块,配置进程个数之类的都是写在main中的。

http中最核心的是server块、location块。一个http块中可以有多个server块和location块。nginx会根据链接中的域名找到对应的server块,然后根据uri路径找到对应的location块。

nginx中的配置指令有其对应的上下文范围。就是说有些配置只能放在某个配置块中,而不能出现在其他配置块中。

 

例如log_format指令在配置文件中用于指定每一行配置文件的格式。
文档对其介绍为:

Syntax:	log_format name [escape=default|json|none] string ...;
Default:	
log_format combined "...";
Context:	http

其中Context就是该指令的上下文,表示log_format只能出现在http块中。

 

access_log指令

Syntax:	access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];
access_log off;
Default:	
access_log logs/access.log combined;
Context:	http, server, location, if in location, limit_except

 

access_log配置可以出现在http, server, location, if in location, limit_except配置块中。

 


如果一个指令出现在多个配置块中,他们的优先级如何,是否可以合并?

指令分为两种

值指令: 存配置项的值的指令,这类指令可以合并,如 root,access_log,gzip

动作类指令:指定行为,这类不可以合并,如rewrite,proxy_pass

对于值指令,如果同时出现在多个配置块中,则遵循以下原则:
子配置不存在,直接使用父配置块的指令。
子配置存在,则覆盖父配置块的指令。
即子配置中的指令优先级更高。

 

例如:

http {
   server {
        listen 8080;
        root /home/geek/nginx/html;
        access_log logs/geek.access.log.log main;
        
        location /test {
            root /home/geek/nginx/test;
            access_log logs/access.test.log main;
        }
        
        location /dlib {
            alias dlib/;
        }
        
        location / {
        
        }
    }
}


如server下定义的root /home/geek/nginx/html; 表示凡是访问本服务器8080端口的请求都指向/home/geek/nginx/html目录。

第三个location中没有定义root或者alias,此时就会使用server的root指令配置的内容。
第一个location有定义root,那么会用它自己的root配置

每一个模块下面有些什么指令,指令的格式和参数,上下文等都在nginx官网文档中有详细说明。

 

listen 指令

context是server,只能在server中使用。

示例:

listen unix:/var/run/nginx.sock;
listen 127.0.0.1:8000;   # 只有内网可以访问,外网无法访问
listen 127.0.0.1;        # 默认80端口
listen 8000;             # 任何ip都可以访问
listen *:8000;      # 同 listen 8000;
listen [::1];
listen [::]:8000 ipv6only=on;

等等。

 

Nginx 接收请求的过程

Nginx接收请求过程

 

从上图可以看到三次握手之后,连接建立,操作系统内核会选中CPU中的某一个worker进程,将连接句柄传给epoll_wait这个函数,调用accept方法并分配连接内存池 connection_pool_size,默认是512个字节。
从epoll_wait到accept都是nginx的事件模块的工作。

接下来accept会把请求交给http模块去处理,然后事件模块就去处理其他的读事件或者写事件了。
而http模块开启,调用ngx_http_init_connection设置回调方法epoll_ctl,添加超时定时器,设置client_header_timeout默认60s。

此时只是建立了连接,把http模块给唤醒了而已。还没有真正开始处理请求。

当客户端真正开始发送http请求,服务端的操作系统接受一个客户端发来的DATA数据包(应用层),然后TCP层返回一个ACK数据包给客户端表示服务端收到了请求。
然后系统内核将这个DATA发送给nginx事件模块的epoll_wait函数,再交给HTTP模块处理,ngx_http_wait_request_handler分配内存来读http请求(参数client_header_buffer_size),默认是1k。这1k的内存是用来解析请求行的。

所以无论是建立连接和接收请求,nginx都要分配内存给每一个连接和每一个请求,建立的连接越多,处理的请求越多就越耗内存。

然后HTTP模块就开始接受URI,解析请求行(就是HTTP报文第一行中\r\n之前的部分,包括方法名POST/GET、URI、协议)。

Nginx解析HTTP请求头的流程

 

GET /full/000178f3e94cb440ff977d6a227d9ab1fdaca180.jpg HTTP/1.1\r\n

这就是一个请求行

如果发现URI很长,超过了刚刚分配的1k内存,nginx会分配更大的内存来解析请求行。


当解析完请求行,标识完URI,就开始接受和解析请求头header,请求头的大小就比请求行内容大多了。
此时nginx会分配更大的内存来解析header,然后标识header。

解析完请求行和请求头,nginx会移除超时定时器,然后开始11个阶段的HTTP请求处理。
 

如果您需要转载,可以点击下方按钮可以进行复制粘贴;本站博客文章为原创,请转载时注明以下信息

张柏沛IT技术博客 > Nginx HTTP模块篇 Nginx接收HTTP请求的流程 (八)

热门推荐
推荐新闻