Nginx的stream模块提供了TCP负载均衡的功能,最初的stream模块比较简单,在nginx-1.11.4后也开始采用类似HTTP模块中分阶段处理请求的方式。
stream模块的处理阶段
在ngx_stream.h中定义了stream模块的7个阶段。如下面所示
与HTTP模块相同,每个阶段有相应的checker检查方法和handler回调方法,每个阶段都有零个或多个ngx_stream_phase_handler_t结构体。
stream模块接到请求后,初始化连接后调用ngx_stream_core_run_phases依次执行各个阶段的处理函数。
POST_ACCEPT、PREACCESS、ACCESS阶段
POST_ACCEPT、PREACCESS、ACCESS阶段的checker检查方法都是ngx_stream_core_generic_phase,这三个阶段主要进行访问控制的一些工作。因为stream模块处理TCP请求,阶段之间关系比较简单,将模块挂载在哪个阶段只会影响执行的顺序。
下面是ngx_stream_core_generic_phase函数
与HTTP模块类似,根据rc = ph->handler(s)
结果进行处理。
- rc为NGX_OK表示这一阶段的工作完成,进入下一个阶段
- rc为NGX_DECLINED表示进入下一个模块处理
- rc为NGX_AGAIN表示当前请求暂时无法完成,返回NGX_OK
- rc为NGX_DONE表示当前请求告一段落,会被再次调用,返回NGX_OK
- rc为NGX_ERROR表示出现错误,结束请求
- rc为其他值时表示处理完成,此时rc为状态码
注意,TCP请求中没有HTTP请求那样的状态码,这里的状态码只是表示连接处理的信息,如源超时状态码为502。
SSL阶段
SSL阶段的checker检查方法也是ngx_stream_core_generic_phase,这里挂载了ngx_stream_ssl_module,开启SSL时这里进行SSL握手的处理。
PREREAD阶段
这个阶段的特点是会读取下游的请求包体。读取后调用handler回调函数处理。读取的数据会保存在c->buffer中。如CONTENT阶段中ngx_stream_proxy_module在处理时会将c->buffer中的内容发送给上游源服务器。如果你在CONTENT阶段之前读取了下游的数据又想将这些数据通过proxy发送给上游,就可以加数据放到c->buffer中。
这里官方挂载了ngx_stream_ssl_preread_module模块,当TCP连接采用SSL通信时用这个模块可以解析client hello握手包,从extensions字段中得到server_name赋值给变量$ssl_preread_server_name中。这个模块只能在监听地址没有开启SSL,但是上下游却是通过SSL进行通信的情况下使用。
PREREAD阶段checker检查方法是ngx_stream_core_preread_phase。如下所示
CONTENT阶段
CONTENT阶段的检查方法是ngx_stream_core_content_phase
很显然这一阶段只能有一个处理方法,如进行TCP代理时需要ngx_stream_proxy_module,这里挂载的就是proxy模块的handler函数
LOG阶段
LOG阶段虽然是一个独立的阶段,却是在连接结束时调用的。在CONTENT阶段结束时就会调用ngx_stream_finalize_session结束请求。这部分在ngx_stream_handler.c中