http{}配置内
# 上游(后端)服务upstream http_backend { server 192.168.1.1:8080; server 192.168.1.2:8080; ... keepalive 16; check interval=5000 rise=1 fall=3 timeout=4000 default_down=false type=http; check_http_send "GET / HTTP/1.0/r/n/r/n";}server { listen 8080; location / { proxy_method GET; proxy_pass http://http_backend; proxy_http_version 1.1; proxy_set_header Connection ""; }}长连接配置:proxy默认是HTTP 1.0版本,需要手动设置1.1,并且由于proxy模块默认会把Header中的Connection填充close,所以也要手动覆盖一下,才能实现与upstream的长链接。keepalive
表示长链接队列的大小,LRU淘汰策略;状态检查:检查上游服务器健康状态,是nginx第三方库nginx_upstream_check_module提供的功能,interval
检查间隔(微秒ms),rise
检查成功次数后才认为该服务健康,fall
检查失败次数后才认为该服务异常,timeout
响应超时,default_down
设置初始后端服务状态(默认为失败状态),type
访问后端服务的协议。ngx_http_upstream()
,向ngx_http_upstream_main_conf_t.upstreams数组中增加(有判重)一个ngx_http_upstream_srv_conf_t对象,并收录server配置proxy_pass指令,ngx_http_proxy_pass()
,根据参数解析出host,通过ngx_http_upstream_add()
找到相应的ngx_http_upstream_srv_conf_t对象并关联到plcf->upstream->upstream负载均衡器初始化,ngx_http_upstream_keepalive_module
模块先初始化,设置初始化upstream的函数回调,在ngx_http_upstream_init_main_conf()
函数执行该回调,对每个upstream server产生peer对象,设置权重、超时、最大连接次数等,并设置了us->peer.init = ngx_http_upstream_init_round_robin_peer
,在每次请求时会被调用kcf->original_init_upstream = uscf->peer.init_upstream ? uscf->peer.init_upstream : ngx_http_upstream_init_round_robin;uscf->peer.init_upstream = ngx_http_upstream_init_keepalive;http headers初始化,proxy模块的ngx_http_proxy_merge_loc_conf
最后会对反向迭代转发的headers进地初始化,主要是收集ngx_http_proxy_headers和headers_source(这个变量保存了proxy_set_header指令设置的变量),收集http头的长度和内容,包括GET /uri和配置文件,比如$proxy_host为请求的host处理请求时进入handler环节,由于在与proxy_pass绑定的ngx_http_proxy_pass()
设置了clcf->handler = ngx_http_proxy_handler
,所以在NGX_HTTP_FIND_CONFIG_PHASE阶段的ngx_http_update_location_config()
最后会设置r->content_handler = clcf->handler
,接着在NGX_HTTP_CONTENT_PHASE阶段会执行r->content_handler(r)
,正式进入proxy_handler处理部分
调用链ngx_http_proxy_handler() ==> ngx_http_upstream_init() ==> ngx_http_upstream_init_request()
调用u->create_request(),实际调用ngx_http_proxy_create_request()
,生成请求的Header,先统计Header总长度,再填充buf调用uscf->peer.init(),实际调用ngx_http_upstream_init_keepalive_peer()
==> ngx_http_upstream_init_round_robin_peer()
,代码中tried是位图,用来标识在一轮选择中,各个后端服务器是否已经被选择过。该过程中注册了即将调用的get和free方法,平滑的加权轮询策略,参考 Nginx模块开发(十二)(续):upstream负载均衡 继续在ngx_http_upstream_init_request()
函数选中了后端服务器,进入函数ngx_http_upstream_connect()
展开ngx_http_upstream_send_request()
参考:nginx中upstream的设计和实现(二)
ngx_http_upstream_process_header()
为处理后端服务的读函数,从upstream读取数据,并发送给client
ngx_http_upstream_ignore_header_line()
ngx_http_upstream_send_response(),发送数据client ngx_http_send_header(),发送Header,进入ngx_http_top_header_filter
的调用链,最后到达ngx_http_header_filter()
计算headers的字符串长度,包括status、内置header(Server、Date、Content-Type、Content-Length、Last-Modified、Connection等)、r->headers_out收集的header申请buf,将status、内置header、r->headers_out拷贝到buf中调用ngx_http_write_filter()发送数据ngx_http_upstream_process_upstream(),初始化pipe,记录upstream和downstream ngx_event_pipe() ngx_event_pipe_read_upstream(),接收数据:p->preread_bufs如果还有空间则先用该buf接收数据,然后若p->free_raw_bufs非空则使用该buf,否则ngx_create_temp_buf生成新buf,供数据接收使用 调用p->upstream->recv_chain(),实际为调用ngx_readv_chain(),这是在ngx_event_connect_peer()函数中设置的upstream(这里的upstream为ngx_connection_t)调用p->input_filter(),实际为调用ngx_http_proxy_copy_filter(),对接收到的数据进行操作,该函数在ngx_http_proxy_handler()进行的挂载上个函数执行完会把do_write=1,再次循环时会进入ngx_event_pipe_write_to_downstream()分支,将数据发送给client 调用p->output_filter(),实际为调用ngx_http_output_filter(),**,该函数在设置pipe时的ngx_http_upstream_send_response()进行的挂载 调用ngx_http_top_body_filter(),实际为调用ngx_http_range_body_filter(),无实现操作,接着调用ngx_http_copy_filter(),执行ngx_output_chain(),调用ctx->output_filter(),实际为调用ngx_http_charset_body_filter(),经过一系列filter函数后,进入ngx_http_write_filter()
函数 调用c->send_chain(),实际调用ngx_linux_sendfile_chain()函数,发送chain buffer接着分析ngx_http_write_filter()
c->send_chain = ngx_send_chain
,而宏定义了#define ngx_send_chain ngx_io.send_chain
,extern ngx_os_io_t ngx_io
,其中ngx_os_io_t是ngx_linux_init.c文件中定义的结构体,封装了linux下高级的socket函数新闻热点
疑难解答