一会儿改

来源:互联网 发布:食品经营许可网络平台 编辑:程序博客网 时间:2024/04/29 20:52
/* nginx 就是靠 ngx_http_core_run_phases, ngx_http_finalize_request, 还有所有 
 * phase 的 checker 的逻辑支撑起来的, 他们三者的逻辑组合支撑了 nginx http 核心
 * 的状态变迁, 所有的 module 都是在逻辑规则的范围内施展自己的想象力.
 * 其中, ngx_http_finalize_request 的逻辑是最复杂的, 要细细的把所有细节列出来
 */


/* 接受的 rc 值:
 * NGX_DONE
 * NGX_OK
 * NGX_DECLINED
 * NGX_ERROR, NGX_HTTP_BAD_REQUEST, NGX_HTTP_CLIENT_CLOSED_REQUEST
 * NGX_HTTP_SPECIAL_RESPONSE(300)以上, NGX_HTTP_CREATED,NGX_HTTP_NO_CONTENT
 * NGX_HTTP_CLOSE
 */


/* r 的 write_event_handler 可能有的值是:
 *  ngx_http_core_run_phases; 他只会在 ngx_http_handler 和 ngx_http_finalize_request 中被设置. 表示来一遍 phase.(有别于 writer, writer是继续给数据, 即相当于接手 content phase 的后续工作)
 *  ngx_http_handler; 就是子状态机的入口. 将 write_event_handler 定位至 
 *  ngx_http_core_run_phases. 在生成子请求的时候, 也会把新生成的请求子状态 
 *  入口设为 ngx_http_handler. 当 wev 可写时间来, ngx_http_request_handler 
 *    最后执行 ngx_http_run_posted_requests, 进入的就是子请求入口. 
 *  ngx_http_request_empty_handler; 此状态下什么都不干. 在不需要响应 wev 的时
 *  候就把状态设为此函数. 如果有 content_handler, 那么 write_event_handler
 *  为空. 在 finalize_request 中请求真正完成的时候; http_writer 真正写完的
 *  时候; 在 keepalive 重新初始化的时候.
 *  ngx_http_request_finalizer; 在 finalize_request 中的两个情况下被设置, 表示
 *    一旦再有一个 w 事件, 则以 0 为参数再次 finalize_request
 *  ngx_http_terminate_handler; 一旦再有 w 事件, 则确信无疑的关闭连接
 *  ngx_http_writer; 持续调用 ngx_http_output_filter, 直到 buffer 为空.
 */


/* r 的 read_event_handler 可能有的值是:
 *  ngx_http_block_reading; 此状态下拒绝读事件, 即暂时屏蔽 r 事件.
 *  ngx_http_discarded_request_body_handler;
 *  ngx_http_read_client_request_body_handler; 这个最终是通过 ngx_http_proxy_handler *  设置上的, 也就是说 GET 带 body 的 nginx 最简版本是没有的, 全靠 proxy module.
 *  ngx_http_request_empty_handler; 黑洞状态
 *  ngx_http_test_reading; 因为 nginx 没有 error 事件, nginx 把 error 打包成
 *    in|out. 这个状态相当于测试连接状态. 在 ngx_http_set_write_handler 的时候
 *    被设置, 即开始靠写回调 write_event_handler 来处理错误, 一旦写回调第一次
 *    调用后. 可能下一次再用不会回调了, 因此需要在这之前把读回调挂上, 用
 *  read_event_handler 处理错误.
 */


/* rev 可以的回调用
 * ngx_event_accept
 * ngx_event_acceptex
 * ngx_event_busy_lock_posted_handler
 * ngx_http_init_request
 * ngx_http_keepalive_handler 
 * ngx_http_lingering_close_handler  这个暂时可以不考虑.配置文件指定的,完全可以不配
 * ngx_http_process_request_headers
 * ngx_http_process_request_line
 * ngx_http_request_handler
 * ngx_http_ssl_handshake
 * ngx_http_upstream_handler
 * ngx_resolver_read_response
 * 有个不固定的 rev handler, 是: ngx_add_channel_event 函数可指定 rev 的 handler
 */


/* wev 可以的回调有(wev 回调都在 http/upstream 层设置):
 * ngx_http_upstream_handler
 * ngx_http_empty_handler
 * ngx_http_request_handler
 * 其回调在 ngx_http_copy_filter_module 中被调用, 剩下都是在 epoll 判断可写后的回调.
 * 回调必然是三种之一. 而其中最重要的 ngx_http_request_handler 就是交替执行 
 * r->read/write_event_handler, 即让 epoll 绕过 c, 直接驱动 r 的逻辑状态迁移. 
 * 也就是说一旦出了 r 层, wev 就没啥意义了. 直接无视.
 */


