- path: string 路径
- splicing: int 当客户端支持cookie时,将会固定使用后端多少秒
- pathAdd: bool 将客户端访问的路径附加在path上 例:/api/req => /ws => /ws/api/req
- - matcher 将会附加到每个backs前
+ - dealer 将会附加到每个backs前
- backs: [] 后端, 可以动态增加/删除
- name: string 后端名称,将在日志中显示
- to: string 后端地址,例"s://www.baidu.com",会根据客户端自动添加http or ws在地址前
- weight: int 权重,按routes中的全部back的权重比分配,当权重变为0时,将停止新请求的进入
- - errBanSec: int 当后端错误时(指连接失败,不指后端错误响应),将会禁用若干秒
- - matcher
+ - dealer
-matcher:
+dealer:
+- errToSec: int 当后端响应超过(ws则指初次返回时间)指定秒,将会触发errBanSec
+- errBanSec: int 当后端错误时(指连接失败,不指后端错误响应),将会禁用若干秒
- reqHeader: [] 请求后端前,请求头处理器, 可以动态增加/删除
- action: string 可选access、deny、replace、add、del、set。
- key: string 具体处理哪个头
var backIs []*Back
if t, e := r.Cookie("_psign_" + cookie); e == nil {
if backP, ok := route.backMap.Load(t.Value); ok && backP.(*Back).IsLive() && HeaderMatchs(backP.(*Back).ReqHeader, r) {
- backP.(*Back).PathAdd = route.PathAdd
- backP.(*Back).Splicing = route.Splicing
- backP.(*Back).tmp.ReqHeader = append(route.ReqHeader, backP.(*Back).ReqHeader...)
- backP.(*Back).tmp.ResHeader = append(route.ResHeader, backP.(*Back).ResHeader...)
- backP.(*Back).tmp.ReqBody = append(route.ReqBody, backP.(*Back).ReqBody...)
+ backP.(*Back).cloneDealer()
for i := 0; i < backP.(*Back).Weight; i++ {
backIs = append(backIs, backP.(*Back))
}
Splicing int `json:"splicing"`
PathAdd bool `json:"pathAdd"`
- Matcher
+ Dealer
backMap sync.Map `json:"-"`
Backs []Back `json:"backs"`
}
}
-// func (t *Route) GenBack() []*Back {
-// var backLink []*Back
-// for i := 0; i < len(t.Back); i++ {
-// back := &t.Back[i]
-// back.SwapSign()
-// if back.Weight == 0 {
-// continue
-// }
-// tmpBack := Back{
-// Name: back.Name,
-// Splicing: t.Splicing,
-// Sign: back.Sign,
-// To: back.To,
-// Weight: back.Weight,
-// ErrBanSec: back.ErrBanSec,
-// PathAdd: t.PathAdd,
-// MatchHeader: append(t.MatchHeader, back.MatchHeader...),
-// ReqHeader: append(t.ReqHeader, back.ReqHeader...),
-// ResHeader: append(t.ResHeader, back.ResHeader...),
-// }
-// for i := 1; i <= back.Weight; i++ {
-// backLink = append(backLink, &tmpBack)
-// }
-// }
-// return backLink
-// }
-
func (t *Route) FiliterBackByRequest(r *http.Request) []*Back {
var backLink []*Back
for i := 0; i < len(t.Backs); i++ {
if t.Backs[i].IsLive() && HeaderMatchs(t.Backs[i].ReqHeader, r) {
- t.Backs[i].PathAdd = t.PathAdd
- t.Backs[i].Splicing = t.Splicing
- t.Backs[i].tmp.ReqHeader = append(t.ReqHeader, t.Backs[i].ReqHeader...)
- t.Backs[i].tmp.ResHeader = append(t.ResHeader, t.Backs[i].ResHeader...)
- t.Backs[i].tmp.ReqBody = append(t.ReqBody, t.Backs[i].ReqBody...)
+ t.Backs[i].cloneDealer()
for k := 0; k < t.Backs[i].Weight; k++ {
backLink = append(backLink, &t.Backs[i])
}
lock sync.RWMutex `json:"-"`
upT time.Time `json:"-"`
- Name string `json:"name"`
- To string `json:"to"`
- Weight int `json:"weight"`
- ErrBanSec int `json:"errBanSec"`
+ Name string `json:"name"`
+ To string `json:"to"`
+ Weight int `json:"weight"`
Splicing int `json:"-"`
PathAdd bool `json:"-"`
- Matcher
- tmp Matcher `json:"-"`
+ Dealer
+ tmp Dealer `json:"-"`
+}
+
+func (t *Back) cloneDealer() {
+ t.PathAdd = t.route.PathAdd
+ if t.route.Splicing != 0 {
+ t.Splicing = t.route.Splicing
+ }
+ if t.route.ErrBanSec != 0 {
+ t.ErrBanSec = t.route.ErrBanSec
+ }
+ if t.route.ErrToSec != 0 {
+ t.ErrToSec = t.route.ErrToSec
+ }
+ t.tmp.ReqHeader = append(t.route.ReqHeader, t.ReqHeader...)
+ t.tmp.ResHeader = append(t.route.ResHeader, t.ResHeader...)
+ t.tmp.ReqBody = append(t.route.ReqBody, t.ReqBody...)
}
func (t *Back) Id() string {
t.upT = time.Now().Add(time.Second * time.Duration(t.ErrBanSec))
}
-type Matcher struct {
+type Dealer struct {
+ ErrToSec int `json:"errToSec"`
+ ErrBanSec int `json:"errBanSec"`
ReqHeader []Header `json:"reqHeader"`
ResHeader []Header `json:"resHeader"`
ReqBody []Body `json:"reqBody"`
return errors.New("后端故障")
}
- logger.Debug(`T:`, fmt.Sprintf("%v > %v > %v http ok %v", chosenBack.route.config.Addr, routePath, chosenBack.Name, time.Since(opT)))
+ if chosenBack.ErrToSec != 0 && time.Since(opT).Seconds() > float64(chosenBack.ErrToSec) {
+ logger.Warn(`W:`, fmt.Sprintf("%v > %v > %v http 超时响应 %v", chosenBack.route.config.Addr, routePath, chosenBack.Name, time.Since(opT)))
+ chosenBack.Disable()
+ } else {
+ logger.Debug(`T:`, fmt.Sprintf("%v > %v > %v http ok %v", chosenBack.route.config.Addr, routePath, chosenBack.Name, time.Since(opT)))
+ }
{
cookie := &http.Cookie{
return errors.New("后端故障")
}
- logger.Debug(`T:`, fmt.Sprintf("%v > %v > %v ws ok %v", chosenBack.route.config.Addr, routePath, chosenBack.Name, time.Since(opT)))
+ if chosenBack.ErrToSec != 0 && time.Since(opT).Seconds() > float64(chosenBack.ErrToSec) {
+ logger.Warn(`W:`, fmt.Sprintf("%v > %v > %v ws 超时响应 %v", chosenBack.route.config.Addr, routePath, chosenBack.Name, time.Since(opT)))
+ chosenBack.Disable()
+ } else {
+ logger.Debug(`T:`, fmt.Sprintf("%v > %v > %v ws ok %v", chosenBack.route.config.Addr, routePath, chosenBack.Name, time.Since(opT)))
+ }
{
cookie := &http.Cookie{