脾胃虚寒吃什么药| 莲子吃了有什么好处| 怕痒的男人意味着什么| 身份证号码代表什么| 苏打水喝了有什么好处| 炁是什么意思| 白带带血丝是什么原因| 十一月是什么星座的啊| ft什么单位| 疙瘩疤痕有什么方法可以去除| 95棉5氨纶是什么面料| 白羊座和什么座最配| 拉肚子吃什么水果好| 胆固醇高有什么症状| 红薯用什么繁殖| 头晕头疼挂什么科| 十月初是什么星座| 口是什么生肖| 胡同是什么意思| 目不暇接的意思是什么| 脚酸臭是什么原因| 人的五官是什么| 天蝎座和什么星座最不配| white是什么意思颜色| 鱼肝油什么时候吃最好| 水痘长什么样子| 生物冰袋里面是什么| 更年期出虚汗吃什么药| 哺乳期妈妈感冒了可以吃什么药| 牛和什么生肖最配| 胃溃疡适合吃什么水果| 萨瓦迪卡什么意思| 蛇为什么怕雄黄| 正常舌头是什么颜色| 左卵巢囊性结构是什么意思| herry是什么意思| 30度穿什么衣服合适| remember是什么意思| 什么样的人容易得心梗| ipmn是什么意思| 嗓子疼喝什么药| 牛顿三大定律是什么| 胃动力不足是什么原因造成的| 促甲状腺激素偏高有什么症状| 莫须有什么意思| 甲状腺结节3类什么意思| 河南为什么简称豫| 农历七月初七是什么节日| 娘娘命是什么样的命| 梦见黑蛇是什么意思| 小暑吃黄鳝有什么好处| 宫颈糜烂是什么原因引起的| 心率低有什么危害| 吃什么补血快| 1964年是什么命| 健康证需要检查什么| 维生素B1有什么副作用| 好的什么意思| 4月4日是什么日子| kpa是什么单位| 腹部彩超挂什么科| 臣附议是什么意思| 为什么鼻毛会变白| 手心为什么老出汗| 天干是什么| 坐以待毙是什么意思| 茱萸是什么东西| 膀胱不充盈什么意思| 杭盖是什么意思| 剁椒鱼头是什么鱼| 三个金读什么| 黄花胶是什么鱼的胶| 翊字五行属什么| 来例假不能吃什么东西| 中队长是什么级别| fob什么意思| 蛇盘疮吃什么药好得快| 七月半吃什么| 特警力量第二部叫什么| 慢性胃炎用什么药效果最好| 皮肤黄是什么原因| 炎性肉芽肿是什么意思| 2月23号是什么星座| 6朵玫瑰代表什么意思| 一什么晚霞| 北京是我国的什么中心| 应无所住而生其心什么意思| 突然头晕是什么原因| 胎位loa是什么位置| 要强的女人是什么性格| 太平猴魁是什么茶| 胎儿胆囊偏小有什么影响| 健脾益气是什么意思| lamer是什么牌子| 腰疼去医院挂什么科| 为什么身上老是痒| 手指上的斗和簸箕代表什么意思| 胃反酸吃什么药最好| 同型半胱氨酸是什么意思| 5月15日什么星座| 蒲公英什么功效| 1月26日是什么星座| 乔字五行属什么| 三月八号是什么星座| 圆脸适合什么发型短发| 一什么缸| 为什么老是打喷嚏| 哮喘咳嗽吃什么药好得快| 结肠炎吃什么药好| 什么生肖不能养龟| 镜子碎了有什么征兆吗| 左手小指疼痛预兆什么| 肺部小结节是什么意思| 为什么总是放屁很频繁| 譬如是什么意思| 窦炎是什么意思| 小孩咳嗽吃什么药好| 小马过河的故事告诉我们什么道理| 黑白蛇是什么蛇| 儿童疝气挂什么科| 粽子用什么叶子包| 尿沉渣检查什么| 为什么合欢树又叫鬼树| 硅油是什么| 头痛吃什么药好| 手麻脚麻是什么原因| 碘伏过敏是什么症状| 智力是什么意思| 股骨头坏死有什么症状| 肆无忌惮的意思是什么| 障碍是什么意思| 备孕需要做什么检查| 病毒感冒吃什么药| 胆固醇偏高有什么危害| 洋地黄中毒首选什么药| o型血不能和什么血型的人生孩子| 咳嗽黄痰吃什么药| 呋喃硫胺片治什么病| 血脂高吃什么药| 三生有幸是什么意思| 疖子是什么原因引起的| 断头婚是什么意思| 扬琴属于什么乐器| 喝白酒有什么好处| 泉州有什么特产| 什么中药补气血效果最好| merry是什么意思| 保守治疗是什么意思| 单飞是什么意思| 毛细血管扩张是什么原因引起的| 子息克乏是什么意思| 红薯和什么不能一起吃| 手指红肿是什么原因| 野人是什么意思| 决堤是什么意思| 血小板偏高是什么原因| babies是什么意思| 肿瘤和囊肿有什么区别| 疼风是什么原因引起的| 8.1是什么星座| 12月9日什么星座| 菊花有什么功效和作用| 甲胎蛋白偏高说明什么| 韩信点兵什么意思| 倒嗓是什么意思| 液体面包是什么| 梦见自己丢钱了什么征兆| 备孕去医院挂什么科| 脂蛋白a高吃什么药| 恨不相逢未嫁时什么意思| 矢量是什么意思| 眼皮红肿是什么原因引起的| 投资什么好| 错构瘤是什么| 移植后吃什么容易着床| 喝酒拉肚子吃什么药| 蜂蜡有什么用| 鼻子里流出黄水是什么原因| 吃什么降火| 壁虎吃什么食物| 高考什么时候恢复的| 拉肚子喝什么饮料| 头晕可以吃什么药| 闺六月是什么意思| 什么什么什么人| 甜瓜不能和什么一起吃| 护士要什么学历| 殚精竭虑是什么意思| 推介是什么意思| 痛风吃什么比较好| 天团是什么意思| gm是什么牌子| 指甲油用什么能洗掉| 嘴巴里苦是什么原因| 知了代表什么生肖| 喝苏打水有什么好处和坏处| 金牛座是什么象星座| 阿斯伯格综合症是什么| 孕妇血糖高有什么症状| 低压高是什么引起的| 有什么功效| 有什么好吃的零食| 戒指上的s925是什么意思| 冲菜是什么菜| 2019什么年| 钊读什么| 闭门思过是什么意思| 小孩肛门瘙痒什么原因| 小孩咳嗽是什么原因引起的| 4月出生是什么星座| 内膜居中是什么意思| 胃立康片适合什么病| 阿甘正传珍妮得了什么病| 现在是什么时辰| 无回声结节是什么意思| 脑梗是什么原因| 农历六月初四是什么日子| 反应停是什么药| 肾炎的饮食应注意什么| 贼眉鼠眼是什么生肖| 他叫什么名字| 非萎缩性胃炎是什么意思| 验孕棒一深一浅是什么意思| 生育酚是什么| 促胃动力药什么时候吃| 面部油腻是什么原因| 包饺子什么馅好吃| 补气血吃什么最好| 肠澼是什么意思| 盗窃是什么意思| 吃什么对子宫好| 忍辱负重是什么意思| 返聘是什么意思| dodo是什么意思| 十一月三号是什么星座| 谷维素是什么| 乳腺癌吃什么好| bug是什么意思中文翻译| 什么是鸡尾酒| 间是什么结构| 狮子座前面是什么星座| 黄体期出血是什么原因| 鼠配什么生肖最好| 戒备心是什么意思| a是什么| 血氯高是什么原因| neighborhood什么意思| 白芷是什么| 米果念什么| 蜘蛛吃什么| 房颤是什么病| 什么药| 见不得别人好是什么心理| 重孙是什么意思| 上嘴唇发黑是什么原因| 梦到僵尸是什么预兆| 红斑狼疮是什么症状能治好吗| 结婚15年是什么婚| 打酱油是什么意思啊| 女人吃鹅蛋有什么好处| c2m模式是什么意思| 脚冰凉是什么原因| 尿葡萄糖是什么意思| 硒片什么牌子好| 百度
Skip to content

