parent proxy 源码学习

来源:互联网 发布:kvm和vmware区别 知乎 编辑:程序博客网 时间:2024/05/24 01:44

基于ATS7.0.0代码研究(与ATS6.1.1相差不大)

UML图:






notes:

1. ParentRecord 与 pRecord : ParentRecord 对应一条parent.config 记录, pRecord 对应一个回源IP或域名, 即 parent 或 secondary_parent 都可以配置多个下一跳的IP或域名,ParentRecord 中包含主(备)parent(secondary_parent)两个 pRecord 数组, 此时是 2:1 对应, 由于ParentRecord 里面包含多个 pRecord, 此时为 n:1 对应。

2. ParentRecord 与 ParentConfigParams :ParentConfigParams 通过 ParentTable 指针保存着所有的 parent.config 信息, 即 n:1 对应。

3. ParentRecord 与 ParentResult : 每个请求 request 都有一个ParentResult 对应着一个 ParentRecord 此时是 1:1 对应, 但是多个请求 req 的 ParentResult 可能共用一个ParentRecord 内存, 此时是 n:1 对应。


父代理的相关类介绍:

ParentSelectionStrategy 类, 基础工厂类

 虚函数成员方法:

  virtualvoid selectParent(const ParentSelectionPolicy *policy, bool firstCall,ParentResult *result, RequestData *rdata) = 0;

  virtual void markParentDown(constParentSelectionPolicy *policy, ParentResult *result) = 0;

  virtualuint32_t numParents(ParentResult *result) const = 0;

  virtual voidmarkParentUp(ParentResult *result) = 0;

 

ParentConsistentHash 类, 内容哈希模块

  相关类介绍

 ATSConsistentHash 类: (一致性内容哈希 和 其哈希配置存储)

      将name域名结点node通过weight和自增变量值,计算出很多个离散的hash值出来,并存储到map中;

      name(域名)查找时,先计算其哈希值,再通过map的lower_bound 函数找出对应的node结点。

 

  成员变量:

 ATSHash64Sip24 hash[2];  //哈希算法的指定,对应 parent 和 secondary_parent

 ATSConsistentHash *chash[2]; 

//配置内容哈希值存储指针,对应 parent 和 secondary_parent, 对象实例化在ParentConsistentHash::ParentConsistentHash() 中

 

  pRecord*parents[2];  

//存储ParentRecord 的 parents 和 secondary_parents 指针, 值赋值可参考ParentConsistentHash::ParentConsistentHash()

 

  boolfoundParents[2][MAX_PARENTS];  //此值暂时未使用

  boolignore_query; //请求URL哈希时是否忽略URL的参数部分, 值赋值可参考ParentConsistentHash::ParentConsistentHash()

 

  staticconst int PRIMARY = 0;  //常变量

  staticconst int SECONDARY = 1;  //常变量

 

  内容HASH分为PRIMARY(主) 和 SECONDARY(备) 两种选择

 

  成员方法:

  uint64_tgetPathHash(HttpRequestData *hrdata, ATSHash64 *h);  //通过请求 hrdata 获取次请求域名对应的哈希值

  voidselectParent(const ParentSelectionPolicy *policy, bool firstCall, ParentResult*result, RequestData *rdata); 

//用请求rdata 通过哈希的方式在 parents[2] 查找出合适的父IP(或域名)

 

  voidmarkParentDown(const ParentSelectionPolicy *policy, ParentResult *result);

//通过policy 和 result 中的信息,

         //来更新result 对应 ParentRecord 的parents 和 secondary_parents 中父IP(或域名)的不可用状态

 

  uint32_tnumParents(ParentResult *result) const;

//返回正在查询的parents[PRIMARY/SECONDARY] 在 parent.config 中配置父代理IP或域名的个数

 

  voidmarkParentUp(ParentResult *result); 

//通过result 中的信息, 来更新 result 对应ParentRecord 的 parents 和 secondary_parents 中父IP(或域名)的可用状态

 

ParentRoundRobin 类, 轮询模块

  成员变量:

  ParentRR_tround_robin_type; 

//枚举变量,对应 parent.config 中的 round_robin 参数,初始化可参考 ParentRecord::Init(), 值有: (具体示意参考parent.config 官方文档)

        //P_NO_ROUND_ROBIN: 即 false, Round robin selection does not occur.

        //P_STRICT_ROUND_ROBIN: 即 strict, Traffic Server machines serve requestsstrictly in turn.

        //P_HASH_ROUND_ROBIN: 即 true, Traffic Server determines the parent based onclient IP address.

        // 上面三个对应ParentRoundRobin

        //P_CONSISTENT_HASH: 即 consistent_hash, consistent hash of the url so thatone parent is chosen for a given url. (对应ParentConsistentHash )

 

  成员方法:

  voidselectParent(const ParentSelectionPolicy *policy, bool firstCall, ParentResult*result, RequestData *rdata);

               //通过请求rdata 在 result->rec->parents 按指定方式查找可用的父代理信息, 并用 result 的其他变量存储和返回

 

  voidmarkParentDown(const ParentSelectionPolicy *policy, ParentResult *result);

