Nginx是一个被宽泛应用的反向代理(Reverse Proxy)开源软件。在“反向代理”这个方向上,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, 设置为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.comcluster_a
Host=www.b.comcluster_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中设计了“条件表达式”(Condition Expression)机制,以进步转发规定的可维护性,并升高性能进化的隐患。

(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蕴含重定向规定,可动静加载。在安装包中,示例中的配置文件如下:

{    "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》中的阐明。此书已由电子工业出版社正式出版,书名为《万亿级流量转发 - BFE核心技术与实现》。

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

欢送关注“BFE开源我的项目”公众号,取得本我的项目的更多更新。谢谢!