vlambda博客
学习文章列表

BFE和Nginx有什么差异?- 转发模型的对比


提示:本文较长,且涉及部分配置,点击文章最下方的“阅读原文” 在手机或PC上查看,效果更佳。点击“阅读原文” 还可以留言或发表评论。



    Nginx是一个被广泛使用的反向代理(ReverseProxy)开源软件。在“反向代理”这个方向上,BFE是被设计用来替代Nginx的。

    于是,一个被经常提出的问题出现了:为什么要使用BFE?和Nginx相比,BFE到底有什么地方是不同的?

 

    BFE和Nginx最大的不同是设计出发点和转发模型。

    BFE从一开始就是为转发场景设计的,能够很好的满足各种转发场景的需求;而Nginx本来是作为Web Server设计的,用来做转发是“半路出家”,在模型方面存在一些问题。

    本文将重点说明两者在“转发模型”上的差异。


1. 对Nginx的分析

1.1 Nginx的转发配置

    首先看看Nginx是怎么做的。

    Nginx配置中的核心概念是server, location,upstream。

  • server:代表一个web server,可以定义web server的监听端口和主机名

  • location:代表一个web server之下的各路径/接口

  • upstream:代表被转发的目标


    一个典型的Nginx转发配置如下所示:

# 定义转发目标集群cluster_a

upstream cluster_a {
    server 192.168.1.1:8080;
    server 192.168.1.2:8080;
}

 

# 定义转发目标集群cluster_b

upstream cluster_b {
    server 192.168.1.3:8080;
    server 192.168.1.4:8080;
}

 

# 定义www.a.com的转发规则

server {

         listen 80;

         server_name www.a.com;   # host

         location / {               # path, 设置为any

proxy_pass  http://cluster_a;# 转发给cluste_a

         }

}

 

# 定义www.b.com的转发规则

server {

         listen 80;

         server_name www.b.com;     # host

         location / {                  # path,设置为any

proxy_pass  http://cluster_b;    # 转发给cluster_b

         }

}


    如果要在转发过程中做一些特殊的处理,则在以上的配置中插入相关的语句。例如,针对www.a.com的请求,可以增加如下rewrite规则:


server {

         listen 80;

         server_name www.a.com;

         location / {

rewrite '^/images/([a-z]{2})/([a-z0-9]{5})/(.*)\.(png|jpg)$'  /data?file=$3.$4;

proxy_pass  http://cluster_a

         }

}


1.2 Nginx转发模型的问题


     虽然目前很多人将Nginx用于转发场景,但是不得不说,Nginx的转发机制有比较严重的问题。


(1) 转发配置的描述能力较弱

对于一个转发场景来说,配置规则的基本逻辑是:转发条件 => 转发目标

多条转发规则可以形成一张转发表。

转发条件

转发目标

Host=www.a.com

cluster_a

Host=www.b.com

cluster_b


在Nginx中,并没有出现明确的转发表概念,转发规则的描述受到配置中server-location结构的限制。server-location结构本来是设计用于web server的,用于转发就比较笨重。例子中这种简单的转发逻辑需要比较多的配置语句。

在Nginx开源版本中,location描述机制在表达能力方面的缺点具体表现在:

  • 仅支持基于uri的条件,无法直接支持基于请求Header或请求上下文的条件

  • 针对常见的uri包含匹配、后缀匹配也不得不使用正则表达式

  • 难以对多个条件灵活进行逻辑组合(与或非)


(2) 转发规则的优先级较复杂

   在存在多条转发规则的时候,优先级的控制就变得非常重要。

   Nginx在匹配优先级上做了一定的限制,必须首先匹配Host以确定server,然后在server内匹配location。这个限制在简单的场景下没有问题,但是在比较复杂的场景下可能会制约规则的编写。


    在匹配server和匹配location时,都有比较复杂的规则(见下)。在比较复杂的场景下,最终生效的结果并不容易预测。


匹配server时,规则如下:

1、完全匹配

2、通配符在前的,如*.test.com

3、在后的,如www.test.*

4、正则匹配,如~^\.www\.test\.com$

如果都不匹配