//通过policy 和 result 中的信息, 来更新result->rec->parents 中父IP(或域名)的不可用状态

 

  uint32_tnumParents(ParentResult *result) const; //返回 result->rec->parents 在parent.config 中配置父代理IP或域名的个数

  voidmarkParentUp(ParentResult *result);  //更新result->rec->parents 中父IP(或域名)的可用状态

 

ParentConsistentHash ParentRoundRobin都继承于ParentSelectionStrategy,使用的是工厂方法设计模式。

 

ATSConsistentHashNode 结构体, 结点,就是个struct

    boolavailable;  //是否可用

    char*name;  //域名指针

 

pRecord 结构体,  继承于ATSConsistentHashNode ,主要是对ATSConsistentHashNode 其他属性的扩展

                存储 parent.config 中的parent 或 secondary_parent 的配置项

    成员变量配置属性:

    charhostname[MAXDNAME + 1];  //域名,可以是IP

    intport;  //端口值

    time_tfailedAt; //Mark the parent as down, 是原子操作

    intfailCount; //失败次数, 是原子操作

    int32_tupAt;  //此值未使用

    const char*scheme; //A request URL protocol: http or https.

    int idx; //表示parent 或 secondary_parent 的父代理的坐标索引

    floatweight;  //表示parent 或 secondary_parent 的多个父代理的权重值,只用于 consistent_hash, 默认值为 1.0

 

ParentRecord 类,一个对象对应一行 parent.config 配置

parent.config 的参数具体含义请参考官方文档

  成员变量:

  pRecord*parents;  //数组指针,用于存 parent.config 的 parent 配置项

  pRecord*secondary_parents;  //数组指针,用于存 parent.config 的 secondary_parent 配置项,只针对 consistent_hash 生效

  intnum_parents;   //与parents 对应, 保存 parent.config 的parent 配置父代理的总数

  int num_secondary_parents;//与 secondary_parents 对应, 保存parent.config 的 secondary_parent 配置父代理的总数

 

  const char*scheme;  //A request URL protocol: httpor https. 用于存 parent.config 的scheme 配置项

  boolignore_query;  //请求URL哈希时是否忽略URL的参数部分,只针对 consistent_hash 生效, 用于存 parent.config 的qstring 配置项

  volatileuint32_t rr_next; //强制轮询计数器, 只用于 ParentRoundRobin 的P_STRICT_ROUND_ROBIN 场景

  boolgo_direct; 

//对应parent.config 的 go_direct 参数,默认值为 true, parent_is_proxy 为 cache servers 时才会生效

         //true, 请求不走父直接回源站(PARENT_DIRECT), requests bypass parent hierarchiesand go directly to the origin server.

         //false, 请求走父, requests do not bypass parent hierarchies.

 

  boolparent_is_proxy;  //对应parent.config 的 parent_is_proxy 参数,默认值为 true

                         //true 表示此行配置的是cache servers

                         //false 表示此行配置的是origin servers ,此时的 go_direct 值是被忽略无效的

 ParentSelectionStrategy *selection_strategy;  //策略选择,在 ParentConsistentHash 和 ParentRoundRobin 两种中选择

 UnavailableServerResponseCodes *unavailable_server_retry_responses;

//对应parent.config 的 unavailable_server_retry_responses 参数,

                  //表示返回的状态码是否为不可用, 默认值为503, 配置值statuscode(500< statuscode <600), 可以配多个值

 

  ParentRetry_tparent_retry;  //枚举类型,对应 parent.config 的 parent_retry 参数

                              //PARENT_RETRY_NONE: 初始值

                              //PARENT_RETRY_SIMPLE: 即 simple_retry

                              //PARENT_RETRY_UNAVAILABLE_SERVER: 即unavailable_server_retry

                              //PARENT_RETRY_BOTH: 即 both, 为simple_retry 和 unavailable_server_retry 都选择

  intmax_simple_retries;  //对应parent.config 的 max_simple_retries 参数,默认值为1, 与 parent_retry 一起使用

  intmax_unavailable_server_retries; 

