nginx upstream模块详解(处理流程篇一 upstream处理)

时间:2025-02-16 15:36:13
  • static void
  • ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
  • {
  • ...
  • rc = ngx_http_send_header(r); //发送头部数据到请求端
  • if (rc == NGX_ERROR || rc > NGX_OK || r->post_action) { //满足条件 由ngx_http_upstream_finalize_request处理
  • ngx_http_upstream_finalize_request(r, u, rc);
  • return;
  • }
  • u->header_sent = 1; //标记头部发送
  • if (u->upgrade) { //upgrage升级处理
  • ngx_http_upstream_upgrade(r, u);
  • return;
  • }
  • c = r->connection;
  • if (r->header_only) { //只有请求头
  • if (!u->buffering) { //不进行缓冲
  • ngx_http_upstream_finalize_request(r, u, rc);
  • return;
  • }
  • if (!u->cacheable && !u->store) { //不可缓存 并且不保存
  • ngx_http_upstream_finalize_request(r, u, rc);
  • return;
  • }
  • u->pipe->downstream_error = 1; //只有请求头部 便标记为downstream_error
  • }
  • if (r->request_body && r->request_body->temp_file) { //对在临时文件的请求包体进行清理
  • ngx_pool_run_cleanup_file(r->pool, r->request_body->temp_file->);
  • r->request_body->temp_file-> = NGX_INVALID_FILE;
  • }
  • clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
  • if (!u->buffering) { //不进行缓冲处理
  • if (u->input_filter == NULL) {
  • u->input_filter_init = ngx_http_upstream_non_buffered_filter_init;
  • u->input_filter = ngx_http_upstream_non_buffered_filter;
  • u->input_filter_ctx = r;
  • }
  • u->read_event_handler = ngx_http_upstream_process_non_buffered_upstream;
  • r->write_event_handler =
  • ngx_http_upstream_process_non_buffered_downstream;
  • r->limit_rate = 0;
  • if (u->input_filter_init(u->input_filter_ctx) == NGX_ERROR) {
  • ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  • return;
  • }
  • if (clcf->tcp_nodelay && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) { //设置tcp_nodelay
  • ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
  • tcp_nodelay = 1;
  • if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
  • (const void *) &tcp_nodelay, sizeof(int)) == -1)
  • {
  • ngx_connection_error(c, ngx_socket_errno,
  • "setsockopt(TCP_NODELAY) failed");
  • ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  • return;
  • }
  • c->tcp_nodelay = NGX_TCP_NODELAY_SET;
  • }
  • n = u-> - u->;
  • if (n) {
  • u-> = u->;
  • u->state->response_length += n;
  • if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR) {
  • ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  • return;
  • }
  • ngx_http_upstream_process_non_buffered_downstream(r);
  • } else {
  • u-> = u->;
  • u-> = u->;
  • if (ngx_http_send_special(r, NGX_HTTP_FLUSH) == NGX_ERROR) {
  • ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  • return;
  • }
  • if (u->->read->ready || u->length == 0) {
  • ngx_http_upstream_process_non_buffered_upstream(r, u);
  • }
  • }
  • return;
  • }
  • /* TODO: preallocate event_pipe bufs, look "Content-Length" */
  • #if (NGX_HTTP_CACHE)
  • if (r->cache && r->cache-> != NGX_INVALID_FILE) { //缓存文件无效 进行文件清理
  • ngx_pool_run_cleanup_file(r->pool, r->cache->);
  • r->cache-> = NGX_INVALID_FILE;
  • }
  • switch (ngx_http_test_predicates(r, u->conf->no_cache)) { //no_cache检测
  • case NGX_ERROR:
  • ngx_http_upstream_finalize_request(r, u, NGX_ERROR); //检测出错
  • return;
  • case NGX_DECLINED: //满足不缓存条件 设置不缓存标记
  • u->cacheable = 0;
  • break;
  • default: /* NGX_OK */
  • if (u->cache_status == NGX_HTTP_CACHE_BYPASS) { //可以进行缓存
  • /* create cache if previously bypassed */
  • if (ngx_http_file_cache_create(r) != NGX_OK) { //创建缓存文件
  • ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  • return;
  • }
  • }
  • break;
  • }
  • if (u->cacheable) {
  • time_t now, valid;
  • now = ngx_time();
  • valid = r->cache->valid_sec;
  • if (valid == 0) {
  • valid = ngx_http_file_cache_valid(u->conf->cache_valid,
  • u->headers_in.status_n); //获取缓存有效期
  • if (valid) {
  • r->cache->valid_sec = now + valid; //更新缓存有效期
  • }
  • }
  • if (valid) {
  • r->cache->date = now;
  • r->cache->body_start = (u_short) (u-> - u->); //body_start位置获取
  • if (u->headers_in.status_n == NGX_HTTP_OK
  • || u->headers_in.status_n == NGX_HTTP_PARTIAL_CONTENT) //缓存满足200/206状态值 必要参数更新
  • {
  • r->cache->last_modified = u->headers_in.last_modified_time; //更新缓存的last_modified_time值
  • if (u->headers_in.etag) { //更新缓存的etag值
  • r->cache->etag = u->headers_in.etag->value;
  • } else {
  • ngx_str_null(&r->cache->etag); //etag赋空值
  • }
  • } else {
  • r->cache->last_modified = -1;
  • ngx_str_null(&r->cache->etag);
  • }
  • if (ngx_http_file_cache_set_header(r, u->) != NGX_OK) { //设置缓存头部信息
  • ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  • return;
  • }
  • } else { //无valid_sec 即没有有效时间 不可缓存
  • u->cacheable = 0;
  • }
  • }
  • ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
  • "http cacheable: %d", u->cacheable);
  • if (u->cacheable == 0 && r->cache) { //临时文件清理
  • ngx_http_file_cache_free(r, u->pipe->temp_file);
  • }
  • if (r->header_only && !u->cacheable && !u->store) { //满足只有head请求或者body数据返回条件
  • ngx_http_upstream_finalize_request(r, u, 0);
  • return;
  • }
  • #endif //以下为event_pipe对上游服务器返回的包体处理
  • p = u->pipe;
  • p->output_filter = ngx_http_upstream_output_filter; //event_pipe对响应请求包体处理
  • p->output_ctx = r;
  • p->tag = u->;
  • p->bufs = u->conf->bufs;
  • p->busy_size = u->conf->busy_buffers_size;
  • p->upstream = u->;
  • p->downstream = c;
  • p->pool = r->pool;
  • p->log = c->log;
  • p->limit_rate = u->conf->limit_rate;
  • p->start_sec = ngx_time();
  • p->cacheable = u->cacheable || u->store; //传入upstream标记值
  • p->temp_file = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)); //创建临时文件 以用于缓存包体信息
  • if (p->temp_file == NULL) {
  • ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  • return;
  • }
  • p->temp_file-> = NGX_INVALID_FILE;
  • p->temp_file-> = c->log;
  • p->temp_file->path = u->conf->temp_path;
  • p->temp_file->pool = r->pool;
  • if (p->cacheable) {
  • p->temp_file->persistent = 1; //临时文件不会在close调用之后进行销毁
  • #if (NGX_HTTP_CACHE)
  • if (r->cache && r->cache->file_cache->temp_path) {
  • p->temp_file->path = r->cache->file_cache->temp_path; //传入临时文件目录
  • }
  • #endif
  • } else {
  • p->temp_file->log_level = NGX_LOG_WARN;
  • p->temp_file->warn = "an upstream response is buffered "
  • "to a temporary file";
  • }
  • p->max_temp_file_size = u->conf->max_temp_file_size; //传入临时文件配置的大小限制
  • p->temp_file_write_size = u->conf->temp_file_write_size;
  • #if (NGX_THREADS)
  • if (clcf->aio == NGX_HTTP_AIO_THREADS && clcf->aio_write) { //任务提交到线程池
  • p->thread_handler = ngx_http_upstream_thread_handler;
  • p->thread_ctx = r;
  • }
  • #endif
  • p->preread_bufs = ngx_alloc_chain_link(r->pool);
  • if (p->preread_bufs == NULL) {
  • ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  • return;
  • }
  • p->preread_bufs->buf = &u->buffer;
  • p->preread_bufs->next = NULL;
  • u-> = 1;
  • p->preread_size = u-> - u->;
  • if (u->cacheable) {
  • p->buf_to_file = ngx_calloc_buf(r->pool); //创建写入到文件的buffer缓冲
  • if (p->buf_to_file == NULL) {
  • ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  • return;
  • }
  • p->buf_to_file->start = u->;
  • p->buf_to_file->pos = u->;
  • p->buf_to_file->last = u->;
  • p->buf_to_file->temporary = 1;
  • }
  • if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
  • /* the posted aio operation may corrupt a shadow buffer */
  • p->single_buf = 1;
  • }
  • /* TODO: p->free_bufs = 0 if use ngx_create_chain_of_bufs() */
  • p->free_bufs = 1;
  • /*
  • * event_pipe would do u-> += p->preread_size
  • * as though these bytes were read
  • */
  • u-> = u->;
  • if (u->conf->cyclic_temp_file) { //临时文件复用标记
  • /*
  • * we need to disable the use of sendfile() if we use cyclic temp file
  • * because the writing a new data may interfere with sendfile()
  • * that uses the same kernel file pages (at least on FreeBSD)
  • */
  • p->cyclic_temp_file = 1;
  • c->sendfile = 0;
  • } else {
  • p->cyclic_temp_file = 0;
  • }
  • p->read_timeout = u->conf->read_timeout;
  • p->send_timeout = clcf->send_timeout;
  • p->send_lowat = clcf->send_lowat;
  • p->length = -1;
  • if (u->input_filter_init
  • && u->input_filter_init(p->input_ctx) != NGX_OK) //上游服务器返回包体filter初始化
  • {
  • ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  • return;
  • }
  • u->read_event_handler = ngx_http_upstream_process_upstream; //上游包体数据接收处理
  • r->write_event_handler = ngx_http_upstream_process_downstream; //下游包体数据传送处理
  • ngx_http_upstream_process_upstream(r, u); //上游包体处理
  • }