当前位置: 首页 > 网络应用技术

NGINX流模块原理和代码分析

时间:2023-03-06 14:33:19 网络应用技术

  从1.9.0开始,NGINX添加了流模块,以实现四个-Layer协议的转发,代理和负载平衡。在功能和性能方面的差距及其实现相对简单。

  在性能方面,流模块在应用层中实现了四层转发层。它需要与两端建立套接字连接,然后在两端的数据和接收数据中以进行代理转发。因此,大量数据从内核状态传输到用户模式,然后从用户模式传输到内核状态。这些数据副本加上系统调度开销,与纯核的LV转发相比,存在一定差距。

  从功能的角度来看,流模块对许多协议的ALG功能几乎没有支持。这需要ALG支持的协议,例如SIP,端口模式等,流式模块没有良好的支持。

  正是由于相对简单的流模块,使我们有一个很好的机会窥视其完整的实施机制。

  我们将尝试使用下图中描述的流模块的主要数据结构分析以下代码方案,其中linux平台下的DNS负载平衡的示例以分析以下代码方案。

  如何从插座监视手柄上从图的上部和上侧的小红色框中接收到DNS流的连接过程,直到所有子市场相关的子模块中的所有相关子模块的处理程序功能红色盒子的下侧称为。

  在此过程中,如何通过选择哪种负载平衡算法为服务选择上游DNS服务。

  数据如何从客户端转发到NGINX,然后从NGINX转发到上游的服务器。

  以下分析中的所有相关代码均基于我们的DNS场景假设。

  用户状态中的四个层次代理主要基于以下步骤:

  创建套接字监视客户连接。

  连接客户端后,使用负载平衡器算法选择了正确的上游服务器,并建立了插座连接。

  将数据从客户端转换为上游服务器,然后将上游服务器接收到的数据转发到客户端。

  与上面的逻辑相似,NGINX流模块的一般逻辑如下图所示。

  First Nginx通过客户端建立下游执行服务器角色。

  然后扮演客户端的角色,然后选择服务器通过基于其自己的配置来通过特定的负载平衡算法建立连接。

  在两端之间的连接之后,NGINX将接收到的数据发送到另一端以实现代理函数。

  要在内核中实现四层代理,不需要侦听套接字,也不需要连接到远程服务器。所有数据包都在内核状态中重新固定。内核需要是nat。

  在系统启动阶段,每个模块调用该函数以解析与其自己的模块相关的配置。与流模块相对应的功能是NGX_STREAM_BLOCK,它主要完成以下任务。

  1)子模块配置文件的分析

  在ngx_stream_block函数的开头,生成流模块本身所需的上下文。然后调用create_main_conf,create_srv_conf,preponfiguration,init_main_conf,init_main_conf和merge_srv_srv_srv_conf reccession reccession yever -module的生成和初始化的配置信息,要求对每个子模型进行构模。并将此信息存储在流模块的上下文中。

  同时,在分析过程中,每个顺式模块的所有配置指令都具有用于处理的相对回调函数。例如,当代理模块正在处理proxy_pass指令时,上游将与分析服务器关联。在上游解析时,它将在上游和用于内部服务器的负载平衡算法相关联。

  整个分析过程完成后,流模块的所有侦听插座,配置的所有服务器,上游已经被解析,并且与彼此的负载平衡算法相关联,所有服务器在上游内部采用了所有服务器,从而提供了数据支持,从而提供了数据支持水平操作。

  2)子模块处理功能组织

  与HTTP模块类似,流模块将安装所有模块安装到以下七个阶段中的过程。

  所有流子模块均为如下,我们可以发现许多与许多HTTP模块相对应的子模块都可以在流模块中找到。

  函数NGX_STREAM_BLOCK调用NGX_STREAM_INIT_PHASE_HASELER初始化结构eptape_engine以存储流的所有子模块处理功能。这些处理功能构成了流模块处理的核心引擎。

  在完成NGX_STREAM_BLOCK之后的每个子模块的配置分析后,然后调用每个提交的每个提交的后配置函数以将其自己的处理程序函数存储到相应的处理程序阵列中。根据在特定逻辑中存储在epth_engine中的每个模块的处理程序。

  3)创建听力插座

  在解析配置文件的过程中,将生成与每个服务器相对应的侦听套接字。并将所有这些插座添加到全局收听套接字列表中。

  如果事件模块的初始化函数ngx_event_process_init,对于系统的每个侦听套接字,它将首先通过ngx_get_connection函数获取连接结构,以与客户端处理连接。连接自己的阅读事件的恢复功能to ngx_event_recvmsg.finally将此事件添加到全局民意调查红色和黑树中。连接了侦听插座后,ngx_event_recvmsg函数被调用。

  在NGX_STREAM_BLOCK函数的末尾,将调用NGX_STREAM_PREAM_OPTIMIZE_SERVERS函数以将“检索套接字的回调函数”设置为ngx_stream_init_connection.it在Leatel Socket的新连接处理函数ngx_event_recvmsg中被调用。

  当执行NGX_STREAM_BLOCK时,已经建立了与与整个流模块相关的控制平面相关的控制平面的数据结构。

  1)新连接处理

  当收听套接字接收数据时,操作系统将通知EPOLL返回,与Leatel Socket的事件回调函数NGX_EVENT_RECVMSG相对应。数据处理阶段。

  2)函数ngx_stream_init_connection逻辑

  在ngx_stream_init_connection函数中,将生成一个重要的数据结构,ngx_stream_session_t,并连接到连接到相应客户端的ngx_connection_t结构。执行此回调功能。

  3)函数ngx_stream_session_handler逻辑

  在ngx_stream_session_handler中,主要任务是调用ngx_stream_core_run_phasses执行dns示例的回调函数。。

  4)函数ngx_stream_proxy_handler逻辑

  对于下游客户端是在此功能中生成的,并连接到ngx_stream_upstream_t的结构。

  设置上游成员的ngx_stream_session_t结构。该上游成员是在启动过程中通过配置分析获得的。在分析过程中,连接了服务器和相应的上游。

  设置连接到Leate_socket的NGX_Connection_T结构的读取和写作事件的回调功能。

  在这一点上,这是第三次读取与侦听_socket连接的客户端对应的ngx_connection_t的读取事件恢复功能第三次更改。

  调用上游对等方的初始功能选择相应的上游服务器以选择相应的上游服务器。在我们的示例中,我们配置了默认的循环robin算法。

  设置完成后,请调用NGX_STREAM_PROXY_CONNECT连接上游服务器。

  5)函数ngx_stream_proxy_connect逻辑

  在函数ngx_stream_proxy_connect函数中,在get回调函数中调用ngx_stream_upstream_peer函数。该函数是上游模块的核心,以执行LoadElable。主要功能是选择最合适的上游服务器。

  获取上游服务器后,调用网络编程的API会创建插座并连接到上游服务器。在同时,将NGX_Connection_t分配给上游服务器的通信。该结构对应于Nginx和Upstream Server之间的连接。

  上游服务器连接的读取和写作事件的处理程序是ngx_udp_recv(ugx_udp_unix_recv)和ngx_send(ngx_unix_send)。

  将连接的读数和写作事件的处理程序功能设置为ngx_stream_proxy_connect_handler。

  当上游服务器具有读取事件时,将调用NGX_STREAM_PROXY_CONNECT_HANDLER。

  6)函数ngx_stream_proxy_connect_handler逻辑

  调用NGX_STREAM_PROXY_INIT_UPSTREAM函数以初始化与上游服务器的连接。这些包括设置与ngx_stream_upstreamdler对应的ngx_connection_t对应的读取和写作事件的恢复函数,对应于ngx_stream_upstreamdler,对应于读取和写作事件,对应于读和写作事件。

  调用NGX_STREAM_PROXY_PROCESS之间的数据代理以处理下游和上游服务器之间的数据。

  到目前为止,已经为下游客户端的连接建立了流模块,并连接到上游服务器。连接到两端的读取功能也设置为ngx_stream_proxy_downstream_handler和ngx_prox_proxy_proxy_upstream_handler。调用相应的功能。侧面的调用功能基本上是调用NGX_STREAM_PROXY_PROCESS_CONNECTION,然后调用NGX_STREAM_PROXY_PROCESS。

  当从一侧收到数据时,流模块将数据读取到缓冲区中,然后写入另一侧的写作缓冲区以发送。

  上面的代码过程分析是学习代码过程中的注释。文章更听话,更像是一篇文章,可以帮助您自己理解代码。希望帮助所有人。

  原始作者:Pipilu

  转载来源:NGINX开源社区