Commit f373b3a

Browse files
author
liangchuan
committed
Add HTTPS backend support
Signed-off-by: liangchuan <liangchuan@yf-networks.com>
1 parent e2a7475 commit f373b3a

26 files changed

+2145
-98
lines changed

?bfe_balance/backend/health_check.go

Lines changed: 253 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,25 +17,36 @@
1717
package backend
1818

1919
import (
20+
"crypto/x509"
21+
"encoding/json"
2022
"fmt"
2123
"net"
2224
"net/http"
25+
"net/url"
26+
"regexp"
27+
"strconv"
2328
"strings"
2429
"time"
25-
)
2630

27-
import (
2831
"github.com/baidu/go-lib/log"
29-
)
3032

31-
import (
3233
"github.com/bfenetworks/bfe/bfe_config/bfe_cluster_conf/cluster_conf"
3334
"github.com/bfenetworks/bfe/bfe_debug"
35+
"github.com/bfenetworks/bfe/bfe_tls"
3436
)
3537

38+
type checkRtn struct {
39+
ok bool
40+
err error
41+
}
42+
3643
func UpdateStatus(backend *BfeBackend, cluster string) bool {
44+
var (
45+
checkConf *cluster_conf.BackendCheck
46+
httpConf *cluster_conf.BackendHTTPS
47+
)
3748
// get conf of health check, which is separately stored for each cluster
38-
checkConf := getCheckConf(cluster)
49+
checkConf, httpConf = getCheckConf(cluster)
3950
if checkConf == nil {
4051
// just ignore if not found health check conf
4152
return false
@@ -45,14 +56,15 @@ func UpdateStatus(backend *BfeBackend, cluster string) bool {
4556
// if backend's status become fail, start healthcheck.
4657
// at most start 1 check goroutine for each backend.
4758
if backend.UpdateStatus(*checkConf.FailNum) {
48-
go check(backend, cluster)
59+
go check(backend, cluster, httpConf)
4960
return true
5061
}
5162

5263
return false
5364
}
5465

55-
func check(backend *BfeBackend, cluster string) {
66+
func check(backend *BfeBackend, cluster string, httpConf *cluster_conf.BackendHTTPS) {
67+
5668
log.Logger.Info("start healthcheck for %s", backend.Name)
5769

5870
// backend close chan
@@ -67,7 +79,7 @@ loop:
6779
}
6880

6981
// get the latest conf to do health check
70-
checkConf := getCheckConf(cluster)
82+
checkConf, _ := getCheckConf(cluster)
7183
if checkConf == nil {
7284
// never come here
7385
time.Sleep(time.Second)
@@ -76,7 +88,7 @@ loop:
7688
checkInterval := time.Duration(*checkConf.CheckInterval) * time.Millisecond
7789

7890
// health check
79-
if ok, err := CheckConnect(backend, checkConf); !ok {
91+
if ok, err := CheckConnect(backend, checkConf, httpConf); !ok {
8092
backend.ResetSuccNum()
8193
if bfe_debug.DebugHealthCheck {
8294
log.Logger.Debug("backend %s still not avail (check failure: %s)", backend.Name, err)
@@ -150,6 +162,232 @@ func doHTTPHealthCheck(request *http.Request, timeout time.Duration) (int, error
150162
return response.StatusCode, nil
151163
}
152164

165+
// extractIP extract ip address
166+
func extractIP(rsAddr string) string {
167+
if strings.HasPrefix(rsAddr, "[") {
168+
// IPv6
169+
endIndex := strings.LastIndex(rsAddr, "]")
170+
if endIndex == -1 {
171+
return ""
172+
}
173+
ip := rsAddr[:endIndex+1]
174+
if net.ParseIP(ip[1:endIndex]) == nil {
175+
return ""
176+
}
177+
return ip
178+
} else {
179+
// IPv4
180+
ip := strings.Split(rsAddr, ":")[0]
181+
if net.ParseIP(ip) == nil {
182+
return ""
183+
}
184+
return ip
185+
}
186+
}
187+
188+
func getHostByType(host, rsAddr, hostType *string, def string) string {
189+
if hostType == nil {
190+
ht := cluster_conf.HostType_HOST
191+
hostType = &ht
192+
}
193+
switch *hostType {
194+
case cluster_conf.HostType_Instance_IP:
195+
if rsAddr != nil {
196+
return extractIP(*rsAddr)
197+
}
198+
default:
199+
if host != nil {
200+
return *host
201+
}
202+
}
203+
return def
204+
}
205+
206+
// add by liangc
207+
func checkHTTPSConnect(backend *BfeBackend, checkConf *cluster_conf.BackendCheck, httpConf *cluster_conf.BackendHTTPS) (bool, error) {
208+
var (
209+
err error
210+
conn net.Conn
211+
addrInfo = getHealthCheckAddrInfo(backend, checkConf)
212+
checkTimeout = 30 * time.Second
213+
statusCode = 0
214+
host string
215+
rootCAs *x509.CertPool = nil
216+
certs []bfe_tls.Certificate = nil
217+
cert bfe_tls.Certificate
218+
insecure = false
219+
uri = "/"
220+
checkRtnCh = make(chan checkRtn, 1)
221+
rtn checkRtn
222+
)
223+
224+
var (
225+
getStatusCodeFn = func(statusLine string) (int, error) {
226+
// "HTTP/1.1 200 OK"
227+
re, err := regexp.Compile(`\s(\d{3})\s`)
228+
if err != nil {
229+
return 0, err
230+
}
231+
matches := re.FindStringSubmatch(statusLine)
232+
if len(matches) == 2 {
233+
statusCode := matches[1]
234+
log.Logger.Debug("StatusCode = %s, raw = %s", statusCode, statusLine)
235+
return strconv.Atoi(statusCode)
236+
} else {
237+
return 0, fmt.Errorf("Status code not found: %s", statusLine)
238+
}
239+
}
240+
241+
doCheckFn = func(conn net.Conn) checkRtn {
242+
// TLS Check >>>>>>>
243+
if err = conn.(*bfe_tls.Conn).Handshake(); err != nil {
244+
log.Logger.Debug("debug_http err=%s", err.Error())
245+
return checkRtn{false, err}
246+
}
247+
if *checkConf.Schem == "tls" { // http or tls
248+
return checkRtn{true, nil}
249+
}
250+
// TLS Check <<<<<<<
251+
252+
// HTTPS Check vvvvvvvvvvvvv
253+
if checkConf.Uri != nil && *checkConf.Uri != "" {
254+
uri = *checkConf.Uri
255+
}
256+
request := fmt.Sprintf("GET %s HTTP/1.1\r\n"+
257+
"Host: %s\r\n"+
258+
"User-Agent: BFE-Health-Check\r\n"+
259+
"\r\n", uri, host)
260+
_, err = conn.Write([]byte(request))
261+
if err != nil {
262+
log.Logger.Debug("debug_http err=%s", err.Error())
263+
return checkRtn{false, err}
264+
}
265+
var (
266+
response = ""
267+
ok bool
268+
err error
269+
data = make([]byte, 0)
270+
bufSz = 128
271+
buf = make([]byte, bufSz)
272+
total = 0
273+
)
274+
//TODO: if timeout , how to handle ?
275+
for {
276+
total, err = conn.Read(buf)
277+
if err != nil {
278+
break
279+
}
280+
data = append(data, buf[:total]...)
281+
if total < bufSz {
282+
break
283+
}
284+
}
285+
//data, err = ioutil.ReadAll(conn)
286+
if err != nil {
287+
log.Logger.Debug("debug_http err=%s", err.Error())
288+
return checkRtn{false, err}
289+
}
290+
response = string(data)
291+
log.Logger.Debug("<- Request:\n%s", request)
292+
log.Logger.Debug("-> Response:\n%s", response)
293+
if checkConf.StatusCode != nil { // check status code
294+
var (
295+
s string
296+
arr = strings.Split(response, "\n")
297+
)
298+
if len(arr) > 0 {
299+
s = strings.ToUpper(arr[0])
300+
statusCode, err = getStatusCodeFn(s)
301+
if err != nil {
302+
return checkRtn{false, err}
303+
}
304+
if checkConf.StatusCodeRange != nil && *checkConf.StatusCodeRange != "" {
305+
log.Logger.Debug("statusCode=%d, statusCodeRange=%s", statusCode, *checkConf.StatusCodeRange)
306+
ok, err := cluster_conf.MatchStatusCodeRange(fmt.Sprintf("%d", statusCode), *checkConf.StatusCodeRange)
307+
return checkRtn{ok, err}
308+
}
309+
}
310+
ok, err = cluster_conf.MatchStatusCode(statusCode, *checkConf.StatusCode)
311+
}
312+
return checkRtn{ok, err}
313+
}
314+
315+
toStringFn = func(o interface{}) string {
316+
b, err := json.Marshal(o)
317+
if err != nil {
318+
return err.Error()
319+
}
320+
return string(b)
321+
}
322+
)
323+
324+
if checkConf.CheckTimeout != nil {
325+
checkTimeout = time.Duration(*checkConf.CheckTimeout) * time.Millisecond
326+
}
327+
conn, err = net.DialTimeout("tcp", addrInfo, checkTimeout)
328+
329+
if err != nil {
330+
log.Logger.Debug("debug_http err=%v", err)
331+
return false, err
332+
}
333+
334+
defer func() {
335+
if r := recover(); r != nil {
336+
log.Logger.Debug("recover_panic = %v", r)
337+
}
338+
_ = conn.Close()
339+
}()
340+
341+
_, err = url.Parse(fmt.Sprintf("%s://%s%s", "http", addrInfo, *checkConf.Uri))
342+
if err != nil {
343+
log.Logger.Debug("debug_http err=%v", err)
344+
return false, err
345+
}
346+
347+
serverName := ""
348+
if httpConf.RSHost != nil {
349+
serverName = *httpConf.RSHost
350+
} else if checkConf.Host != nil {
351+
serverName = *checkConf.Host
352+
}
353+
host = getHostByType(checkConf.Host, &addrInfo, checkConf.HostType, serverName)
354+
355+
rootCAs, err = httpConf.GetRSCAList()
356+
357+
if cert, err = httpConf.GetBFECert(); err == nil {
358+
certs = []bfe_tls.Certificate{cert}
359+
}
360+
361+
if httpConf.RSInsecureSkipVerify != nil {
362+
insecure = *httpConf.RSInsecureSkipVerify
363+
}
364+
365+
conn = bfe_tls.Client(conn, &bfe_tls.Config{
366+
Certificates: certs,
367+
InsecureSkipVerify: true,
368+
ServerName: host,
369+
RootCAs: rootCAs,
370+
VerifyPeerCertificate: bfe_tls.NewVerifyPeerCertHooks(insecure, host, rootCAs).Ready(),
371+
})
372+
373+
log.Logger.Debug("httpCheck conf=%s", toStringFn(checkConf))
374+
go func(conn net.Conn, rtnCh chan checkRtn) {
375+
rtnCh <- doCheckFn(conn)
376+
}(conn, checkRtnCh)
377+
378+
if checkTimeout > 0 {
379+
select {
380+
case rtn = <-checkRtnCh:
381+
return rtn.ok, rtn.err
382+
case <-time.Tick(checkTimeout):
383+
return false, fmt.Errorf("http checkTimeout %dms", checkTimeout/time.Millisecond)
384+
}
385+
} else {
386+
rtn = <-checkRtnCh
387+
}
388+
return rtn.ok, rtn.err
389+
}
390+
153391
func checkHTTPConnect(backend *BfeBackend, checkConf *cluster_conf.BackendCheck) (bool, error) {
154392
// prepare health check request
155393
addrInfo := getHealthCheckAddrInfo(backend, checkConf)
@@ -182,26 +420,28 @@ func checkHTTPConnect(backend *BfeBackend, checkConf *cluster_conf.BackendCheck)
182420
}
183421

184422
// CheckConnect checks whether backend server become available.
185-
func CheckConnect(backend *BfeBackend, checkConf *cluster_conf.BackendCheck) (bool, error) {
423+
func CheckConnect(backend *BfeBackend, checkConf *cluster_conf.BackendCheck, httpConf *cluster_conf.BackendHTTPS) (bool, error) {
186424
switch *checkConf.Schem {
187425
case "http":
188426
return checkHTTPConnect(backend, checkConf)
189427
case "tcp":
190428
return checkTCPConnect(backend, checkConf)
429+
case "http", "tls":
430+
return checkHTTPSConnect(backend, checkConf, httpConf)
191431
default:
192432
// never come here
193433
return checkHTTPConnect(backend, checkConf)
194434
}
195435
}
196436

197437
// CheckConfFetcher returns current health check conf for cluster.
198-
type CheckConfFetcher func(cluster string) *cluster_conf.BackendCheck
438+
type CheckConfFetcher func(name string) (*cluster_conf.BackendCheck, *cluster_conf.BackendHTTPS)
199439

200440
var checkConfFetcher CheckConfFetcher
201441

202-
func getCheckConf(cluster string) *cluster_conf.BackendCheck {
442+
func getCheckConf(cluster string) (*cluster_conf.BackendCheck, *cluster_conf.BackendHTTPS) {
203443
if checkConfFetcher == nil {
204-
return nil
444+
return nil, nil
205445
}
206446
return checkConfFetcher(cluster)
207447
}

0 commit comments

Comments
?(0)
什么样的女人最吸引男人的心 坐地能吸土是什么意思 钙过量会有什么症状 九价是什么意思 男人为什么会遗精
三剑客是什么意思 一个虫一个离念什么 健身后应该吃什么 甲子年是什么意思 祖宗是什么意思
任性妄为是什么意思 四个火念什么 徐才厚什么级别 彪悍是什么意思 二椅子什么意思
什么鸟叫声最好听 天才是指什么生肖 素什么意思 2003年出生属什么 梦到死去的亲人是什么意思
肠炎吃什么药最好hcv8jop2ns9r.cn 午餐吃什么好又能减肥hcv8jop2ns7r.cn 经期头疼是什么原因怎么办hcv9jop3ns8r.cn 男孩流鼻血是什么原因hcv8jop4ns7r.cn eyki是什么牌子的手表hcv8jop3ns9r.cn
年岁是什么意思hcv9jop1ns0r.cn 推是什么意思hcv7jop9ns9r.cn 节育环嵌顿是什么意思mmeoe.com 眉毛里面长痘痘是什么原因hlguo.com 入定是什么意思bjhyzcsm.com
绝膑而亡是什么意思hcv9jop4ns8r.cn 女人梦见下雪是什么征兆hcv8jop7ns7r.cn 舌面有裂纹是什么原因hcv7jop6ns7r.cn 老打嗝什么原因hcv9jop2ns1r.cn fans是什么意思hcv8jop2ns5r.cn
骨质疏松有什么症状表现hcv8jop0ns0r.cn 胆固醇过高有什么危害sanhestory.com 吃什么降血脂最快hcv9jop1ns3r.cn 两个b型血能生出什么血型的孩子hcv9jop4ns5r.cn 皮肤黑的人穿什么颜色的衣服显白helloaicloud.com
百度