NGINX UPSTREAM

   Upstream主要用来实现webserver和后台服务器的进行通信; 接受来自client的请求,创建一个upstream连接到后台服务器,并将client请求转发给后台服务器; 接受后台服务器的响应,并构造响应给client.

   Upstream主要是在NGINX的NGX_HTTP_CONTENT_PHASE执行的,即在ngx_http_core_content_phase中,如果r->content_handler不为NULL,则执行这个r->content_handler,这个content_handler一般就是upstream类模块的处理接口;

  在upstream类模块的处理接口中一般会先注册模块的各种处理接口,下面以FASTCGI为例来说明:

    u->create_request = ngx_http_fastcgi_create_request;
    u->reinit_request = ngx_http_fastcgi_reinit_request;
    u->process_header = ngx_http_fastcgi_process_header;
    u->abort_request = ngx_http_fastcgi_abort_request;
    u->finalize_request = ngx_http_fastcgi_finalize_request;

   

ngx_http_fastcgi_create_request:

这个接口主要是从client的http请求中读取数据并按照FASTCGI的协议要求,将数据组装成FASTCGI的数据包;

ngx_http_fastcgi_reinit_request

这个是重新初始化到后端upstream的请求,主要是重新初始化context

ngx_http_fastcgi_process_header

这个接口主要是处理upstream响应的消息;

ngx_http_fastcgi_finalize_request

request(和后端upstream)结束,需要释放资源


以fastcgi为例说明upstream的处理流程:

在NGX_HTTP_CONTENT_PHASE阶段,如果clcf->handler不为空的调用handler:

1. ngx_http_fastcgi_handler:

这个处理接口主要是创建upstream,并初始化upstream:

   u->create_request = ngx_http_fastcgi_create_request;
    u->reinit_request = ngx_http_fastcgi_reinit_request;
    u->process_header = ngx_http_fastcgi_process_header;
    u->abort_request = ngx_http_fastcgi_abort_request;
    u->finalize_request = ngx_http_fastcgi_finalize_request;

   u->pipe->input_filter = ngx_http_fastcgi_input_filter;

   u->input_filter_init = ngx_http_fastcgi_input_filter_init;

  . . .

2. 然后读取HTTP请求的request body(ngx_http_read_client_request_body)部分(如果有则读取,如果一次读不完,则分多次读取直到读完位置,根据配置还有body的大小决定是否写入临时文件)

3. 读取body后调用upstream的初始化接口ngx_http_upstream_init: 

这个接口主要是,如果是边缘触发的事件处理方式(NGX_USE_CLEAR_EVENT),则挂载写事件处理接口(和client的接口), 然后才真正初始化upstream;

4. ngx_http_upstream_init_request接口主要调用 u->create_request接口创建发送的upstream的消息(创建的消息保存在upstream->request_bufs);并设置upstream的一些属性, 如本地地址,发送的output filter. 然后根据upstream的地址建立和upstream的连接(在这个过程中,可以根据选择upstream的策略来选择upstream,如果upstream的地址还没有解析,则解析upstream的地址)

5. 建立和upstream的连接,在连接的接口上挂载upstream的读写(c->write->handler, c->read->handler)接口ngx_http_upstream_handler; 以及upstream的处理接口:写接口ngx_http_upstream_send_request_handler(u->write_event_handler); 读接口ngx_http_upstream_process_header(u->read_event_handler); 并将request body挂接到                  u->output.free上; 调用upstream接口ngx_http_upstream_send_request将数据发送到UPSTREAM.

6. ngx_http_upstream_send_request先调用ngx_output_chain将u->request_bufs(即将要发送到upstream的数据)保存到u->output.in的chain上(output主要是保存发送的upstream的数据结构:ngx_output_chain_add_copy); 判断是否需要将u->output.in中各个节点的内存拷贝到u->output.buf中,如果需要拷贝,则调用ngx_output_chain_copy_buf将节点上的内存拷贝到u->output.buf中. 将所有需要发送的节点链到out链上调用ctx->output_filter(ngx_chain_writer)发送到upstream. 最后根据发送情况更新output的各个域.

