首页 > 网站 > Nginx > 正文

nginx源码分析线程池详解

2024-08-30 12:25:36
字体:
来源:转载
供稿:网友

nginx源码分析线程池详解

一、前言

     nginx是采用多进程模型,master和worker之间主要通过pipe管道的方式进行通信,多进程的优势就在于各个进程互不影响。但是经常会有人问道,nginx为什么不采用多线程模型(这个除了之前一篇文章讲到的情况,别的只有去问作者了,HAHA)。其实,nginx代码中提供了一个thread_pool(线程池)的核心模块来处理多任务的。下面就本人对该thread_pool这个模块的理解来跟大家做些分享(文中错误、不足还请大家指出,谢谢) 

二、thread_pool线程池模块介绍

     nginx的主要功能都是由一个个模块构成的,thread_pool也不例外。线程池主要用于读取、发送文件等IO操作,避免慢速IO影响worker的正常运行。先引用一段官方的配置示例

Syntax: thread_pool name threads=number [max_queue=number];Default: thread_pool default threads=32 max_queue=65536;Context: main

     根据上述的配置说明,thread_pool是有名字的,上面的线程数目以及队列大小都是指每个worker进程中的线程,而不是所有worker中线程的总数。一个线程池中所有的线程共享一个队列,队列中的最大人数数量为上面定义的max_queue,如果队列满了的话,再往队列中添加任务就会报错。 

     根据之前讲到过的模块初始化流程(在master启动worker之前) create_conf--> command_set函数-->init_conf,下面就按照这个流程看看thread_pool模块的初始化

/******************* nginx/src/core/ngx_thread_pool.c ************************///创建线程池所需的基础结构static void * ngx_thread_pool_create_conf(ngx_cycle_t *cycle){  ngx_thread_pool_conf_t *tcf;   //从cycle->pool指向的内存池中申请一块内存  tcf = ngx_pcalloc(cycle->pool, sizeof(ngx_thread_pool_conf_t));  if (tcf == NULL) {    return NULL;  }      //先申请包含4个ngx_thread_pool_t指针类型元素的数组   //ngx_thread_pool_t结构体中保存了一个线程池相关的信息  if (ngx_array_init(&tcf->pools, cycle->pool, 4,            sizeof(ngx_thread_pool_t *))    != NGX_OK)  {    return NULL;  }   return tcf;} //解析处理配置文件中thread_pool的配置,并将相关信息保存的ngx_thread_pool_t中static char * ngx_thread_pool(ngx_conf_t *cf, ngx_command_t *cmd, void *conf){  ngx_str_t     *value;  ngx_uint_t     i;  ngx_thread_pool_t *tp;   value = cf->args->elts;   //根据thread_pool配置中的name作为线程池的唯一标识(如果重名,只有第一个有效)  //申请ngx_thread_pool_t结构保存线程池的相关信息  //由此可见,nginx支持配置多个name不同的线程池  tp = ngx_thread_pool_add(cf, &value[1]);  .......  //处理thread_pool配置行的所有元素  for (i = 2; i < cf->args->nelts; i++) {    //检查配置的线程数    if (ngx_strncmp(value[i].data, "threads=", 8) == 0) {     .......    }         //检查配置的最大队列长度    if (ngx_strncmp(value[i].data, "max_queue=", 10) == 0) {     .......    }  }  ......} //判断包含多个线程池的数组中的各个线程池的配置是否正确static char * ngx_thread_pool_init_conf(ngx_cycle_t *cycle, void *conf){  ....  ngx_thread_pool_t **tpp;   tpp = tcf->pools.elts;  //遍历数组中所有的线程池配置,并检查其正确性  for (i = 0; i < tcf->pools.nelts; i++) {    .....  }   return NGX_CONF_OK;}            
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表