/* 在 r 构成前, 原始驱动是各种 ev, 他们的上下文是 c. (rev,wev)pair表示了一个状态.
 * rev 上下文主要缓冲区 r->header_in(ngx_buf_t), 并设置读到的头.
 * ngx_http_keepalive_handler 本质也是继续读缓冲没区别. 当 r 构造完之后, 对 rev
 * 的驱动转换为对 read_event_handler 的驱动. 即相当于 rev 的上下文是 c, 在这层
 * 状态机完成对 r 的构造. 然后在状态 ngx_http_request_handler 以 r 作为上下文,
 * 进入子状态机的循环(即对于上层状态机停在这个状态自循环).
 * 对于 wev 则一直是 empty_handler, 一旦上下文 r 具备, 则直接在 
 * ngx_http_request_handler 开始循环. 即二者在这个状态是统一的.
 *
 * 在子状态下, 驱动还是 ev(上层只转发未新建), 但是经过上层包装, ev 驱动
 * read_event_handler 和 write_event_handler .上下文变为 r.
 * 且主要是 r 的 in out chain. r 中其余内容本质上都是控制变量, 用以调整 chain.
 *
 * ngx_http_finalize_request 复杂之处在于他是同时穿越子状态机和父状态机. 即
 * 完成子状态机的终止态后可能跳出来继续完成父状态机的终止态.
 *
 * 注: 一旦进入 r 层后, 虽然 (rev, wev) pair 表示一个状态, 但 read_event_handler
 * 和 write_event_handler 是交替运行, 且只有 write_event_handler 不可写的时候
 * read_event_handler 才会被调用. 即 ngx_http_request_handler 状态下对事件的响应
 * 是串行的, 一个输入一个响应.
 */


/* 上面 r 级别与 c 级别的所有回调组成了一个 http 生命周期的状态集合
 * ngx_http_finalize_request 是重要的 r 级状态和上下文调整函数, 也是
 * 从 r 状态机跳转至 c 状态机的出口. 其主要逻辑如下:
 * 1 减少 r->main 引用计数
 * 2 关掉连接或设置状态linger关闭或者 keepalive 处理下一个 main 请求. 
 * finalize_connection 就是干这个的.
 * 3 设置状态使其重走 8 个 phase
 * 4 处理 error, 关掉连接
 * 5 递归处理 ngx_http_special_response_handler 返回的值. 其实也就是其他
 *   几种情况之一
 * 6 如果 r 数据未输出完或 r 需要等待数据(postponed/blocked), 则调整其状态于
 *   ngx_http_writer, 直到数据完成或失败再迁移至其他状态.
 * 7 协助完成子请求的更新.
 * 
 * ngx_http_finalize_request 用来调节状态和上下文, 不作为状态(request_finalizer
 * 才是). 对 ngx_http_finalize_request 的使用可以非常灵活. 像对于 static
 * module, 请求一开始处理之后马上 ngx_http_finalize_request, 剩下的事交给
 * ngx_http_writer 办; 而对于 stream content module, 则可以反复的使用 NGX_DECLINED
 * 调用, 以便不断的走 8 个 phase. 某个 moudle 调用 ngx_http_finalize_request 表示:
 * 我已经把能提供的都提供了, 剩下的事情依靠 finalize_request 的逻辑即可完成
 */


/* 当加上 upstream 之后, 状态复杂度进一步增加了, upstream 再次新增了一个子状态:
 * u. 包括 u->read_event_handler 和 u->write_event_handler. 由子状态
 * ngx_http_upstream_handler 作为子状态的入口(回调的参数是 ngx_event_t).
 * 而 u 的 read/write_event_handler 会不断的自我调整, 还会调整 r 的
 * read/write_event_handler, 以便与 r 和 c 的最终 chain 处理结合起来. 
 * (empty_handler 是一直被大量使用, 这个状态设计的不够好)
 * 子状态机的初始化: 
 * 在第一次 content phase 时, 把控制权交给 ngx_http_proxy_handler, 那么
 * ngx_http_proxy_handler 在第一次执行时, 无论出现什么情况, 都要完成子状态
 * 机的构造. 对于其他 upstream, 可能是 ngx_http_memcached_handler 等.
 * 当然实际上 nginx 子状态的构造是 ngx_http_upstream_init 完成的.
 * 
 * 首先看 r->read_event_handler 新增的状态:
 * ngx_http_upstream_rd_check_broken_connection: 在构造了 request 之后, 将 
 * r->read/write_event_handler 绑定进入此状态. 然后才发起对 up 的连接
 *
 * connection 部分新增:
 * 对于 up 一端, c 新增了一个 read/write 状态 ngx_http_upstream_handler
 * 作用和 down 端的 c, 差不多, down 端的 ngx_http_request_handler不断执行 
 * r->read/write_event_handler, up 端的是执行 u->read/write_event_handler
 * 
 *
 * r->write_event_handler 新增:
 * ngx_http_upstream_init_request: 
 * ngx_http_upstream_wr_check_broken_connection: 
 * ngx_http_upstream_process_downstream:
 * ngx_http_upstream_process_non_buffered_downstream: 在收到 up 的完整响应头
 * 之后, 将 r 绑定至此状态(no buffer情况下).
 *
 * u->read_event_handler 状态:
 * ngx_http_upstream_process_header: connection up 后马上(不脱离当前函数,
 *  可认为是事务, 以抢在下一次 event 回调之前)绑定. 该状态一旦判定 header 接收完毕
 *  则使用重要函数 ngx_http_upstream_send_response 完成传输状态的构造.
 * ngx_http_upstream_process_body_in_memory: 与子请求有关
 * ngx_http_upstream_process_non_buffered_upstream: 在收到 up 的完整响应头
 *  之后, 将 r 绑定至此状态(no buffer情况下).
 * ngx_http_upstream_process_upstream: 上面状态的 buffer 版本
 *
 * u->write_event_handler 状态:
 * ngx_http_upstream_send_request_handler: connect up 后马上(不脱离当前函数,
 *  可认为是事务, 以抢在下一次 event 回调之前)绑定.
 * ngx_http_upstream_dummy_handler: 纯打印日志, 在send request成功后 write
 *  就进入此状态
 */
原创粉丝点击