当前位置:K88软件开发文章中心网站服务器框架nginx → 文章内容

Nginx upstream 模块简介

减小字体 增大字体 作者:佚名  来源:网上搜集  发布时间:2019-1-23 14:28:58

odule); u->input_filter_ctx = ctx;完成 upstream 初始化并进行收尾工作。 r->main->count++; ngx_http_upstream_init(r); return NGX_DONE;任何 upstream 模块,简单如 memcached,复杂如 proxy、fastcgi 都是如此。不同的 upstream 模块在这 6 步中的最大差别会出现在第 2、3、4、5 上。其中第 2、4 两步很容易理解,不同的模块设置的标志和使用的回调函数肯定不同。第 5 步也不难理解,只有第3步是最为晦涩的,不同的模块在取得后端服务器列表时,策略的差异非常大,有如 memcached 这样简单明了的,也有如 proxy 那样逻辑复杂的。这个问题先记下来,等把memcached剖析清楚了,再单独讨论。第 6 步是一个常态。将 count 加 1,然后返回 NGX_DONE。Nginx 遇到这种情况,虽然会认为当前请求的处理已经结束,但是不会释放请求使用的内存资源,也不会关闭与客户端的连接。之所以需要这样,是因为 Nginx 建立了 upstream 请求和客户端请求之间一对一的关系,在后续使用 ngx_event_pipe 将 upstream 响应发送回客户端时,还要使用到这些保存着客户端信息的数据结构。这部分会在后面的原理篇做具体介绍,这里不再展开。将 upstream 请求和客户端请求进行一对一绑定,这个设计有优势也有缺陷。优势就是简化模块开发,可以将精力集中在模块逻辑上,而缺陷同样明显,一对一的设计很多时候都不能满足复杂逻辑的需要。对于这一点,将会在后面的原理篇来阐述。回调函数前面剖析了 memcached 模块的骨架,现在开始逐个解决每个回调函数。ngx_http_memcached_create_request:很简单的按照设置的内容生成一个 key,接着生成一个“get $key”的请求,放在 r->upstream->request_bufs 里面。ngx_http_memcached_reinit_request:无需初始化。ngx_http_memcached_abort_request:无需额外操作。ngx_http_memcached_finalize_request:无需额外操作。ngx_http_memcached_process_header:模块的业务重点函数。memcache 协议的头部信息被定义为第一行文本,可以找到这段代码证明: for (p = u->buffer.pos; p < u->buffer.last; p++) { if ( * p == LF) { goto found; }如果在已读入缓冲的数据中没有发现 LF('\n')字符,函数返回 NGX_AGAIN,表示头部未完全读入,需要继续读取数据。Nginx 在收到新的数据以后会再次调用该函数。Nginx 处理后端服务器的响应头时只会使用一块缓存,所有数据都在这块缓存中,所以解析头部信息时不需要考虑头部信息跨越多块缓存的情况。而如果头部过大,不能保存在这块缓存中,Nginx 会返回错误信息给客户端,并记录 error log,提示缓存不够大。process_header 的重要职责是将后端服务器返回的状态翻译成返回给客户端的状态。例如,在 ngx_http_memcached_process_header 中,有这样几段代码: r->headers_out.content_length_n = ngx_atoof(len, p - len - 1); u->headers_in.status_n = 200; u->state->status = 200; u->headers_in.status_n = 404; u->state->status = 404;u->state 用于计算 upstream 相关的变量。比如 u->state->status 将被用于计算变量“upstream_status”的值。u->headers_in 将被作为返回给客户端的响应返回状态码。而第一行则是设置返回给客户端的响应的长度。在这个函数中不能忘记的一件事情是处理完头部信息以后需要将读指针 pos 后移,否则这段数据也将被复制到返回给客户端的响应的正文中,进而导致正文内容不正确。 u->buffer.pos = p + 1;process_header 函数完成响应头的正确处理,应该返回 NGX_OK。如果返回 NGX_AGAIN,表示未读取完整数据,需要从后端服务器继续读取数据。返回 NGX_DECLINED 无意义,其他任何返回值都被认为是出错状态,Nginx 将结束 upstream 请求并返回错误信息。ngx_http_memcached_filter_init:修正从后端服务器收到的内容长度。因为在处理 header 时没有加上这部分长度。ngx_http_memcached_filter:memcached 模块是少有的带有处理正文的回调函数的模块。因为 memcached 模块需要过滤正文末尾 CRLF "END" CRLF,所以实现了自己的 filter 回调函数。处理正文的实际意义是将从后端服务器收到的正文有效内容封装成 ngx_chain_t,并加在 u->out_bufs 末尾。Nginx 并不进行数据拷贝,而是建立 ngx_buf_t 数据结构指向这些数据内存区,然后由 ngx_chain_t 组织这些 buf。这种实现避免了内存大量搬迁,也是 Nginx 高效的奥秘之一。本节回顾这一节介绍了 upstream 模块的基本组成。upstream 模块是从 handler 模块发展而来,指令系统和模块生效方式与 handler 模块无异。不同之处在于,upstream 模块在 handler 函数中设置众多回调函数。实际工作都是由这些回调函数完成的。每个回调函数都是在 upstream 的某个固定阶段执行,各司其职,大部分回调函数一般不会真正用到。upstream 最重要的回调函数是 create_request、process_header 和 input_filter,他们共同实现了与后端服务器的协议的解析部分。

上一页  [1] [2] 


Nginx upstream 模块简介