Nginx可以开启多个进程,每个进程拥有最大上限128个子线程以及一定的可用连接数。如果你希望使用线程可以在配置文件中设置worker_threads这个参数,但这个参数在Nginx官方手册上没有。只有通过阅读源代码才看到。最大客户端连接数等于进程数与连接数的乘积,连接是在主进程中初始化的,一开始所有连接处于空闲状态。
每一个客户端请求进来以后会通过事件处理机制,在Linux是Epoll,在FreeBSD下是KQueue放到空闲的连接里。
如果设置了线程数,那么被填充的连接会在子线程中处理,否则会在主线程中依次处理。
如果解析出是动态脚本请求,会根据fast-cgi的设置访问php-cgi进程,php进程数量的多少依据php-fpm.conf中max_children的设置。
因此Nginx的动态请求能力不仅仅依靠Nginx本身的设置,还要调试php-fpm。从源代码级别上看nginx由以下几个元素组成:
1. worker(进程)
2. thread(线程)
3. connection(连接)
4. event(事件)
5. module(模块)
6. pool(内存池)
7. cycle(全局设置)
8. log(日志)
大概就这些元素组成的。
整个程序从main()开始算
ngx_max_module = 0;
for (i = 0; ngx_modules[i]; i++) {
ngx_modules[i]->index = ngx_max_module++;
}
这几句比较关键,对加载的模块点一下数,看有多少个。ngx_modules并不是在原代码中被赋值的,你先执行一下./configure命令生成用于编译的make环境。在根目录会多出来一个文件夹objs,找到ngx_modules.c文件,默认情况下nginx会加载大约30个模块,的确不少,如果你不需要那个模块尽量还是去掉好一些。
接下来比较重要的函数是 ngx_init_cycle(),这个函数初始化系统的配置以及网络连接等,如果是多进程方式加载的会继续调用ngx_master_process_cycle(),这是main函数中调用的最关键的两个函数。
ngx_init_cycle()实际上是个复杂的初始化函数,首先是加载各子模块的配置信息、并初始化各组成模块。
任何模块都有两个重要接口组成,一个是create_conf,一个是init_conf。分别是创建配置和初始化配置信息。
模块按照先后顺序依次初始化,大概是这样的:
&ngx_core_module,
&ngx_errlog_module,
&ngx_conf_module,
&ngx_events_module,
&ngx_event_core_module,
&ngx_epoll_module,
&ngx_http_module,
&ngx_http_core_module,
&ngx_http_log_module,
首先是内核模块、错误日志、配置模块、事件模块、时间内核模块、EPOLL模块、http模块、http内核模块、http日志模块,剩下的模块都算不上关键。
epoll是比较关键的核心模块之一,nginx兼容多种IO控制模型,memecached用的是libevent不如nginx彻头彻尾是自己实现的。
在ngx_init_cycle()中对模块初始化完毕后,调用ngx_open_listening_sockets()函数对socket进行了初始化。
在listen上80端口以后,调用模块的另外一个重要接口init_module对各模块进行初始化。
并不是每个模块都对init_module接口进行了定义,在比较重要的模块中仅有 ngx_http_log_module 对这个接口进行了定义。
ngx_init_cycle()返回后,主要的工作都是在ngx_master_process_cycle()函数中继续进行的。
ngx_master_process_cycle()函数中的重要过程有调用ngx_start_worker_processes()生成多个子进程,一般nginx是多进程的。
ngx_start_worker_processes()函数内部调用ngx_worker_process_cycle()函数建立每个进程的实际工 作内容,在这个函数中首先调用ngx_create_thread()初始化各线程。我们知道每个线程都有一个启动处理函数,nginx的线程处理函数为 ngx_worker_thread_cycle(),内部过程中最重要的是对ngx_event_thread_process_posted()函数 的调用,用于实际处理每一次请求。
在初始化线程结束后,首先调用ngx_process_events_and_timers()函数,该函数继续调用 ngx_process_events接口监听事件,一般情况下对应的函数是ngx_epoll_process_events(),如果使用的是其它种 类的IO模型,则应该实现相应的实际函数。这个接口负责把事件投递到ngx_posted_events事件队列里,并在 ngx_event_thread_process_posted()函数中进行处理。
nginx的connection和event是按照链表的方式进行存放的,区别在于connection是单向链表而event是双向链表。
nginx中的connection链表是提前分配的,定义在ngx_event_process_init()函数内,具体代码如下:
...
cycle->connections = ngx_alloc(sizeof(ngx_connection_t) * ecf->connections,
cycle->log);
...
i = cycle->connection_n;
next = NULL;
do {
i--;
c[i].data = next;
c[i].read = &cycle->read_events[i];
c[i].write = &cycle->write_events[i];
c[i].fd = (ngx_socket_t) -1;
next = &c[i];
#if (NGX_THREADS)
c[i].lock = 0;
#endif
} while (i);
cycle->free_connections = next;
cycle->free_connection_n = ecf->connections;
在内存池里为所有connection分配空间,并依次初始化,并依次初始化各连接的链表关系,也就是在data上存下一个connection的指针。
在具体应用中通过ngx_get_connection()函数取出空闲的connection并使用。
至于event是一个双向链表,链表的入队和出队有下面的定义:
#define ngx_locked_post_event(ev, queue) \
\
if (ev->prev == NULL) { \
ev->next = (ngx_event_t *) *queue; \
ev->prev = (ngx_event_t **) queue; \
*queue = ev; \
\
if (ev->next) { \
ev->next->prev = &ev->next; \
} \
\
ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0, "post event %p", ev); \
\
} else { \
ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0, \
"update posted event %p", ev); \
}
#define ngx_post_event(ev, queue) \
\
ngx_mutex_lock(ngx_posted_events_mutex); \
ngx_locked_post_event(ev, queue); \
ngx_mutex_unlock(ngx_posted_events_mutex);
#define ngx_delete_posted_event(ev) \
\
*(ev->prev) = ev->next; \
\
if (ev->next) { \
ev->next->prev = ev->prev; \
} \
\
ev->prev = NULL; \
ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0, \
"delete posted event %p", ev);
简单说 ngx_post_event 用于插入事件、ngx_delete_posted_event 用于删除事件。这两个是宏定义,会比函数定义用起来节省。
整个程序就围绕这event和connection进行。不断的投入、拿出。
nginx的模块处理
nginx由若干模块组成,但所有模块全部采用静态编译的办法。我们以rewrite模块为例,
我们输入./configure --help 命令可以查看的有关rewrite模块的描述
--without-http_rewrite_module disable ngx_http_rewrite_module
这是在auto/options下定义的,在auto/soruces里面指定了与这个模块有关的源代码位置
HTTP_REWRITE_MODULE=ngx_http_rewrite_module
HTTP_REWRITE_SRCS=src/http/modules/ngx_http_rewrite_module.c
在auto/summary下提供了关于rewrite模块的依赖条件检查:
if [ $HTTP_REWRITE = YES ]; then
if [ $USE_PCRE = DISABLED ]; then
cat << END
$0: error: the HTTP rewrite module requires the PCRE library.
You can either disable the module by using --without-http_rewrite_module
option or you have to enable the PCRE support.
END
exit 1
fi
if [ $PCRE = NONE -o $PCRE = NO ]; then
cat << END
$0: error: the HTTP rewrite module requires the PCRE library.
You can either disable the module by using --without-http_rewrite_module
option, or install the PCRE library into the system, or build the PCRE library
statically from the source with nginx by using --with-pcre=<path> option.
END
exit 1
fi
fi
下面是对rewrite模块代码分析,其它模块也带有同样的结构。
一般模块都会有一个ngx_command_t结构,存放在ngingx配置文件中,这个模块的一些语法命令,详细结构为:
struct ngx_command_s {
ngx_str_t name;
ngx_uint_t type;
char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
ngx_uint_t conf;
ngx_uint_t offset;
void *post;
};
name 是名称
type 是类型
set 是处理这个命令的具体函数
conf 属于那种配置,一共三种 main结构、server结构、location结构。
offset 在配置文件中的偏移量。
post 没见到用到。
下面是和rewrite模块中的代码:
static ngx_command_t ngx_http_rewrite_commands[] = {
{ ngx_string("rewrite"),
NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_TAKE23,
ngx_http_rewrite,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL },
{ ngx_string("return"),
NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_TAKE1,
ngx_http_rewrite_return,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL },
{ ngx_string("break"),
NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_NOARGS,
ngx_http_rewrite_break,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL },
{ ngx_string("if"),
NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_BLOCK|NGX_CONF_1MORE,
ngx_http_rewrite_if,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL },
{ ngx_string("set"),
NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_TAKE2,
ngx_http_rewrite_set,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL },
{ ngx_string("rewrite_log"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF
|NGX_HTTP_LIF_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_rewrite_loc_conf_t, log),
NULL },
{ ngx_string("uninitialized_variable_warn"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF
|NGX_HTTP_LIF_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_rewrite_loc_conf_t, uninitialized_variable_warn),
NULL },
ngx_null_command
};
rewrite模块内部一共有四类函数,关键的一类为一类是动作处理函数,一共有:
ngx_http_rewrite_init 模块初始化函数。
ngx_http_rewrite_handler 在具体请求中的处理函数。
这两个函数通过在模块初始化的过程中,把handler推送到phases结构中,这是一个简单数组,请求会对数组中存放的每一个handler依次进行处理。如果我们自己写什么模块也应该放进去,例如同样的ngx_http_access_init()等初始化函数也是把自己模块的ngx_http_access_handler注册进去。
nginx在内部已经定义了所有可以在http请求中被处理的模块列表:
typedef enum {
NGX_HTTP_POST_READ_PHASE = 0,
NGX_HTTP_SERVER_REWRITE_PHASE,
NGX_HTTP_FIND_CONFIG_PHASE,
NGX_HTTP_REWRITE_PHASE,
NGX_HTTP_POST_REWRITE_PHASE,
NGX_HTTP_PREACCESS_PHASE,
NGX_HTTP_ACCESS_PHASE,
NGX_HTTP_POST_ACCESS_PHASE,
NGX_HTTP_CONTENT_PHASE,
NGX_HTTP_LOG_PHASE
} ngx_http_phases;
和rewrite有关的一共是两个,都是在ngx_http_rewrite_handler()函数中进行处理
一类为与配置文件有关的创建和合并函数,一共有:
ngx_http_rewrite_create_loc_conf
ngx_http_rewrite_merge_loc_conf
一类作为common命令的解析函数,一共有:
ngx_http_rewrite
ngx_http_rewrite_return
ngx_http_rewrite_break
ngx_http_rewrite_if
ngx_http_rewrite_set
一类为解析命令中内部使用的函数,一共有:
ngx_http_rewrite_if_condition
ngx_http_rewrite_variable
ngx_http_rewrite_value
ngx_http_rewrite_var
langwan 2008.11
http://hi.baidu.com/langwan
相关推荐
动态加载概述与原理.docx
LOL_params_0900000.pt
分群用户详情_7_2024-09-06 09_49_58
动态加载的高级主题:懒加载与按需加载.docx
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。 替换数据可以直接使用,注释清楚,适合新手
为Towny Flagwar实现中立国家 /nasetnu 设置自己的国家为中立(仅king可用)
本代码是基于python pytorch环境安装的。 下载本代码后,有个环境安装的requirement.txt文本 首先是代码的整体介绍 总共是3个py文件,十分的简便 本代码是不含数据集图片的,下载本代码后需要自行搜集图片放到对应的文件夹下即可 需要我们往每个文件夹下搜集来图片放到对应文件夹下,每个对应的文件夹里面也有一张提示图,提示图片放的位置 然后我们需要将搜集来的图片,直接放到对应的文件夹下,就可以对代码进行训练了。 运行01生成txt.py,是将数据集文件夹下的图片路径和对应的标签生成txt格式,划分了训练集和验证集 运行02CNN训练数据集.py,会自动读取txt文本内的内容进行训练,这里是适配了数据集的分类文件夹个数,即使增加了分类文件夹,也不需要修改代码即可训练 训练过程中会有训练进度条,可以查看大概训练的时长,每个epoch训练完后会显示准确率和损失值 训练结束后,会保存log日志,记录每个epoch的准确率和损失值 最后训练的模型会保存在本地名称为model.ckpt 运行03pyqt界面.py,就可以实现自己训练好的模型去识别图片了
内容概要:本文详细介绍了一款基于Java的订餐系统的设计与实现。文章首先介绍了互联网时代背景下,订餐系统作为一种新型生活方式的便捷性与必要性。接着阐述了系统的设计背景、目的及其所采用的技术框架(如JSP、MySQL、MyEclipse)。系统分为前台和后台两大部分,前台主要负责用户的界面展示和互动,包括食品展示、查询、购物车等功能;后台则是管理员进行餐品管理和用户信息维护的平台。文中还详细解析了各主要功能模块的设计思路和技术实现细节,以及数据库表结构的设计。 适合人群:具备一定的Java开发基础,对Web应用开发有兴趣的初学者或工程师。 使用场景及目标:用于学习基于B/S架构的订餐系统的开发全过程,理解前后端分离、JSP动态页面生成、MySQL数据库操作等核心技术的应用。适合希望深入了解餐饮管理系统内部运作机制的学生或从业者。 其他说明:此系统设计符合现代互联网发展趋势,通过引入JSP、JavaScript、MySQL等主流技术,旨在提高餐饮行业的管理效率和服务水平,增强用户体验。此外,本项目也包含了系统测试的内容,确保各项功能的正常运转。
功能说明: 管理员:个人中心、用户管理、商品分类管理、品牌管理、商品信息管理、订单评价管理、留言板管理、系统管理、订单管理。用户:个人中心、订单评价管理、我的收藏管理、订单管理。前台首页:首页、商品信息、商品资讯、留言反馈、我的、跳转到后台、购物车等功能的家用电器销售网站。 环境说明: 开发语言:java 框架:ssm jdk版本:jdk1.8 数据库:mysql 5.7+ 数据库工具:Navicat11+ 管理工具:maven 开发工具:idea/eclipse 部署容器:tomcat7+
联想电脑的bios设置、图文都有
技术:ssm+mysql+redis vue+element 功能:宿舍管理、学生管理、班级管理、宿舍楼管理、维修记录、晚归记录、请假记录、用户管理、角色管理、菜单管理、日志管理
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。 替换数据可以直接使用,注释清楚,适合新手
跨浏览器兼容性测试.docx
Vosk是一个开源的语音识别工具,支持中英文及多种语言,具备离线识别能力,且不依赖互联网。优势 Vosk 是一个离线开源语音识别工具包,它的优点在于: 轻量:Vosk 提供轻量级的模型(小于 50MB 大小),可以用于低功耗平台(例如 Android、树莓派之类) 多编程语言、多平台支持:Python、Java、Node.js、C#、C++、Rust、Go 等 多语种支持:支持二十多种语言的识别(包括中文) 实时性:实时性语音识别场景下,vosk 的延迟非常低 简单来讲,你电脑中有 Python 环境,再下载一个 50 MB 的模型,就可以用 Vosk 实现一个正确率还可以接受的语言识别相关的项目。而像 Whisper 虽然识别效果好,但是对硬件要求很高,同时部署起来麻烦(例如需要配置 CUDA 环境),另外也不是很适用于实时性场景。 此包为编译好的c调用的运行库,有需要的可以直接下载使用。
影视源码自动对接资源站开源源码
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。 替换数据可以直接使用,注释清楚,适合新手
大学生社团管理系统 SSM毕业设计 附带论文 启动教程:https://www.bilibili.com/video/BV1GK1iYyE2B
网络安全 - 图片文件黑客攻击
服务器可运行。实现文件复制。
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。 替换数据可以直接使用,注释清楚,适合新手