nginx的upstream模块

关键数据结构

1 ngx_http_upstream_s

其结构定义为

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;//连接到后端服务器的连接对象

    ngx_event_pipe_t                *pipe;//开启缓存时用于将上游数据发到下游

    ngx_chain_t                     *request_bufs; //用于存放发到上游的消息的缓存
    //用于将数据发送到上游
    ngx_output_chain_ctx_t           output;
    ngx_chain_writer_ctx_t           writer;

    ngx_http_upstream_conf_t        *conf;//表示依赖upstream的其它http模块的上游配置
    ngx_http_upstream_srv_conf_t    *upstream;//上游的upstream的srv配置
#if (NGX_HTTP_CACHE)
    ngx_array_t                     *caches;//开启NGX_HTTP_CACHE时的缓存
#endif
    //处理上游响应时处理头部
    ngx_http_upstream_headers_in_t   headers_in;

    ngx_http_upstream_resolved_t    *resolved;//解析到的上游信息

    ngx_buf_t                        from_client;//用于存储下游数据的缓存

    ngx_buf_t                        buffer;//用于接收响应的缓冲区
    off_t                            length;//响应长度
    //用于向下游发送响应的缓冲区
    ngx_chain_t                     *out_bufs;
    ngx_chain_t                     *busy_bufs;
    ngx_chain_t                     *free_bufs;

    ngx_int_t                      (*input_filter_init)(void *data);//处理上游响应包体的初始化操作
    ngx_int_t                      (*input_filter)(void *data, ssize_t bytes);//处理上游响应包体
    void                            *input_filter_ctx;

#if (NGX_HTTP_CACHE)
    ngx_int_t                      (*create_key)(ngx_http_request_t *r);//开启缓存时用于创建缓存key
#endif
    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);//结束请求
    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);//重写cookie

    ngx_msec_t                       start_time;//向上游发起连接的时间

    ngx_http_upstream_state_t       *state;//上游的状态信息

    ngx_str_t                        method;//发往上游的方法
    ngx_str_t                        schema;//发往上游的协议
    ngx_str_t                        uri;//发往上游的uri

#if (NGX_HTTP_SSL || NGX_COMPAT)
    ngx_str_t                        ssl_name;//开启ssl时为上游解析到的主机信息
#endif

    ngx_http_cleanup_pt             *cleanup;

    unsigned                         store:1;//是否指定文件缓存路径的标识
    unsigned                         cacheable:1;//是否开启文件缓存
    unsigned                         accel:1;//暂时没有使用
    unsigned                         ssl:1;//是否基于ssl协议访问上游
#if (NGX_HTTP_CACHE)
    unsigned                         cache_status:3;//缓存状态
#endif

    unsigned                         buffering:1;//当向下游转发上游的响应包体时,是否开启更大的内存及临时于缓存来不及发到下游的响应包体
    unsigned                         keepalive:1;//是否与上游保活
    unsigned                         upgrade:1;//上游是否在升级
    unsigned                         error:1;

    unsigned                         request_sent:1;//是否向上游发送过请求
    unsigned                         request_body_sent:1;//是否向上游发送包体
    unsigned                         request_body_blocked:1;//向上游发送包体是否发生阻塞
    unsigned                         header_sent:1;//是否把包头转发给下游
};

2 ngx_http_upstream_conf_t

其结构定义为

