typedef struct ngx_http_upstream_s ngx_http_upstream_t;
struct ngx_http_upstream_s {
// 处理读事件的回调函数
ngx_http_upstream_handler_pt read_event_handler;
// 处理写事件的回调函数
ngx_http_upstream_handler_pt write_event_handler;
// 主动向上游服务器发起的连接
ngx_peer_connection_t peer;
/* 当向下游服务器转发响应时,如果打开了缓存且认为上游网速更快,
则会使用pipe成员来转发响应。这时,pipe必须由HTTP模块事先构造。 */
ngx_event_pipe_t *pipe;
ngx_chain_t *request_bufs;
// 定义了向下游发送响应的方式
ngx_output_chain_ctx_t output;
ngx_chain_writer_ctx_t writer;
// 使用upstream机制时的各种配置
ngx_http_upstream_conf_t *conf;
#if (NGX_HTTP_CACHE)
ngx_array_t *caches;
#endif
/* 希望upstream直接转发响应,就需要在process_header函数中将解析出来的
响应头部适配为HTTP的响应头部,同时需要把包头中的信息设置到header_in结构体中 */
ngx_http_upstream_headers_in_t headers_in;
// 用于解析主机域名
ngx_http_upstream_resolved_t *resolved;
ngx_buf_t from_client;
/* 接收上游服务器响应包头的缓冲区,在不需要把响应直接转发给客户端,或者buffering标志位
为0的情况下转发包体,接收包体的缓冲区仍然使用buffer */
ngx_buf_t buffer;
// 表示来自上游服务器的响应包体的长度
off_t length;
/* 视两种情况而定:
1. 当不需要转发包体,且使用默认的input_filter方法处理包体时,out_bufs指向响应包体;
2. 当需要转发包体到下游时,这个链表指向上一次下游转发响应到现在这段时间内接收自上游的缓存响应;
*/
ngx_chain_t *out_bufs;
/* 当需要转发响应包体到下游时,它表示上一次向下游转发响应时没有发送完的内容 */
ngx_chain_t *busy_bufs;
// 用于回收out_bufs中已经发送给下游的ngx_buf_t结构体
ngx_chain_t *free_bufs;
// 处理包体前的初始化方法
ngx_int_t (*input_filter_init)(void *data);
// 处理包体的方法
ngx_int_t (*input_filter)(void *data, ssize_t bytes);
// 用于传递HTTP模块自定义的数据结构,在上述的两个函数中作为参数传递
void *input_filter_ctx;
#if (NGX_HTTP_CACHE)
ngx_int_t (*create_key)(ngx_http_request_t *r);
#endif
// HTTP模块实现,用于构造发往上游服务器的请求的函数
ngx_int_t (*create_request)(ngx_http_request_t *r);
// 与上游服务器通信失败后,重新发起连接
ngx_int_t (*reinit_request)(ngx_http_request_t *r);
// 解析上游服务器返回响应的包头
ngx_int_t (*process_header)(ngx_http_request_t *r);
void (*abort_request)(ngx_http_request_t *r);
// 请求结束时调用
void (*finalize_request)(ngx_http_request_t *r,
ngx_int_t rc);
// 可由HTTP模块实现的重定向函数
ngx_int_t (*rewrite_redirect)(ngx_http_request_t *r,
ngx_table_elt_t *h, size_t prefix);
ngx_int_t (*rewrite_cookie)(ngx_http_request_t *r,
ngx_table_elt_t *h);
ngx_msec_t timeout;
// 上游响应的错误码、包体长度等信息
ngx_http_upstream_state_t *state;
// 使用文件缓存时有用
ngx_str_t method;
// 日志记录时有用
ngx_str_t schema;
ngx_str_t uri;
#if (NGX_HTTP_SSL)
ngx_str_t ssl_name;
#endif
// 暂时相当于一个表示是否清理资源的标志位
ngx_http_cleanup_pt *cleanup;
// 是否指定缓存路径
unsigned store:1;
// 是否启用文件缓存
unsigned cacheable:1;
unsigned accel:1;
// 是否基于SSL协议访问上游服务器
unsigned ssl:1;
#if (NGX_HTTP_CACHE)
unsigned cache_status:3;
#endif
// 向下游转发上游包体时,是否开启更大的内存及临时磁盘文件用于缓存
unsigned buffering:1;
unsigned keepalive:1;
unsigned upgrade:1;
// 表示是否已经向上游服务器发送了请求
unsigned request_sent:1;
// 表示是否把包头转发给客户端
unsigned header_sent:1;
};
这个结构体指定了upstream的运行方式。它必须在启动upstream机制前设置。
typedef struct {
/* 当ngx_http_upstream_t中没有实现resolved成员时,这个变量才会生效,
用来定义上游服务器的配置 */
ngx_http_upstream_srv_conf_t *upstream;
// 建立TCP连接的超时时间,实际上就是写事件添加到定时器中时设置的超时时间
ngx_msec_t connect_timeout;
// 发送请求超时时间,通常是写事件添加的定时器中设置的超时时间
ngx_msec_t send_timeout;
// 接收响应的超时时间,通常是读事件添加的定时器中设置的超时时间
ngx_msec_t read_timeout;
ngx_msec_t timeout;
ngx_msec_t next_upstream_timeout;
// TCP的SO_SNOLOWAT选项,表示发送缓冲区的下限
size_t send_lowat;
// 定义了接收头部的缓冲区大小(ngx_http_upstream_t中的buffer缓冲区)
size_t buffer_size;
size_t limit_rate;
// 当buffering=1,并且向下游转发响应时生效
size_t busy_buffers_size;
// buffering=1,若上游速度快于下游,则可能把上游的响应存在临时文件中的临时文件大小
size_t max_temp_file_size;
// 一次写入临时文件的字符流最大长度
size_t temp_file_write_size;
size_t busy_buffers_size_conf;
size_t max_temp_file_size_conf;
size_t temp_file_write_size_conf;
// 以缓存响应的方式转发上游服务器的包体时所用的内存大小
ngx_bufs_t bufs;
// 针对ngx_http_upstream_t中的header_in成员,ignore_headers可根据位操作跳过一些头部
ngx_uint_t ignore_headers;
// 以二进制来表示一些错误码,会根据这些错误码重新选择新的上游服务器
ngx_uint_t next_upstream;
// 表示创建的目录、文件的权限
ngx_uint_t store_access;
ngx_uint_t next_upstream_tries;
/* 决定转发响应方式的标志位
1:认为上游快于下游,会尽量地在内存或者磁盘中缓存来自上游的响应;
0:仅开辟一块固定大小的内存块作为缓存来转发响应 */
ngx_flag_t buffering;
ngx_flag_t request_buffering;
ngx_flag_t pass_request_headers;
ngx_flag_t pass_request_body;
// 1:上游服务器交互时不检查是否与下游客户端断开连接,继续执行交互内容
ngx_flag_t ignore_client_abort;
// 截取错误码,查看是否有对应可以返回的语义
ngx_flag_t intercept_errors;
// 1:试图复用临时文件中已经使用过的空间
ngx_flag_t cyclic_temp_file;
ngx_flag_t force_ranges;
// 存放临时文件的路径
ngx_path_t *temp_path;
// 根据ngx_http_upstream_hide_headers_hash函数构造出的需要隐藏的HTTP头部散列表
ngx_hash_t hide_headers_hash;
// 不希望转发的头部
ngx_array_t *hide_headers;
// 明确希望转发的头部
ngx_array_t *pass_headers;
// 连接上游服务器时的本机地址
ngx_http_upstream_local_t *local;
#if (NGX_HTTP_CACHE)
ngx_shm_zone_t *cache_zone;
ngx_http_complex_value_t *cache_value;
ngx_uint_t cache_min_uses;
ngx_uint_t cache_use_stale;
ngx_uint_t cache_methods;
ngx_flag_t cache_lock;
ngx_msec_t cache_lock_timeout;
ngx_msec_t cache_lock_age;
ngx_flag_t cache_revalidate;
ngx_array_t *cache_valid;
ngx_array_t *cache_bypass;
ngx_array_t *no_cache;
#endif
// 表示存放路径的长度
ngx_array_t *store_lengths;
// 表示存放路径
ngx_array_t *store_values;
#if (NGX_HTTP_CACHE)
signed cache:2;
#endif
// 与ngx_http_upstream_t中的store一样
signed store:2;
// 1:捕获到404直接转发
unsigned intercept_404:1;
/* 1:用于动态决定buffering标志位。根据ngx_http_upstream_t的headers_in中的
X-Accel-Buffering(yes/no)的值来确定buffering */
unsigned change_buffering:1;
#if (NGX_HTTP_SSL)
ngx_ssl_t *ssl;
ngx_flag_t ssl_session_reuse;
ngx_http_complex_value_t *ssl_name;
ngx_flag_t ssl_server_name;
ngx_flag_t ssl_verify;
#endif
// 使用upstream的模块名称,仅用于记录日志
ngx_str_t module;
} ngx_http_upstream_conf_t;