nginx的upstream模块数据转发过程及流量控制分析
2014-04-24 11:26
1106 查看
1.基本介绍
关于nginx的upstream模块的基本原理及设计,可参考点击打开链接。其实它就是一个特殊的handler模块,各种XX_proxy指令的set函数,会设置该location的content_handler,如XX_memcached_module的ngx_http_memcached_handler(),XX_proxy_module的ngx_http_proxy_handler()。可以简单地阅读一下这些代码,会发现它们几乎差不多1. 先创建一个upstream结构,简单的初始化;
2. 挂载一些hook函数,如create_request,reinit_request,process_header,finalize_request等(这种hook的实现方式,很好的统一了各种upstream模块的总体架构,只在具体协议相关的部分区别);
3. 调用ngx_http_upstream_init(r)来初始化上游连接。
其中,ngx_http_upstream_init()函数是一个关键,它会找到一个上游server(依据特定的算法),建立tcp连接,并为downstream、upstream两个连接设置read/write_handler,并加入到epoll中。这里有很多值得学习的地方,如寻找peer.connection的方法,非阻塞的建立tcp连接的方式等。到这里,整个content_handler就结束了,之后的事情完全由事件驱动。
2.工作流程
下面重点看一下之后的工作流程。一个比较大的文件传输,通常会需要多次epoll_wait来完成整个请求,如请求上游服务器中的一张图片(150K),工作过程如下:其中XX_upstream_process_upstream()是控制数据流转发的关键,它这要是调用ngx_event_pipe(),具体看这个函数
ngx_int_t ngx_event_pipe(ngx_event_pipe_t *p, ngx_int_t do_write) { u_int flags; ngx_int_t rc; ngx_event_t *rev, *wev; for ( ;; ) { //循环处理,从上游到下游转发数据 if (do_write) { p->log->action = "sending to client"; rc = ngx_event_pipe_write_to_downstream(p); if (rc == NGX_ABORT) { return NGX_ABORT; } //向downstream发不动了,那就也不用再从upstream读了 if (rc == NGX_BUSY) { return NGX_OK; } } p->read = 0; p->upstream_blocked = 0; p->log->action = "reading upstream"; if (ngx_event_pipe_read_upstream(p) == NGX_ABORT) { return NGX_ABORT; } /* 没读到数据,但若是因为p->upstream_blocked,即上游应用层读缓存不够了,那么还可以继续向下游写,从而释放上游的读缓存;但若不是因为这个,则可能是出现了错误、或出错了,则退出 */ if (!p->read && !p->upstream_blocked) { break; } do_write = 1; } if (p->upstream->fd != -1) { 继续添加读event到epoll中,并添加超时 } if (p->downstream->fd != -1 && p->downstream->data == p->output_ctx) { 同上 } return NGX_OK; }其中ngx_event_pipe_read_upstream(p)主体是一个for(;;)循环,调用ngx_readv_chain(c,chain)把上游数据读到应用层,再通过ngx_http_proxy_copy_filter(),过滤数据,并最终挂在p->in链上。
ngx_event_pipe_write_to_downstream(p)主体也是一个for(;;)循环,整合p->busy,p->out,p->in组成链out,调用ngx_http_top_body_filter(r,out),进入filter链,直到最后的ngx_http_write_filter,把数据发送给client,若来不及发,则把剩余的数据挂在r->out上。
3.数据流量
到这里,upstream基本的工作流程就清楚了。如前所述,可以看到在传输数据的过程中,数据的流量控制往往是导致过程复杂化的原因,并且由于要同时维护两个连接,尤其是后端up-server在一些特殊情况下(如阻塞)的行为很难预知,更要仔细地处理每种情况。下面以数据流量控制为契机,重新看数据的转化过程。数据流量的控制,涉及到tcp连接的双方,并且与底层协议大有关联,也会有很多问题,以后再不断看把。
相关文章推荐
- Nginx Upstream模块源码分析(上)
- nginx源码分析(2)——http模块的初始化过程
- 蔡军生先生第二人生的源码分析(二十七)发送数据的流量控制
- 蔡军生先生第二人生的源码分析(三十一)接收数据的流量控制
- 第二人生的源码分析(二十七)发送数据的流量控制
- 蔡军生先生第二人生的源码分析(三十一)接收数据的流量控制
- 第二人生的源码分析(三十一)接收数据的流量控制
- Nginx源码分析 - HTTP模块篇 - ngx_http_optimize_servers函数和TCP连接建立过程
- 第二人生的源码分析(二十七)发送数据的流量控制
- 第二人生的源码分析(三十一)接收数据的流量控制
- Hadoop源码分析:HDFS数据读写流量控制(DataTransferThrottler类)
- 第二人生的源码分析(二十七)发送数据的流量控制
- nginx源码分析(2)——http模块的初始化过程
- Nginx源码分析 - HTTP模块篇 - ngx_http_wait_request_handler函数和HTTP Request解析过程
- Nginx Upstream模块源码分析(上)
- Nginx之upstream模块和proxy模块简单应用
- spark高级数据分析---网络流量异常检测(升级实战)
- 用OpenCL实现HEVC中ME模块的测试数据分析
- Nginx源码分析-启动初始化过程(二)
- 嵌入式 vlc从接收到数据流到播放视频的过程分析(经典)