//对应parent.config 的 max_unavailable_server_retries 参数,默认值为1, 与 parent_retry 一起使用

 

  成员方法:

 config_parse_error Init(matcher_line *line_info); //解析一行parent.config 配置

  boolDefaultInit(char *val);  //parent.config 默认配置的解析,ParentConfigParams 初始化时被 createDefaultParent() 调用

                                //默认值配置records.config, [default_var] proxy.config.http.parent_proxies

 

  voidUpdateMatch(ParentResult *result, RequestData *rdata); 

//根据result->line_number 和请求 rdata 来更新查找的ParentRecord 配置

 

  voidPrint();  //打印ParentRecord 的配置信息, 主要打印 hostname, port, go_direct,parent_is_proxy 参数

 

  boolbypass_ok() const;  //返回go_direct 的值

  const char*ProcessParents(char *val, bool isPrimary); //解析parent.config 中的 parent 和 secondary_parent 参数,

                                                        //并将值保存到 parents 和 secondary_parents 中

 

ParentResult 类,存储 ParentRecord 对象, 和一些其他的相关参数, 一个请求对应一个ParentResult

                ParentResult 与 ParentRecord 是多对一的关系

  成员变量:

 ParentResultType result;  //枚举变量,表示请求查找父代理的类型,值为:

                            // PARENT_UNDEFINED: 未指定父代理,初始化值

                            // PARENT_DIRECT : 直接回源

                            // PARENT_SPECIFIED: 指定了父代理包括api设置父代理

                            // PARENT_AGENT : 此值暂时未使用

                            // PARENT_FAIL : 指定父代理失败

  const char*hostname;  //匹配配置中的主机名

  int port;  //匹配配置中的端口

  boolretry;  //是否进行重试

 

  //private:

  intline_number;  //rec 配置在parent.config 中对应的行号

  ParentRecord*rec;  //parent.config 中的一项配置

  uint32_tlast_parent;  //最后一个父配置项

  uint32_tstart_parent;  //第一个父配置项,只在 ParentRoundRobin::selectParent() 中使用了

  boolwrap_around;  //没有实际意义

  // state forconsistent hash.

  intlast_lookup;  //表示查找的是PRIMARY 还是 SECONDARY, 只针对consistent hash 生效

  ATSConsistentHashIterchashIter[2];

//map的迭代器,定义为:typedef std::map<uint64_t, ATSConsistentHashNode *>::iteratorATSConsistentHashIter;

          //ATSConsistentHash 中 lookup_by_hashval 和lookup 查找 ATSConsistentHashNode 时的迭代器,不传此值也没问题

 

  成员方法:

  void reset();  //此ParentResult 对象初始化

  boolis_api_result() const;  //判断是否调用了api设置父代理

  bool is_some()const;  //判断rec 是否为空, 并进行了特需校验

  boolparent_is_proxy() const;  //先判断is_api_result(), 并返回是否为父代理

  unsignedretry_type() const;  //先判断is_api_result(), 并返回 parent_retry 值

  unsignedmax_retries(ParentRetry_t method) const; //先判断 is_api_result(), 并通过method 值返回最大重试次数

  boolresponse_is_retryable(HTTPStatus response_code) const;  //通过retry_type() 和 状态码 判断源站是否可用

  boolbypass_ok() const;  //先判断is_api_result(), 再返回 go_direct 的值

 

typedef ControlMatcher<ParentRecord,ParentResult> P_table; //使用模板加载配置,配置模板可以参考 congestion代码解析

 

ParentConfigParams 类,继承于ConfigInfo, 用于配置管理,其对象的使用和删除是通过计数器来控制的

  成员变量:

  P_table*parent_table;       

//保存parent.config 中的配置项,父配置文件 parent.config 指定参数为proxy.config.http.parent_proxy.file

  ParentRecord*DefaultParent;  //父的默认配置,可以通过 [default_var] proxy.config.http.parent_proxies 进行指定

                                //若default_var 参数未指定, 则无默认的父配置, 线上情况一般没有指定

 ParentSelectionPolicy policy; //是对records.config 中父配置的存储

                                //ParentRetryTime:[retry_var] proxy.config.http.parent_proxy.retry_time ,

                                //ParentEnable:[enable_var]proxy.config.http.parent_proxy_routing_enable ,

                               //FailThreshold: [threshold_var]proxy.config.http.parent_proxy.fail_threshold

 

  成员方法:

  boolapiParentExists(HttpRequestData *rdata); 

//判断此请求是否通过rdata->api_info (如: TSHttpTxnParentProxySet) 设置了父代理信息

 

  voidfindParent(HttpRequestData *rdata, ParentResult *result); 

//通过请求信息rdata 在 parent_table 中查找对应的父配置信息,

                 //调用 selectParent() 时firstCall 为 true 即第一次查找, 主策略中查找,并返回 result

 

  voidnextParent(HttpRequestData *rdata, ParentResult *result); 

