初探Nginx HTTP处理流程

本文介绍了Nginx的HTTP处理流程,从基本概念、初始化服务器、HTTP请求解析到请求处理阶段,详细讲解了Nginx如何接收和处理HTTP请求,包括连接池、请求头解析、事件处理和11个处理阶段的工作原理。
摘要由CSDN通过智能技术生成

基本概念:

  Nginx作为一款开源的、高性能的HTTP服务器和反向代理服务器而闻名,本文基于nginx-1.15.0,将为读者简要介绍其HTTP处理流程。

  通常nginx配置文件如下所示:

worker_processes  1;

events {
    worker_connections  1024;
}

http{
    access_log  logs/access.log  main;
    
    server {
        listen       80;
        server_name  example.com;
        
        location ~ \.php$ {
            fastcgi_pass   127.0.0.1:9000;
        }
    }
}
  • Nginx采用master-worker编模式,master初始化配置,创建Socket并监听端口,启动并管理worker进程,worker进程负责接收客户端请求并提供服务;其中程worker_processes配置的就是worker进程的数目;
  • events指令块用于配置事件处理相关,比如worker_connections用于配置每个worker进程最大维护的socket链接数目;
  • http指令块用于配置http请求处理相关,比如access_log用于配置access日志文件路径;
  • server指令块用于配置virtual server,通常会在一台机器配置多个virtual server,监听不同端口号,映射到不同文件目录;比如listen可配置监听端口号;
  • location指令块配置不同路径请求处理方式,比如proxy_pass可配置将请求按照http协议格式转发给上游,fastcgi_pass可配置将请求按照fastcgi协议转发给fpm处理。

  Nginx高度模块化,每个模块实现某一具体功能,比如ngx_http_limit_req_module模块实现按请求速率限流功能,ngx_http_fastcgi_module模块实现fastcgi协议通信功能。每个模块都需要解析配置文件中相关配置,每个模块需要解析的所有配置都定义为ngx_command_t数组。

  例如ngx_http_module模块,其ngx_command_t数定义如下:

struct ngx_command_s {
    ngx_str_t             name;
    ngx_uint_t            type;
    char               *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
    ...
};
 
static ngx_command_t  ngx_http_commands[] = {
 
    { ngx_string("http"),
      NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
      ngx_http_block,
      ...
     },
};
  • name指令名称,解析配置文件时按照名称能匹配查找;
  • type指令类型,NGX_CONF_NOARGS标识该配置无参数,NGX_CONF_BLOCK该配置是一个配置块,NGX_MAIN_CONF表示配置可以出现在哪些位置(NGX_MAIN_CONF、NGX_HTTP_SRV_CONF、NGX_HTTP_LOC_CONF);
  • set指令处理函数;

初始化服务器

  http指令块用于配置http请求处理相关,解析http指令的处理函数为ngx_http_block,实现如下:

static char * ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    //解析main配置
    //解析server配置
    //解析location配置
 
    //初始化HTTP处理流程所需的handler
 
    //初始化listening
    if (ngx_http_optimize_servers(cf, cmcf, cmcf->ports) != NGX_OK) {
        return NGX_CONF_ERROR;
    }
}

  函数ngx_http_block主要解析http块内部的main配置、server配置与location配置;同时会初始化HTTP处理流程所需的handler;以及初始化所有监听端口。

  函数ngx_http_optimize_servers将所有配置的IP端口进一步解析,并存储在conf->cycle->listening字段,这是一个数组,后续操作会遍历此数组,创建socket并监听。

  conf->cycle->listening数组元素类型为ngx_listening_t,创建该ngx_listening_t对象时,同时会设置其处理handler为函数ngx_http_init_connection,当接受到客户端链接请求时,会调用此handler。

  那么什么时候启动监听呢?全局搜索关键字cycle->listening可以找到。main方法会调用ngx_init_cycle,其完成了服务器初始化的大部分工作,其中就包括启动监听(ngx_open_listening_sockets):

ngx_int_t ngx_open_listening_sockets(ngx_cycle_t *cycle)
{
    for (i = 0; i < cycle->listening.nelts; i++) {
        
        s = ngx_socket(ls[i].sockaddr->sa_family, ls[i].type, 0);
        
        bind(s, ls[i].sockaddr, ls[i].socklen);
        
        listen(s, ls[i].backlog);
    }
}

  假设nginx使用epoll处理所有socket事件,那么什么时候将监听事件添加到epoll呢?同样全局搜索关键字cycle->listening可以找到。ngx_event_core_module模块是事件处理核心模块,初始化此模块时会执行ngx_event_process_init函数,从而将监听事件添加到epoll:

static ngx_int_t ngx_event_process_init(ngx_cycle_t *cycle)
{
    ls = cycle->listening.elts;
    for (i = 0; i < cycle->listening.nelts; i++) {
        //设置读事件处理handler
        rev->handler = ngx_event_accept;
         
        ngx_add_event(rev, NGX_READ_EVENT, 0);
    }
}

  注意到向epoll添加读事件时,设置该读事件处理函数为ngx_event_accept,即接收到客户端socket连接请求事件时会调用该处理函数。

HTTP请求解析

基础结构体

  结构体ngx_connection_t存储socket连接相关信息;nginx预先创建若干个ngx_connection_t对象,

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值