typedef struct {
    ngx_http_upstream_srv_conf_t    *upstream;

    ngx_msec_t                       connect_timeout;//控制连接上游的超时时间
    ngx_msec_t                       send_timeout;//发送消息到上游的超时时间
    ngx_msec_t                       read_timeout;//从上游读取消息的超时时间
    ngx_msec_t                       next_upstream_timeout;//获取下一个可用上游的超时时间

    size_t                           send_lowat;//控制在向上游写数据时的阀值,当大于这个阀值时才表示可写
    size_t                           buffer_size;//用于接收上游响应头缓存区的大小
    size_t                           limit_rate;//用于控制上下游转发响应里的速率

    size_t                           busy_buffers_size;//当buffering=1,并且向下游转发响应时生效
    size_t                           max_temp_file_size;//buffering=1,若上游速度快于下游,则可能把上游的响应存在临时文件中的临时文件大小
    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_uint_t                       ignore_headers;//在处理上游响应头部时,根据位来忽略某些头
    ngx_uint_t                       next_upstream;//根据错误码来选择下一个上游服务器
    ngx_uint_t                       store_access;//创建目录和文件的权限
    ngx_uint_t                       next_upstream_tries;//设置请求下一个上游的重试次数
    ngx_flag_t                       buffering;//决定转发响应方式的标志位
    ngx_flag_t                       request_buffering;//在将消息体发到上游时,是否缓存
    ngx_flag_t                       pass_request_headers;//向上游发送请求时,是否透传下游的请求头
    ngx_flag_t                       pass_request_body;//是否透传消息体,与buffering配合使用

    ngx_flag_t                       ignore_client_abort;//当下游断开时,是否检查客户端状态
    ngx_flag_t                       intercept_errors;//是否拦截上游返回的错误码,来决定返回下游错误信息
    ngx_flag_t                       cyclic_temp_file;//复用临时文件中已经使用过的空间
    ngx_flag_t                       force_ranges;//是否忽略上游的响应的"Accept-Ranges"

    ngx_path_t                      *temp_path;//在开启缓存时,用于存放上游响应体的临时文件目录

    ngx_hash_t                       hide_headers_hash;//用于处理上游响应头时,需要忽略的
    ngx_array_t                     *hide_headers;//处理上游响应头时,需要忽略的,在初始化时会添加到hide_headers_hash这个表中
    ngx_array_t                     *pass_headers;//在初始化时,在将hide_headers添加到hide_headers_hasha散列表前,如果在pass_headers中,则不加入到散列表中

    ngx_http_upstream_local_t       *local;//连接上游服务器时的本机地址
    ngx_flag_t                       socket_keepalive;//用于配置连接上游时设置套装字的SO_KEEPALIVE

#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;

    off_t                            cache_max_range_offset;

    ngx_flag_t                       cache_lock;
    ngx_msec_t                       cache_lock_timeout;
    ngx_msec_t                       cache_lock_age;

    ngx_flag_t                       cache_revalidate;
    ngx_flag_t                       cache_convert_head;
    ngx_flag_t                       cache_background_update;

    ngx_array_t                     *cache_valid;
    ngx_array_t                     *cache_bypass;
    ngx_array_t                     *cache_purge;
    ngx_array_t                     *no_cache;
#endif

    ngx_array_t                     *store_lengths;//表示存放路径的长度
    ngx_array_t                     *store_values;//表示存放路径

#if (NGX_HTTP_CACHE)
    signed                           cache:2;
#endif
    signed                           store:2;
    unsigned                         intercept_404:1;//捕获到404直接转发
    unsigned                         change_buffering:1;//动态修改upstream中的buffering
    unsigned                         pass_trailers:1;//结束upstream时是否向下游发送trainer
    unsigned                         preserve_output:1;//在向上游发送完请求后,是否继续输出,主要是设置upstream的write_event_handler,如果不继续,则设置为ngx_http_upstream_dummy_handler

#if (NGX_HTTP_SSL || NGX_COMPAT)
    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;

    ngx_http_complex_value_t        *ssl_certificate;
    ngx_http_complex_value_t        *ssl_certificate_key;
    ngx_array_t                     *ssl_passwords;
#endif

    ngx_str_t                        module;

    NGX_COMPAT_BEGIN(2)
    NGX_COMPAT_END
} ngx_http_upstream_conf_t;

ngx_http_upstream_conf_t的设置

主要是在各自模块的handler来设置

模块

Handler

ngx_http_fastcgi_module

ngx_http_fastcgi_handler

ngx_http_grpc_module

ngx_http_grpc_handler

ngx_http_proxy_module

ngx_http_proxy_handler

ngx_http_memcached_module

ngx_http_memcached_handler

3 ngx_http_upstream_srv_conf_s

struct ngx_http_upstream_srv_conf_s {
    ngx_http_upstream_peer_t         peer;//上游服务对端
    void                           **srv_conf;//服务配置,对应ngx_http_conf_ctx_t中的srv_conf
    //ngx_http_upstream_module在处理server指令添加
    ngx_array_t                     *servers;  /* ngx_http_upstream_server_t */

    ngx_uint_t                       flags;//值可以为以下位值 NGX_HTTP_UPSTREAM_CREATE,NGX_HTTP_UPSTREAM_WEIGHT,NGX_HTTP_UPSTREAM_MAX_CONNS,NGX_HTTP_UPSTREAM_MAX_FAILS,NGX_HTTP_UPSTREAM_FAIL_TIMEOUT,NGX_HTTP_UPSTREAM_DOWN
    ngx_str_t                        host;//对应upstream指令的name
    u_char                          *file_name;//配置所在文件
    ngx_uint_t                       line;//配置所在行
    in_port_t                        port;//端口号,默认是0
    ngx_uint_t                       no_port;  /* unsigned no_port:1 *///没有端口标识,默认是1

#if (NGX_HTTP_UPSTREAM_ZONE)
    ngx_shm_zone_t                  *shm_zone;//ngx_http_upstream_zone_module和ngx_stream_upstream_zone_module会使用到
#endif
};

4 ngx_http_upstream_peer_t