1、优先选择listen配置项后有default或default_server的

2、找到匹配listen端口的第一个server块

 

 

    在匹配location时,规则如下:

1,字符串最长匹配(非正则表达式)

和在配置文件中出现的先后顺序无关

2,正则匹配

正则表达式按照配置文件中顺序匹配,一旦匹配,不会继续匹配


(3) 大量使用正则表达式

       在Nginx中,对于稍微复杂的场景,就需要在转发规则的描述中使用正则表达式。

在实践中,我们发现正则表达式存在以下两个严重问题:

  • 配置难以维护。正则表达式存在严重的可读性问题。用正则表达式编写的转发条件很难看懂,且容易存在二义性。

  • 性能存在隐患。对于编写不当的正则表达式,可能在特定的流量特征下会出现严重的性能退化。


(4) “基础转发”和“转发的附加处理”混杂在一起

在反向代理的转发模型中,需要容纳以下两个基本功能:

  • 基础转发配置。定义转发的条件和转发的目标。

  • 转发的附加处理。定义在转发中需要做的操作,如rewrite, redirect等等。

 

       在Nginx中,“基础转发”和“转发的附加处理”(如,rewrite, redirect等)只能混在一起写。

       在一些情况下,“转发的附加处理”和“基础转发”的匹配逻辑可能并不完全一致,在Nginx中配置维护比较困难。



(5) 不支持在多组实例间按照比例调度

在多数据中心或多容器云的场景下,可能有这样的需求:

  • 多组实例都提供相同的服务

  • 在多组实例间,使用权重比例来调度流量

 

这个需求转换为Nginx的概念,就是需要支持对满足某种转发规则的请求,按照设定的权重转发给多个upstream。Nginx不支持这样的功能。


2. BFE和Nginx的差异

    BFE的定位是“为企业级场景设计的现代七层负载均衡开源软件”。和Nginx相比,BFE有以下的变化:

(1)  面向转发场景设计

  • 在BFE中明确引入了“转发表”的概念,可以清晰而简洁的设定转发条件和转发目标。

  • 在BFE中,除了Host和Path外,也可以很容易的使用请求中更多的信息作为转发条件。

  • 在BFE“转发表”的多条规则间,有较简单的优先级策略,更易于理解


(2) 尽量避免正则表达式的使用

   针对正则表达式所存在的问题,BFE中设计了“条件表达式”(ConditionExpression)机制,以提高转发规则的可维护性,并降低性能退化的隐患。


(3) 将“转发的附加处理”和“基础转发”的配置分离

    如rewrite、redirect这样的处理,各自有独立的配置。


(4) 提供了多组实例间按照比例调度的功能

      这个功能对于多数据中心或多容器云场景的调度非常有用。


3. BFE转发中的基本概念


在BFE中,有以下基本概念:

(1)   租户(Tenant)。使用BFE转发的业务可以基于“租户”的单位来区分。BFE引擎中的配置,比如转发策略、各扩展模块的配置等,都是以租户为单位来区分的。在BFE中,租户也被称为“产品线(Product)”。

(2)   后端集群(Cluster)。具有同类功能的后端被定义为一个集群。对于一个租户,可以定义多个集群。在某些场景中,集群也被称为服务(Service)。在一个租户内,可以使用租户的路由转发表将流量转发给合适的集群。

(3)   后端子集群(Sub Cluster)。在多数据中心场景下,集群可以划分为多个子集群。通常,可以将集群中处于同一数据中心的后端定义为一个子集群。在某些场景中,子集群也被称为实例组(Instance Group)。子集群概念的引入,主要是为了处理多数据中心场景下的流量调度。


    下图中用一个例子对以上概念之间的关系做出了说明,其中包含2个租户。租户1配置了2个集群(集群A和集群B),这2个集群分别有2个子集群和1个子集群,各子集群有1~3个实例;租户2只配置了一个集群(集群C),集群C2个子集群,2个子集群各有2个实例。




4. BFE的转发过程