//通过请求信息rdata 在对应的 result->rec 即ParentRecord 中选择备用父策略

                 //不需要通过 rdata 在 parent_table 中重新查找ParentRecord ,直接使用 result->rec

                 //调用 selectParent() 时firstCall 为 false 即第二次查找, 备用策略中查找,并返回 result

 

  boolparentExists(HttpRequestData *rdata);  //通过请求rdata 调用 findParent() 查找是否有可用的父策略

  voidselectParent(bool firstCall, ParentResult *result, RequestData *rdata);

//根据result 中 ParentRecord 配置信息调用selection_strategy->selectParent 去选择对应的父策略

                 //其实是对 ParentRecord 中的selection_strategy->selectParent 做了一次封装

 

  voidmarkParentDown(ParentResult *result); 

//根据result 中 ParentRecord 配置信息调用selection_strategy->markParentDown 去标记指定父配置不可用

                 //其实是对 ParentRecord 中的selection_strategy->markParentDown 做了一次封装

 

  uint32_tnumParents(ParentResult *result); 

//根据result 中 ParentRecord 配置信息调用selection_strategy->numParents 返回可用父配置数

                 //其实是对ParentRecord 中的 selection_strategy->numParents 做了一次封装

 

  voidmarkParentUp(ParentResult *result); 

//根据result 中 ParentRecord 配置信息调用selection_strategy->markParentUp 去标记指定父配置可用

                 //其实是对 ParentRecord 中的selection_strategy->markParentUp 做了一次封装

 

ParentConfig 类, 配置的读取类,包括热加载和配置内存管理和释放

  成员变量:

  static intm_id; //用于在 configProcessor 中查找ParentConfigParams 对象配置的标识

 

  成员方法:

  static voidstartup();   //配置读取入口,热加载的回调函数注册, 调用 reconfigure() 读取parent.config 配置

  static voidreconfigure();  //加载parent.config 的配置项,并用 ParentConfigParams *params 对象保存配置

                              //params 指向的内存使用配置处理器 configProcessor 保存并管理

  static voidprint();   //打印所有的父配置项,即 ParentConfigParams 对象里面的内容

  static voidset_parent_table(P_table *pTable, ParentRecord *rec, int num_elements);  //只有声明没有实现也没有使用。

                                                //测试了struct下面声明一个函数,没有实现且没有使用,gcc编译器是允许的。

 

  staticParentConfigParams *acquire(); //通过 m_id 在 configProcessor 中获取ParentConfigParams 对象配置

  staticvoid release(ParentConfigParams *strategy); //通过计数器释放 ParentConfigParams 对象内存

 

SocksServerConfig 类: socks代理,与 ParentConfig 类相似,配置存储都是用的ParentConfigParams 类,主要是用于网络层的 SocksProxy 代理模块。读取的配置文件为 socks.config, 参数指定[records.config]:proxy.config.socks.socks_config_file

 

配置读取和更新:

1. void ParentConfig::startup();  //parent.config 读取入口, 在 main() 函数中调用, 注册records.config 参数热加载的回调函数

   parent.config 的热加载可以参考 ConfigUpdateHandler 类, 具体如何热加载的待研究

2. void ParentConfig::reconfigure(); //配置读取

    P_table*pTable = new P_table(file_var, modulePrefix, &http_dest_tags);  //parent.config 配置的读取

    params =new ParentConfigParams(pTable); //默认配置的加载

3. ControlMatcher<ParentRecord,ParentResult>::ControlMatcher(const char *file_var, const char *name, constmatcher_tags *tags, int flags_in);

4. int ControlMatcher<ParentRecord,ParentResult>::BuildTable();

5. int ControlMatcher<ParentRecord,ParentResult>::BuildTableFromString(char *str);

6. config_parse_error HostMatcher<ParentRecord,ParentResult>::NewEntry(matcher_line *line_info);

7. config_parse_error ParentRecord::Init(matcher_line*line_info);

 

父代理处理流程:

1. find_server_and_update_current_info 函数先通过HTTP请求用ParentConfigParams::findParent 找出对应的 parent 配置,用 result 返回赋给 s->parent_result

2. 重试时查找父配置用ParentConfigParams::nextParent, 用 result 返回赋给s->parent_result

3. 标记此父配置不可用ParentConfigParams::markParentDown 在HttpTransact::handle_response_from_parent 和HttpTransact::PPDNSLookup 调用

4. 标记此父配置可用ParentConfigParams::markParentUp 在HttpTransact::handle_response_from_parent 调用

5. ATS查询和修改父配置对外的接口类为 ParentConfigParams, 所有的父配置状态信息修改和重新选择父配置都是在 s->parent_result 中操作




0 0
原创粉丝点击