设为首页 收藏本站
查看: 2127|回复: 0

[经验分享] 转载:HAProxy 研究笔记 -- rules 实现

[复制链接]

尚未签到

发表于 2017-4-18 09:10:36 | 显示全部楼层 |阅读模式
  转载:HAProxy 研究笔记 -- rules 实现 
  原文链接:http://blog.chinaunix.net/uid-10167808-id-3775567.html



  • 作者:Godbach <nylzhaowei@gmail.com>

  • Blog:  http://godbach.blog.chinaunix.net  
  • 微博:weibo.com/godbach


  • 日期:Jun 25, 2013
  • 本文可以自由拷贝,转载。但转载请保持文档的完整性,注明原作者及原链接。
  • ----
  
本文研究 haproxy-1.5-dev17 中 rules 的相关实现。
 


  • 1. ACL
  • 2. rule 的组成
  • 3. rule 的执行
  • 4. rule 的种类



1. ACL

如果要实现功能丰富的 rules,需要有配套的 ACL 机制。
ACL 的格式如下:

acl <aclname> <criterion> [flags] [operator] <value> ...

haproxy 中 ACL 数据结构的定义:

/* The acl will be linked to from the proxy where it is declared */
struct acl {
struct list list;           /* chaining */
char *name;    /* acl name */
struct list expr;    /* list of acl_exprs */
int cache_idx;              /* ACL index in cache */
unsigned int requires;      /* or'ed bit mask of all acl_expr's ACL_USE_* */
};

其中:


  • name: ACL 的名字
  • expr: ACL 定义的表达式。就是定义的 ACL 名字后面的表达式。这是一个链表结构。因此,可以定义多条表达式不同但是名字相同的 ACL。这样,多个表达式都属于同一个 ACL。
  • requires: 所有表达式中关键字对应的作用域(该关键字可以用在什么场合)的集合

函数 parse_acl() 负责解析定义好的 ACL:


  • 查找 ACL 的名字,如果不存在的话,则 alloc 一个新的 acl 结构
  • 通过调用 parse_acl_expr() 对表达式进行解析,并返回 struct acl_expr 结构

    • ACL 中的表达式应该只有一个 kw
    • 查找该关键字,必须是已经注册好的。并返回该关键字注册时的数据结构 struct acl_expr
    • alloc 一个 struct acl_expr 结构体,记录下返回的 kw 的数据结构,并作成员的初始化
    • 调用对应 kw 的 parse 方法,将解析的结果保存在 struct acl_pattern 结构体中,并将该结构体加入到 expr->patterns 的链表中

  • 将解析到的表达式插入到 acl 中的 expr 链表中

总结: 一个 ACL 包含一到多个表达式。每个表达式包含一个 kw及一到多个 pattern。

2. rule 的组成

这里简要描述 rule 与 acl 之间的逻辑关系:


  • rule 应该是 action + condition 组成

    • 有些动作自身可能也需要记录一些信息。不同的 rule 对应动作的信息可能不同,比如 reqirep 等
    • block rules 的动作比较单一, condition 满足之后处理结果均相同

  • condition,完成 rule 检测的判断条件 对应数据结构: struct acl_cond
            struct acl_cond {
    struct list list;           /* Some specific tests may use multiple conditions */
    struct list suites;         /* list of acl_term_suites */
    int pol;                    /* polarity: ACL_COND_IF / ACL_COND_UNLESS */
    unsigned int requires;      /* or'ed bit mask of all acl's ACL_USE_* */
    const char *file;           /* config file where the condition is declared */
    int line;                   /* line in the config file where the condition is declared */
    };
  • condition 包含多个 ACL 组。组的分割逻辑是逻辑或(|| 或者 or),即 struct list suites 的成员,组的数据结构 struct acl_term_suite
        struct acl_term_suite {
    struct list list;           /* chaining of term suites */
    struct list terms;          /* list of acl_terms */
    };


    • 该数据结构可以包含多个 ACL,以及每个 ACL 可能的一个取反标识 '!'
    • 所有表达式中相邻的 ACL 且其逻辑关系为逻辑与(&&) 的构成一个 ACL 组

      • 比如 if acl1 !acl2 or acl3 acl4,则构成两个 acl_term_suite,分别是 acl1 !acl2 和 acl3 acl4
      • 每个 ACL 及其可能的取反标记对应的数据结构: struct acl_term
            struct acl_term {
        struct list list;           /* chaining */
        struct acl *acl;            /* acl pointed to by this term */
        int neg;                    /* 1 if the ACL result must be negated */
        };

    • 一个 ACL 包含多个 expr


