BFE初探

项目简介

BFE是一个开源的七层负载均衡系统,和Nginx功能类似,但是比Nginx多了集群负载均衡功能、转发规则使用的是条件表达式(类似于表达式求值功能,Nginx使用的是正则表达式),提供了丰富的内部状态展示统计信息等。详情 

功能组件

BFE包含了多个组件,部分是可选的:

  • BFE Server: BFE数据平面核心转发模块(必选,已开源)

  • BFE-Reader: BFE日志分析模块,与BFE Server部署在一起,用于对BFE日志进行本地汇聚计算,降低后续计算处理的数据规模。

  • BFE-API Server: BFE控制平面API Server,其它控制平面模块以BFE-API Server为核心协同工作。

  • BFE-Aggregator: BFE日志数据实时聚合计算模块。

  • BFE-Scheduler: BFE流量调度器,基于流量、容量、网络距离及质量,自动计算全局负载均衡(GSLB)策略。

  • BFE-Controller: BFE集群控制器,执行常规控制任务,例如异常巡检及报警。

  • BFE-Web UI: BFE Web控制台。

  • 其它周边依赖系统, 例如缓存服务、非对称密码学算法计算服务等。

在上述组件中,只有 BFE-Server开源了,其他都尚未开源。

概念说明

产品线:Product,也被成为“租户”。BFE的配置,比如转发策略、权限等,是已产品线为单位来进行设置
集   群:Cluster,把具有同类功能的后端集合定义成为一个集群
子集群:Subcluster,集群又可细分成多个子集群,通常把处于同一个IDC的后端定义为子集群
实    例:Instance,每个子集群可包含多个后端服务实例,每个后端实例通过“IP地址+端口号”标识

比如:外卖产品线有多个服务集群(用户端、商家端、管理端等),其中用户端集群有N个子集群(DX,YF集群),每个子集群里面有多个服务实例

流量接入转发说明

流量接入与转发

  • Step 1-2:DNS解析

    • 请求的域名为 demo.example.com
    • 返回IP地址为 6.6.6.6(示例地址)
  • Step 3:用户与 6.6.6.6:80 建立TCP连接并发送HTTP请求,IP报文被路由到IDC1的入口,由四层负载均衡设施处理

  • Step 4:四层负载均衡设施将报文转发给下游BFE

  • Step 5:BFE收到HTTP请求, 确定处理该请求的产品线

    • BFE根据HTTP请求头中的Host字段, 确定产品线
    • 对于demo.example.com域名,假设对应的产品线名为demo
  • Step 6:BFE根据产品线的分流规则,选择该请求的目的集群

    • 对于这个请求,假设对应的目的集群为demo-static
    • 详见基于内容路由说明
  • Step 7-8:BFE根据产品线的均衡策略,选择子集群及实例

    • 对于这个请求,假设子集群为demo-static.idc1,实例为demo-static-01.idc1
    • 详见流量负载均衡说明
  • Step 9:请求被发往后端实例demo-static-01.idc1

  • Step 10:BFE收到后端实例回复的响应

  • Step 11-12:BFE通过四层负载均衡设施,将响应返回给用户

路由规则

根据流量接入转发模型中的流程,服务路由流程如下:

  • BFE根据HTTP请求头中的Host字段, 确定产品线
  • 根据产品线的分流规则,选择该请求的目的集群
  • 根据均衡策略,把请求转到具体的某个 子集群及实例 并把处理后的结果返回

示例

用户请求 demo.example.com,BFE根据HTTP请求中的Host字段,确定产品线为:demo

  • 产品线demo,包含以下3种服务集群:
    • 静态集群(demo-static):服务静态流量
    • post集群(demo-post):服务post流量
    • main集群(demo-main):服务其他流量
  • 期望的转发条件如下:
    • 对于path以"/static"为前缀的,都发往demo-static集群
    • 请求方法为"POST"、且path以"/setting"为前缀的,都发往demo-post
    • 其它请求,都发往demo-main
  • 对应以上要求,产品线demo的转发表如下图所示

Forwarding Table

负载均衡规则 

如何把流量均衡分配到集群中的多个子集群及其内部的实例?这个需求在多IDC场景中非常常见。 详情

另外,为了防止集群整体过载,也可以使用虚拟黑洞集群来主动丢弃(Blackhole)。