7. 如果数据没有发送完,则挂载写事件,等待可以发送数据事件继续发送. 如果发送完数据后,就开始准备读取upstream响应的头部: 如果可以读了就直接调用ngx_http_upstream_process_header读取头部. 否则将upstream的写接口u->write_event_handler 设为ngx_http_upstream_dummy_handler,在这种情况即使有写事件发生,也不会发送数据到upstream. 然后这个过程结束等待upstream返回响应数据.

8.  当收到upstream响应后,触发读事件 ngx_http_upstream_handler->ngx_http_upstream_process_header: 这个接口从socket读取数据到upstream->buffer中, 并调用u->process_header: ngx_http_fastcgi_process_header来处理upstream返回来的头部数据; ngx_http_fastcgi_process_header主要是分析fastcgi消息的头部信息,并将信息保存到ngx_http_fastcgi_ctx_t中; 这个接口还处理fastcgi返回HTTP头部信息,并将解析处理的域保存到u->headers_in中.

9. 处理完解析upstream发过来的头部后, 然后调用ngx_http_upstream_process_headers来处理头域中的一些特殊头部域:如哪些需要隐藏不发送个client等等.并将u->headers_in中的头域拷贝到r->headers_out中用于头部发送给client.

10.  最后调用ngx_http_upstream_send_response将消息发送给client. 这个接口首先调用ngx_http_send_header将头部信息发送给client. 接下来处理body的数据,处理body的分两种情况,即是否需要buffering,这个标记的含义就是nginx是否会尽可能多的读取upstream的数据;如果关闭,则就是一个同步的发送,也就是接收多少,发送给客户端多少.默认这个是打开的.也就是nginx会buf住upstream发送的数据.

  A): 如果是no buffering的情况,upstream的读接口改为ngx_http_upstream_process_non_buffered_upstream;r的写接口改为ngx_http_upstream_process_non_buffered_downstream;这两个接口的作用是从upstream读取body数据后直接发送给client. 首先调用u->input_filter( ngx_http_upstream_non_buffered_filter)将upstream->buffer挂到upstream->out_bufs下,调用ngx_http_upstream_process_non_buffered_downstream将数据发送给client.

 B): 如果是buffering的情况, 首先设置号u->pipe属性,将p->output_filter设置为ngx_http_output_filter,将upstream读事件处理接口设置为ngx_http_upstream_process_upstream(u->read_event_handler);将request的写接口设置为ngx_http_upstream_process_downstream(r->write_event_handler). 然后调用ngx_http_upstream_process_upstream读取upstream来的数据.

11.  ngx_http_upstream_process_upstream主要调用ngx_event_pipe来处理upstream和client之间的数据交换(从upstream读取数据,处理,发送到client). ngx_event_pipe在有数据写的时候调用ngx_event_pipe_write_to_downstream将数据发送到client, 否则调用ngx_event_pipe_read_upstream读取upstream发过来的数据. 处理上述的阶段任务后,根据read和write的状态决定安装还是删除这些接口.

12. ngx_event_pipe_read_upstream:这个函数首先找到一个空闲的chain(根据一定的优先顺序来得到,在一些条件下要将buffer写入到临时文件中[如cacheable, 临时文件还没写满]);然后从upstream的socket接口读取数据到空闲的chain中; 读取数据后将chain挂到free_raw_bufs的头部; 并表示已经读取了数据(p->read = 1); 更新pipe下面的一下域,开始遍历chain对读取的数据进行处理,主要是调用具体upstream注册的p->input_filter对收到的数据进行处理,p->input_filter会将处理后的数据挂到p->in下面. 如果在cacheable打开的情况下,需要将收到的数据写到temp file中去.

13. ngx_event_pipe_write_to_downstream: 如果和upstream已经断开或者upstream的数据已经发送完毕, 则将p->out和p->in上的数据调用output_filter(ngx_http_output_filter)将数据发送到client.  如果upstream数据还没有发送完毕, nginx会尽量发送最大(即配置文件中配置的xxx_buffer_size)的可能的数据到client(即从p->out和p->in中取尽量多的数据来发送).

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值