3. rule 的执行

概括起来很简单,执行判断条件。符合条件,然后执行对应动作。
下面是 rspadd 的示例代码:

/* add response headers from the rule sets in the same order */
list_for_each_entry(wl, &rule_set->rsp_add, list) {
if (txn->status < 200)
break;
if (wl->cond) {
int ret = acl_exec_cond(wl->cond, px, t, txn, SMP_OPT_DIR_RES|SMP_OPT_FINAL);
ret = acl_pass(ret);
if (((struct acl_cond *)wl->cond)->pol == ACL_COND_UNLESS)
ret = !ret;
if (!ret)
continue;
}
if (unlikely(http_header_add_tail(&txn->rsp, &txn->hdr_idx, wl->s) < 0))
goto return_bad_resp;
}

对于同一个种类的 rules,执行逻辑如下:


  • 主要遍历 rule,调用 acl_exec_cond 执行该 rule 的检测条件。该检测结果只给出匹配与否。

    • 逐个遍历 cond 上的 ACL 组,即cond->suites。任一 suite 匹配成功,则认为匹配成功
    • 同一个 ACL 组上,遍历所有 suite->terms (ACL + 取反逻辑)。任意一个 ACL 匹配失败,则跳到下一个 ACL 组继续匹配。同一组全部 ACL 匹配成功,则认为该 ACL 组匹配

      • 同一个 ACL 上的匹配,则是逐一遍历 ACL 的 expr。只要任意一个 expr 匹配成功,则认为该 ACL 匹配成功


  • 结合 condition 中的条件 if/unless,确定最终匹配结果
  • 如果匹配则执行对应的 action,否则检测下一条规则。

4. rule 的种类

从 proxy 结构体可以看出 rule 的种类

struct proxy {
...
struct list acl;                        /* ACL declared on this proxy */
struct list http_req_rules;/* HTTP request rules: allow/deny/http-auth */
struct list block_cond;                 /* early blocking conditions (chained) */
struct list redirect_rules;             /* content redirecting rules (chained) */
struct list switching_rules;            /* content switching rules (chained) */
struct list persist_rules;/* 'force-persist' and 'ignore-persist' rules (chained) */
struct list sticking_rules;             /* content sticking rules (chained) */
struct list storersp_rules;             /* content store response rules (chained) */
struct list server_rules;               /* server switching rules (chained) */
struct {                                /* TCP request processing */
unsigned int inspect_delay;     /* inspection delay */
struct list inspect_rules;      /* inspection rules */
struct list l4_rules;           /* layer4 rules */
} tcp_req;
struct {                                /* TCP request processing */
unsigned int inspect_delay;     /* inspection delay */
struct list inspect_rules;      /* inspection rules */
} tcp_rep;
...
}

其中, 函数 http_process_req_common 中处理的规则如下:

http_process_req_common
{
...
1. process block rules
...
2. process http req rules
...
3. execute regular exp if any
...
4. req add
...
5. process redirect rules
...
}


这里没有详细的介绍各种具体用途的 rules。随后具体分析代码的时候总结一下再加上。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-365720-1-1.html 上篇帖子: haproxy基础详解及动静分离的实现 下篇帖子: haproxy不能正确记录客户端的IP,
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表