实现策略:

  • 设置子集群权重(分流比例),BFE根据配置设做加权轮询调度(WRR),把服务指向子集群;
  • 通一子集群内的多个实例之间,支持多种负载均衡算法:WRR加权轮询、WLC加权最小连接数,支持根据实例处理能力不同设置不同的权重。

健康检测:BFE为每个服务实例维护一个状态机,正常状态或不可用状态,对不可用状态亦会不断进行检测直至恢复可用。

失败重试机制:支持同子集群重试、跨子集群重试

连接池:支持短连接、连接池方式

会话保持:支持将相同来源请求转发至固定的业务后端(某个子集群或某个实例)

Quick Start

配置组织

BFE的核心配置是bfe.conf (conf/bfe.conf),为便于维护, 配置按功能分类存放在相应目录 conf/<feature>/

功能类别

文件位置

描述

服务基础配置

conf/bfe.conf

定义服务监听端口、超时时间、模块、session等

接入协议配置

conf/tls_conf/ 目录

密钥,协议支持等

流量路由配置

conf/server_data_conf/ 目录

host_rule.data:产品线域名表配置文件

vip规则、路由规则等

负载均衡配置

conf/cluster_conf/ 目录

 

扩展模块配置

conf/mod_<name> 目录

 

说明:

1.产品线域名表配置文件 : conf / server_data_conf / host_rule.data 

目的:实现企业多域名都指向同一product的需求,比如: abc.com / abc.cn 都由 productX 提供服务。

