前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >BFE和Nginx有什么差异?- 转发模型的对比

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

作者头像
CNCF
发布2021-08-26 10:18:07
7180
发布2021-08-26 10:18:07
举报
文章被收录于专栏:CNCFCNCF

提示:本文较长,且涉及部分配置,点击文章最下方的“阅读原文” 在手机或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_aupstream cluster_a { server 192.168.1.1:8080; server 192.168.1.2:8080;} # 定义转发目标集群cluster_bupstream 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, 设置为anyproxy_pass http://cluster_a;# 转发给cluste_a }} # 定义www.b.com的转发规则server { listen 80; server_name www.b.com; # host location / { # path,设置为anyproxy_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.com3、在后的,如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)。子集群概念的引入,主要是为了处理多数据中心场景下的流量调度。

(4) 后端实例(Instance)。每个子集群可包含多个后端服务实例(Instance),每个后端实例通过"IP地址 + 端口号"标识。

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

4. BFE的转发过程

下面使用一个例子来说BFE的转发流程。例子的场景如下图所示。客户端首先经过DNS解析,获得目的IP地址(步骤1-2)。之后请求首先被发送到四层负载均衡(步骤3),然后再转发给BFE(步骤4)。

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

  • 步骤 5:确定HTTP请求所属的租户。BFE可以根据HTTP请求头中的“Host”字段或HTTP请求的目标IP地址来确定租户。在本案例中,针对HTTP请求头中demo.example.com域名,BFE找到对应的租户为demo。
  • 步骤 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来处理请求。

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集群。

6. 附加处理的独立配置

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

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

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

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

7. 总结

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

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

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-08-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 CNCF 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 对Nginx的分析
    • 1.1 Nginx的转发配置
    • 2. BFE和Nginx的差异
    • 3. BFE转发中的基本概念
    • 4. BFE的转发过程
    • 5. BFE的转发表
    • 6. 附加处理的独立配置
    • 7. 总结
    相关产品与服务
    负载均衡
    负载均衡(Cloud Load Balancer,CLB)提供安全快捷的流量分发服务,访问流量经由 CLB 可以自动分配到云中的多台后端服务器上,扩展系统的服务能力并消除单点故障。负载均衡支持亿级连接和千万级并发,可轻松应对大流量访问,满足业务需求。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档