在HTTP请求到达BFE后,BFE的处理步骤如下:

  • 步骤 6:根据租户的分流规则,决定HTTP请求的目的集群。对于每个租户,可以配置一张独立的路由转发表。通过查找路由转发表,确定请求所属的目的集群。路由转发机制的详情将在后面的章节中介绍。在本案例中,通过查表确定对应的目的集群为demo-static。

  • 步骤 7:根据集群的内网流量调度策略,选择合适的子集群。对于每个BFE集群,可以针对每个集群的各子集群设置转发权重。BFE根据设置的转发权重来执行转发操作。内网流量调度机制的详情将在后面的章节中介绍。在本案例中,假设在IDC1的BFE集群上,demo-static的3个子集群对应的转发权重为(100, 0, 0),所以,确定转发的目标子集群为demo-static.idc1。

  • 步骤 8:根据集群的子集群负载均衡策略,选择合适的实例。对于每个集群,可以设置子集群的负载均衡策略,如WRR(Weighted Round Robin,加权轮询)、WLC(Weighted Least Connections,加权最小连接数)等。BFE根据子集群的负载均衡策略,在子集群中选择合适服务实例来处理请求。在本案例中,最终选择demo-static-01.idc1来处理请求。


BFE和Nginx有什么差异?- 转发模型的对比


5. BFE的转发表


BFE内对每个租户维护一张独立的转发表。对于每个属于该租户的请求,通过查询转发表获得目标集群。

转发表由多条“转发规则”组成。在查询时,对多条转发规则以顺序的方式查找;只要命中任何一条转发规则,就会结束退出,其中最后一条规则为“默认规则(Default)”。在所有转发规则都没有命中的时候,执行默认规则。

每条转发规则包含两部分:匹配条件和目标集群。其中匹配条件使用BFE自研的“条件表达式“来表述。

下面展示了一个转发表的例子。在这个例子中,包含以下3种服务集群。

(1)   静态集群(demo-static):服务静态流量。

(2)   post集群(demo-post):服务post流量。

(3)   main集群(demo-main):服务其他流量。


期望的转发逻辑如下:

(1)   对于Path以"/static"为前缀的,都发往demo-static集群。

(2)   请求方法为"POST"且Path以"/setting"为前缀的,都发往demo-post集群。

(3)   其他请求,都发往demo-main集群。


BFE和Nginx有什么差异?- 转发模型的对比


6. 附加处理的独立配置


在BFE中,为各扩展处理模块建立了独立的配置文件,这样可以降低配置维护的复杂性,避免配置之间的耦合。

 

以redirect功能为例,在目录conf/mod_redirect/下,可以看到mod_redirect.conf和redirect.data这两个配置文件。

      rewrite.data包含重定向规则,可动态加载。在安装包中,示例中的配置文件如下:


{
    "Version": "1",
    "Config": {
        "example_product": [
            {
                "Cond": "req_path_prefix_in(\"/redirect\", false)",
                "Actions": [
                    {
                        "Cmd": "URL_SET",
                        "Params": ["https://example.org"]
                    }
                ],
                "Status": 301
            }
        ]
    }
}



7. 总结


本文从“转发模型”的角度对Nginx和BFE进行了对比。

Nginx从Web Server出发,被“借用“于反向代理场景,在转发模型方面存在多处问题。在简单的应用场景下,这些问题可能还不明显;但是在较复杂和较大规模的场景下,这些问题会显现出来。

BFE 定位于“为企业级场景设计的现代七层负载均衡开源软件”,在设计中考虑了复杂业务场景的需求,可以支持复杂的转发规则,支持多数据中心和多容器云调度场景。

        由于篇幅所限,关于BFE转发模型的介绍比较粗略。有兴趣的读者可进一步查看《》中的说明。此书已由电子工业出版社正式出版,书名为》。


BFE和Nginx有什么差异?- 转发模型的对比


    可通过扫描下方的二维码优惠购买。


BFE开源项目
BFE(Beyond Front End)是一个基于Go语言编写的企业级七层负载均衡开源软件,具有高安全性和稳定性、功能快速开发、支持复杂场景、运维支持友好等优点。
4篇原创内容
Official Account

     

    点击下方的“阅读原文”,可以提交留言或发表评论。