1{ 2 "Version": "init version", 3 "DefaultProduct": null, 4 "Hosts": { //域名标签和域名列表的映射关系表 5 "exampleTag1":[ //域名标签 6 "example1.org" //域名列表 7 "example2.org" 8 ], 9 "exampleTag2":[ 10 "xxx.org" 11 "zzz.org" 12 ] 13 }, 14 "HostTags": { //产品线和域名标签的映射关系 15 "example_product1":[ //产品线名称 16 "exampleTag1" //域名标签列表 17 ], 18 "product2":[ 19 "exampleTag2" 20 ] 21 } 22}

2.VIP规则配置文件 : conf / server_data_conf / vip_rule.data 

目的:vip_rule和host_rule类似,host_rule是通过域名路由到product;vip_rule通过请求来源的IP路由到product,vip_rule在host_rule失败时生效。在百度内部,BFE的前面是四层负载均衡,每个产品线一般都有固定的vip,所以vip也可以起到像域名一样的路由作用。

1{ 2 "Version": "init version", 3 "Vips": { //各产品线的VIP列表 4 "example_product": [ //产品线名称 5 "111.111.111.111" //VIP列表 6 ] 7 } 8}

3.路由分流配置文件:conf / server_data_conf / router_rule.data

目的:根据规则把请求路由到具体的集群

1{ 2 "Version": "init version", 3 "ProductRule": { //各产品线的分流规则配置 4 "example_product": [ //产品线名称 5 { 6 "Cond": "req_host_in(\"example.org\")", //分流条件, 语法详见Condition 7 "ClusterName": "cluster_example" //目的集群 8 }, 9 { 10 "Cond": "default_t()", 11 "ClusterName": "cluster_example" 12 } 13 ] 14 } 15}

4.集群转发规则配置文件:conf / server_data_conf / cluster_conf.data

目的:根据规则把请求路由到具体的集群

1{ 2 "Version": "init version", 3 "Config": { 4 "cluster_example": { //集群名称 5 "BackendConf": { //后端基础配置 6 "TimeoutConnSrv": 2000, //连接后端的超时时间,单位是毫秒,默认值2 7 "TimeoutResponseHeader": 50000, //从后端读响应头的超时时间,单位是毫秒,默认值60 8 "MaxIdleConnsPerHost": 0, //BFE实例与每个后端的最大空闲长连接数,默认值2 9 "RetryLevel": 0 //请求重试级别。0:连接后端失败时,进行重试;1:连接后端失败、转发GET请求失败时均进行重试,默认值0 10 }, 11 "CheckConf": { //健康检查配置 12 "Schem": "http", //健康检查协议,支持HTTP和TCP,默认值 HTTP 13 "Uri": "/healthcheck",//健康检查请求URI (仅HTTP),默认值 /health_check 14 "Host": "example.org", //健康检查请求HOST (仅HTTP),默认值 "" 15 "StatusCode": 200, //期待返回的响应状态码 (仅HTTP),默认值 0,代表任意状态码 16 "FailNum": 10, //健康检查启动阈值(转发请求连续失败FailNum次后,将后端实例置为不可用状态,并启动健康检查),默认值5 17 "SuccNum": 5, //健康检查成功阈值(健康检查连续成功SuccNum次后,将后端实例置为可用状态),默认值1 18 "CheckTimeout":500,//健康检查的超时时间,单位是毫秒,默认值0(无超时) 19 "CheckInterval": 1000 //健康检查的间隔时间,单位是毫秒,默认值1 20 }, 21 "GslbBasic": { //GSLB基础配置 22 "CrossRetry": 0, //跨子集群最大重试次数,默认值0 23 "RetryMax": 2, //子集群内最大重试次,默认值2 24 "BalanceMode":"WRR", //负载均衡模式(WRR: 加权轮询; WLC: 加权最小连接数),默认值WRR 25 "HashConf": { //会话保持的HASH策略配置 26 "HashStrategy": 0, //会话保持的哈希策(ClientIdOnly, ClientIpOnly, ClientIdPreferred),默认值ClientIpOnly 27 "HashHeader": "Cookie:UID", //会话保持的hash请求头 28 "SessionSticky": false, //是否开启会话保持(开启后,可以保证来源于同一个用户的请求可以发送到同一个后端),默认值false 29 } 30 }, 31 "ClusterBasic": { //集群基础配置 32 "TimeoutReadClient": 30000, //读用户请求wody的超时时间,单位为毫秒,默认值30 33 "TimeoutWriteClient": 60000, //写响应的超时时间,单位为毫秒,默认值60 34 "TimeoutReadClientAgain": 30000,//连接闲置超时时间,单位为毫秒,默认值60 35 "ReqWriteBufferSize": 512, //Write buffer size for request in byte 36 "ReqFlushInterval": 0,//Interval to flush request in ms. if zero, disable periodic flush 37 "ResFlushInterval": -1,//Interval to flush response in ms. if zero, disable periodic flush 38 "CancelOnClientClose": false //Cancel blocking operation on server if client connection disconnected 39 } 40 } 41 } 42}

5.负载均衡

  • 子集群负载均衡则配置文件:conf / cluster_conf / gslb.data

目的:各集群集群内的多个子集群直接分流比例(GSLB)

1{ 2 "Hostname": "", //配置文件生成来源信息 3 "Ts": "0", //配置文件生成的时间戳 4 "Clusters": { //各集群中子集群的分流权重 5 "cluster_example": { //集群名称 6 "GSLB_BLACKHOLE": 0, //GSLB_BLACKHOLE(保留,黑洞子集群),分配到该子集群的流量将被丢弃,用于过载保护, 0代表权重(不参与流量任务),子集群分流权重之和应等于 100 7 "example.bfe.bj": 100 // 子集群名 -> 子集群承接流量的权重 8 } 9 } 10}
  • 实例负载均衡则配置文件:conf / cluster_conf / cluster_table.data

目的:记录各后端集群包含的子集群及实例

1{ 2 "Version": "init version", 3 "Config": { //各集群信息配置 4 "cluster_example": { //集群名称 5 "example.bfe.bj": [ //子集群名称 6 { //子集群配置信息,包含多个实例配置 7 "Addr": "10.199.189.26", //实例监听地址 8 "Name": "example_hostname", //机器名称 9 "Port": 8181, //实例监听端口 10 "Weight": 10 //实例名称 11 } 12 ] 13 } 14 } 15}

6.名字规则配置文件:conf / server_data_conf / name_conf.data

目的:记录服务名字和服务实例的映射关系。BFE很多配置用的是bns(一种名字服务,一个名字可以解析为一组服务实例的ip和端口,权重)。name.conf可以配置本地的名字

1{ 2 "Version": "init version", 3 "Config": { //名字和实例的映射关系 4 "example.redis.cluster": [ //集群名称 5 { //实例信息 6 "Host": "192.168.1.1", //实例地址 7 "Port": 6439, //实例端口 8 "Weight": 10 //实例权重 9 } 10 ] 11 } 12}
点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )