网站首页 > 精选教程 正文
相关视频解析:
这一章节,主要讲解监听套接字初始化函数ngx_http_optimize_servers和Nginx整个连接的过程
一、监听套接字初始化函数ngx_http_optimize_servers
ngx_http_optimize_servers主要处理Nginx服务的监听套接字
/** * ngx_http_optimize_servers:处理Nginx服务的监听套接字 * 说明:主要遍历Nginx服务器提供的端口,然后根据每一个IP地址:port这种配置创建一个监听套接字 * ngx_http_init_listening:初始化监听套接字 */static ngx_int_tngx_http_optimize_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf, ngx_array_t *ports){ ngx_uint_t p, a; ngx_http_conf_port_t *port; ngx_http_conf_addr_t *addr; if (ports == NULL) { return NGX_OK; } /* 根据Nginx配置的端口号进行遍历 */ port = ports->elts; for (p = 0; p < ports->nelts; p++) { ngx_sort(port[p].addrs.elts, (size_t) port[p].addrs.nelts, sizeof(ngx_http_conf_addr_t), ngx_http_cmp_conf_addrs); /* * check whether all name-based servers have the same * configuration as a default server for given address:port */ addr = port[p].addrs.elts; for (a = 0; a < port[p].addrs.nelts; a++) { if (addr[a].servers.nelts > 1#if (NGX_PCRE) || addr[a].default_server->captures#endif ) { if (ngx_http_server_names(cf, cmcf, &addr[a]) != NGX_OK) { return NGX_ERROR; } } } /* 初始化监听套接字 */ if (ngx_http_init_listening(cf, &port[p]) != NGX_OK) { return NGX_ERROR; } } return NGX_OK;}
ngx_http_init_listening 主要初始化侦听套接字
/** * 初始化侦听套接字 */static ngx_int_tngx_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; /* * 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) { addr[last - 1].opt.bind = 1; bind_wildcard = 1; } else { bind_wildcard = 0; } i = 0; /* 根据IP地址 遍历 创建 listening*/ while (i < last) { if (bind_wildcard && !addr[i].opt.bind) { i++; continue; } /* 创建侦听套接字 listening */ 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; hport->naddrs = i + 1; switch (ls->sockaddr->sa_family) { #if (NGX_HAVE_INET6) case AF_INET6: if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) { return NGX_ERROR; } break;#endif default: /* AF_INET */ if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) { return NGX_ERROR; } break; } if (ngx_clone_listening(cf, ls) != NGX_OK) { return NGX_ERROR; } addr++; last--; } return NGX_OK;}
【文章福利】需要C/C++ Linux服务器架构师学习资料加群812855908(资料包括C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等)
ngx_http_add_listening 创建侦听套接字 listening
/** * 创建侦听套接字 listening */static ngx_listening_t *ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr){ ngx_listening_t *ls; ngx_http_core_loc_conf_t *clcf; ngx_http_core_srv_conf_t *cscf; /* 创建一个套接字 */ ls = ngx_create_listening(cf, &addr->opt.sockaddr.sockaddr, addr->opt.socklen); if (ls == NULL) { return NULL; } ls->addr_ntop = 1; /* 侦听套接字 的回调函数。该回调函数在ngx_event_accept函数中回调; * 回调之后,会将读取事件回调函数rev->handler()修改成方法:ngx_http_wait_request_handler*/ ls->handler = ngx_http_init_connection; cscf = addr->default_server; ls->pool_size = cscf->connection_pool_size; ls->post_accept_timeout = cscf->client_header_timeout; clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index]; ls->logp = clcf->error_log; ls->log.data = &ls->addr_text; ls->log.handler = ngx_accept_log_error; return ls;}
二、Nginx整个连接的过程
我们将整个Nginx的连接过程串起来,整个流程如下:
在Nginx main函数的ngx_init_cycle()方法中,调用了ngx_open_listening_sockets函数,这个函数负责将创建的监听套接字进行套接字选项的设置(比如非阻塞、接受发送的缓冲区、绑定、监听处理)
HTTP模块初始化优先于Event模块,HTTP模块通过ngx_http_block()方法进行初始化,然后调用ngx_http_optimize_servers()进行套接字的创建和初始化(ngx_http_init_listening、ngx_http_add_listening、ngx_create_listening)。根据每一个IP地址:port这种配置创建监听套接字。
ngx_http_add_listening函数,还会将ls->handler监听套接字的回调函数设置为ngx_http_init_connection。ngx_http_init_connection此函数主要初始化一个客户端连接connection。
Event模块的初始化主要调用ngx_event_process_init()函数。该函数每个worker工作进程都会初始化调用。然后设置read/write的回调函数。
ngx_event_process_init函数中,会将接收客户端连接的事件,设置为rev->handler=ngx_event_accept方法,ngx_event_accept方法,只有在第一次客户端和Nginx服务端创建连接关系的时候调用。
当客户端有连接上来,Nginx工作进程就会进入事件循环(epoll事件循环函数:ngx_epoll_process_events),发现有read读取的事件,则会调用ngx_event_accept函数。
调用ngx_event_accept函数,会调用ngx_get_connection方法,得到一个客户端连接结构:ngx_connection_t结构。ngx_event_accept函数最终会调用监听套接字的handler回调函数,ls->handler(c); 。
从流程3中,我们知道ls->handler的函数对应ngx_http_init_connection方法。此方法主要初始化客户端的连接ngx_connection_t,并将客户端连接read读取事件的回调函数修改成rev->handler = ngx_http_wait_request_handler
也就是说,当客户端连接上来,第一次事件循环的read事件会调用回调函数:ngx_event_accept函数;而后续的read事件的handler已经被ngx_http_init_connection方法修改掉,改成了ngx_http_wait_request_handler函数了。所以客户端的读取事件都会走ngx_http_wait_request_handler函数。
ngx_http_wait_request_handler函数也是整个HTTP模块的数据处理的入口函数了。
如下图表格:
猜你喜欢
- 2024-09-22 T5大牛带你解读Spring核心源码—一小时手写SpringMVC!
- 2024-09-22 Nginx源码安装并开启http2.0以及brotli压缩
- 2024-09-22 nginx源码剖析—nginx进程模型
- 2024-09-22 Nginx的DNS解析详细过程分析(建议收藏)
- 2024-09-22 开源Superset在线设计图表框架源码解析
- 2024-09-22 熬夜怒肝!SpringCloud 源码之负载均衡 Ribbon,2W字长文深度分析
- 2024-09-22 Nginx源码剖析之内存池,与内存管理
- 2024-09-22 从网卡到应用层nginx,一个数据包经历了什么?
- 2024-09-22 Nginx源码从模块开发开始,不再对nginx源码发怵
- 2024-09-22 「源码分享」.NET Core前后端分离快速开发框架(Core.3.1+AntdVue)
你 发表评论:
欢迎- 04-11Java面试“字符串三兄弟”String、StringBuilder、StringBuffer
- 04-11Java中你知道几种从字符串中找指定的字符的数量
- 04-11探秘Java面试中问的最多的String、StringBuffer、StringBuilder
- 04-11Python字符串详解与示例(python字符串的常见操作)
- 04-11java正则-取出指定字符串之间的内容
- 04-11String s1 = new String("abc");这句话创建了几个字符串对象?
- 04-11java判断字符串中是否包含某个字符
- 04-11关于java开发中正确的发牌逻辑编写规范
- 最近发表
-
- Java面试“字符串三兄弟”String、StringBuilder、StringBuffer
- Java中你知道几种从字符串中找指定的字符的数量
- 探秘Java面试中问的最多的String、StringBuffer、StringBuilder
- Python字符串详解与示例(python字符串的常见操作)
- java正则-取出指定字符串之间的内容
- String s1 = new String("abc");这句话创建了几个字符串对象?
- java判断字符串中是否包含某个字符
- 关于java开发中正确的发牌逻辑编写规范
- windows、linux如何后台运行jar(并且显示进程名)
- 腾讯大佬私人收藏,GitHub上最受欢迎的100个JAVA库,值得学习
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)