Written by
aka.why
on
bfe业余分析(三)
简单分析下配置reload的逻辑。bfe中配置的加载分为主配置和模块配置。
模块配置
以bfe_modules/mod_block
为例。触发的web请求为/reload/mod_block.product_rule_table
,
/reload/mod_block.global_ip_table
。
简单逻辑就是注册对应的reload
的handler, 当出现对应的web请求时,
重新读取配置文件,生成对应的数据然后替换当前模块的配置。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
type ModuleBlock struct {
name string // name of module
state ModuleBlockState // module state
metrics metrics.Metrics
productRulePath string // path of block rule data file
ipBlacklistPath string // path of ip blacklist data file
/*
下面是对应的配置
*/
ruleTable *ProductRuleTable // table for product block rules
ipTable *ipdict.IPTable // table for global ip blacklist
}
....
/*
reload配置注册
*/
func (m *ModuleBlock) reloadHandlers() map[string]interface{} {
handlers := map[string]interface{}{
m.name + ".global_ip_table": m.loadGlobalIPTable,
m.name + ".product_rule_table": m.loadProductRuleConf,
}
return handlers
}
....
/*
看一下其中一个函数
*/
// loadProductRuleConf load from config file.
func (m *ModuleBlock) loadProductRuleConf(query url.Values) error {
// get path
path := query.Get("path")
if path == "" {
// use default
path = m.productRulePath
}
// load file
conf, err := ProductRuleConfLoad(path)
if err != nil {
return fmt.Errorf("err in ProductRuleConfLoad(%s):%s", path, err)
}
/*
里面就是加锁替换变量, 加锁原因是主流程会一直去查询这个变量
*/
m.ruleTable.Update(conf)
return nil
}
/*
请求处理逻辑
*/
// productBlockHandler is a handler for doing product block.
func (m *ModuleBlock) productBlockHandler(request *bfe_basic.Request) (
int, *bfe_http.Response) {
if openDebug {
log.Logger.Debug("%s check request", m.name)
}
m.state.ReqTotal.Inc(1)
// find block rules for given request
/* 这里会加锁 */
rules, ok := m.ruleTable.Search(request.Route.Product)
if !ok { // no rules found
if openDebug {
log.Logger.Debug("%s product %s not found, just pass",
m.name, request.Route.Product)
}
return bfe_module.BfeHandlerGoOn, nil
}
m.state.ReqToCheck.Inc(1)
return m.productRulesProcess(request, rules)
}
|
这块是全量加载
主配置
这里主要看下product的配置reload。
先看web入口函数(bfe_server/web_server.go
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
// reloadHandlers holds all reload handlers.
func (m *BfeMonitor) reloadHandlers() map[string]interface{} {
handlers := map[string]interface{}{
// for server data conf
"server_data_conf": m.srv.ServerDataConfReload,
// for gslb data conf
"gslb_data_conf": m.srv.GslbDataConfReload,
// for name conf
"name_conf": m.srv.NameConfReload,
// for tls
"tls_conf": m.srv.TLSConfReload,
"tls_session_ticket_key": m.srv.SessionTicketKeyReload,
}
return handlers
}
|
然后顺着看下对应的函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
// ServerDataConfReload reloads host/route/cluster conf
func (srv *BfeServer) ServerDataConfReload(query url.Values) error {
hostFile := srv.Config.Server.HostRuleConf
vipFile := srv.Config.Server.VipRuleConf
routeFile := srv.Config.Server.RouteRuleConf
clusterConfFile := srv.Config.Server.ClusterConf
path := query.Get("path")
if path != "" {
hostFile = joinPath(path, hostFile)
vipFile = joinPath(path, vipFile)
routeFile = joinPath(path, routeFile)
clusterConfFile = joinPath(path, clusterConfFile)
}
return srv.serverDataConfReload(hostFile, vipFile, routeFile, clusterConfFile)
}
func (srv *BfeServer) serverDataConfReload(hostFile, vipFile, routeFile, clusterConfFile string) error {
newServerConf, err := bfe_route.LoadServerDataConf(hostFile, vipFile, routeFile, clusterConfFile)
if err != nil {
log.Logger.Error("ServerDataConfReload():bfe_route.LoadServerDataConf: %s", err)
return err
}
/*
这里更新配置
*/
srv.confLock.Lock()
srv.ServerConf = newServerConf
srv.confLock.Unlock()
srv.ReverseProxy.setTransports(srv.ServerConf.ClusterTable.ClusterMap())
// set gslb basic
srv.balTable.SetGslbBasic(newServerConf.ClusterTable)
return nil
}
|
这段server配置使用时,是在生成request变量时直接赋值给它(bfe_server/http_conn.go
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
// Read next request from connection.
func (c *conn) readRequest() (request *bfe_basic.Request, err error) {
c.lr.N = int64(c.server.MaxHeaderBytes) + 4096 /* bufio slop */
var req *bfe_http.Request
// another request arrives
c.reqSN += 1
if req, err = bfe_http.ReadRequest(c.buf.Reader, c.server.MaxHeaderUriBytes); err != nil {
if c.lr.N == 0 {
return nil, errTooLarge
}
return nil, err
}
c.lr.N = noLimit
req.RemoteAddr = c.remoteAddr
req.State.SerialNumber = c.reqSN
req.State.Conn = c.rwc
reqStat := bfe_basic.NewRequestStat(req.State.StartTime)
reqStat.ReadReqEnd = time.Now()
reqStat.HeaderLenIn = int(req.State.HeaderSize)
/*
获取对应的server配置, 然后生成request。后续在查找host对应的product时直接使用该配置
*/
sf := c.server.GetServerConf()
return bfe_basic.NewRequest(req, c.rwc, reqStat, c.session, sf), nil
}
/*
安全的获取
*/
func (s *BfeServer) GetServerConf() *bfe_route.ServerDataConf {
s.confLock.RLock()
sf := s.ServerConf
s.confLock.RUnlock()
return sf
}
|