typedef struct {
    ngx_http_upstream_init_pt        init_upstream;//初始化upstream的处理器
    ngx_http_upstream_init_peer_pt   init;//初始化peer的处理器
    void                            *data;//peer的数据,不同的负载均衡有不同的数据结构
} ngx_http_upstream_peer_t;

5 ngx_http_upstream_rr_peers_s和ngx_http_upstream_rr_peer_s

负载均衡的轮询方式会使用

struct ngx_http_upstream_rr_peers_s {
    ngx_uint_t                      number;//上游服务器的个数 

#if (NGX_HTTP_UPSTREAM_ZONE)
    ngx_slab_pool_t                *shpool;
    ngx_atomic_t                    rwlock;
    ngx_http_upstream_rr_peers_t   *zone_next;
#endif

    ngx_uint_t                      total_weight;//总的权重值 是经过加权计算得出
    ngx_uint_t                      tries;//不包含处于down下线状态的服务器的个数,用于重试计数

    unsigned                        single:1;//仅有一个peer server 
    unsigned                        weighted:1;

    ngx_str_t                      *name;

    ngx_http_upstream_rr_peers_t   *next;//下一个peer server

    ngx_http_upstream_rr_peer_t    *peer;//当前轮询的peer server
};

//在ngx_http_upstream_init_round_robin中设置
struct ngx_http_upstream_rr_peer_s {
    struct sockaddr                *sockaddr;//服务端地址
    socklen_t                       socklen;//服务端sock长度
    ngx_str_t                       name;//服务地址名
    ngx_str_t                       server;//服务名

    ngx_int_t                       current_weight;//当前权重,初始为0
    ngx_int_t                       effective_weight;//有效权重,不会大于weight
    ngx_int_t                       weight;//配置的权重

    ngx_uint_t                      conns;//连接数
    ngx_uint_t                      max_conns;//最大连接数

    ngx_uint_t                      fails;//失败数
    time_t                          accessed;//记录失败时的时间
    time_t                          checked;//用于失败检查恢复的时间

    ngx_uint_t                      max_fails;//最大失败数
    time_t                          fail_timeout;//失败超时时间
    ngx_msec_t                      slow_start;
    ngx_msec_t                      start_time;

    ngx_uint_t                      down;

#if (NGX_HTTP_SSL || NGX_COMPAT)
    void                           *ssl_session;
    int                             ssl_session_len;
#endif

#if (NGX_HTTP_UPSTREAM_ZONE)
    ngx_atomic_t                    lock;
#endif

    ngx_http_upstream_rr_peer_t    *next;

    NGX_COMPAT_BEGIN(32)
    NGX_COMPAT_END
};

6 ngx_peer_connection_s

struct ngx_peer_connection_s {
    ngx_connection_t                *connection;

    struct sockaddr                 *sockaddr;
    socklen_t                        socklen;
    ngx_str_t                       *name;

    ngx_uint_t                       tries;
    ngx_msec_t                       start_time;

    ngx_event_get_peer_pt            get;//获取远端服务器函数指针,其定义为typedef ngx_int_t (*ngx_event_get_peer_pt)(ngx_peer_connection_t *pc,void *data);
    ngx_event_free_peer_pt           free;//释放远端服务器函数指针,其定义为typedef void (*ngx_event_free_peer_pt)(ngx_peer_connection_t *pc, void *data,ngx_uint_t state);
    ngx_event_notify_peer_pt         notify;//通知远端服务器函数指针,其定义为typedef void (*ngx_event_notify_peer_pt)(ngx_peer_connection_t *pc,void*data, ngx_uint_t type);
    void                            *data;

#if (NGX_SSL || NGX_COMPAT)
    ngx_event_set_peer_session_pt    set_session;
    ngx_event_save_peer_session_pt   save_session;
#endif

    ngx_addr_t                      *local;

    int                              type;
    int                              rcvbuf;

    ngx_log_t                       *log;

    unsigned                         cached:1;
    unsigned                         transparent:1;
    unsigned                         so_keepalive:1;
    unsigned                         down:1;

                                     /* ngx_connection_log_error_e */
    unsigned                         log_error:2;

    NGX_COMPAT_BEGIN(2)
    NGX_COMPAT_END
};

依赖关系

upstream的抽象设计

input_filter_init:处理上游响应包体前的初始化操作

input_filter:处理上游响应包体

create_key:在开启缓存时,创建缓存的key

create_request:创建发送到上游的请求

reinit_request:在出错时,重新初始化发送到上游的请求

process_header:处理上游返回的包头

abort_request:丢弃上游的请求

finalize_request:结束上游请求

rewrite_redirect:在上游返回的响应包头中包含Location或者Refresh,ngx_http_upstream_process_headers会调用重写重定向

rewrite_cookie:在上游返回的响应包头中包含Set-Cookie时,ngx_http_upstream_process_headers会调用重写cookie

处理流程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kgduu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值