重写健康检查
This commit is contained in:
@@ -1,29 +1 @@
|
||||
package health_check_http
|
||||
|
||||
import "github.com/eolinker/apinto/discovery"
|
||||
|
||||
// agent 从属于HTTPCheck,实现了IHealthChecker接口
|
||||
type agent struct {
|
||||
agentID string
|
||||
checker *HTTPCheck
|
||||
}
|
||||
|
||||
// NewAgent 创建agent
|
||||
func NewAgent(agentID string, checker *HTTPCheck) discovery.IHealthChecker {
|
||||
return &agent{agentID: agentID, checker: checker}
|
||||
}
|
||||
|
||||
// AddToCheck 将节点添加进HTTPCheck的检查列表
|
||||
func (a *agent) AddToCheck(node discovery.BaseNode) error {
|
||||
a.checker.addToCheck(&checkNode{
|
||||
node: node,
|
||||
agentID: a.agentID,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
// Stop 停止agent并且将HTTPCheck中属于该agent的正在检查的所有节点都移除
|
||||
func (a *agent) Stop() error {
|
||||
a.checker.stop(a.agentID)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -11,7 +11,10 @@ import (
|
||||
"github.com/eolinker/eosc/log"
|
||||
|
||||
"github.com/eolinker/apinto/discovery"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
var (
|
||||
_ discovery.IHealthChecker = (*HTTPCheck)(nil)
|
||||
)
|
||||
|
||||
// NewHTTPCheck 创建HTTPCheck
|
||||
@@ -22,32 +25,36 @@ func NewHTTPCheck(config Config) *HTTPCheck {
|
||||
config: &config,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
ch: make(chan *checkNode, 10),
|
||||
|
||||
client: &http.Client{},
|
||||
locker: sync.RWMutex{},
|
||||
}
|
||||
go checker.doCheckLoop()
|
||||
|
||||
return checker
|
||||
}
|
||||
|
||||
// HTTPCheck HTTP健康检查结构,实现了IHealthChecker接口
|
||||
type HTTPCheck struct {
|
||||
config *Config
|
||||
nodes discovery.INodes
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
ch chan *checkNode
|
||||
delCh chan string
|
||||
|
||||
client *http.Client
|
||||
locker sync.RWMutex
|
||||
}
|
||||
|
||||
func (h *HTTPCheck) Check(nodes discovery.INodes) {
|
||||
go h.doCheckLoop(nodes)
|
||||
}
|
||||
|
||||
// doCheckLoop 定时检查,维护了一个待检测节点集合
|
||||
func (h *HTTPCheck) doCheckLoop() {
|
||||
func (h *HTTPCheck) doCheckLoop(nodes discovery.INodes) {
|
||||
if h.config.Period < 1 {
|
||||
return
|
||||
}
|
||||
ticker := time.NewTicker(h.config.Period)
|
||||
nodes := map[string]map[string]*checkNode{}
|
||||
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
select {
|
||||
@@ -55,84 +62,43 @@ func (h *HTTPCheck) doCheckLoop() {
|
||||
return
|
||||
case <-ticker.C:
|
||||
{
|
||||
nodes = h.check(nodes)
|
||||
}
|
||||
//接收待检测节点并存入待检测节点集合
|
||||
case node, ok := <-h.ch:
|
||||
{
|
||||
if ok {
|
||||
if _, ok := nodes[node.agentID]; !ok {
|
||||
nodes[node.agentID] = make(map[string]*checkNode)
|
||||
}
|
||||
nodes[node.agentID][node.node.ID()] = node
|
||||
}
|
||||
}
|
||||
//接收agentID,并将待检测集合中属于该agent的所有节点移除
|
||||
case agentID, ok := <-h.delCh:
|
||||
{
|
||||
if ok {
|
||||
delete(nodes, agentID)
|
||||
}
|
||||
h.check(nodes.All())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Agent 生成一个agent
|
||||
func (h *HTTPCheck) Agent() (discovery.IHealthChecker, error) {
|
||||
return NewAgent(uuid.NewString(), h), nil
|
||||
}
|
||||
|
||||
// Reset 重置HTTPCheck的配置
|
||||
func (h *HTTPCheck) Reset(conf Config) error {
|
||||
h.config = &conf
|
||||
func (h *HTTPCheck) Reset(conf interface{}) error {
|
||||
cf, ok := conf.(Config)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
h.reset(&cf)
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddToCheck 将节点添加进HTTPCheck的检查列表
|
||||
func (h *HTTPCheck) AddToCheck(node discovery.BaseNode) error {
|
||||
h.addToCheck(&checkNode{
|
||||
node: node,
|
||||
agentID: "",
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
// addToCheck 将节点传入HTTPCheck的检测Channel
|
||||
func (h *HTTPCheck) addToCheck(node *checkNode) error {
|
||||
h.ch <- node
|
||||
return nil
|
||||
func (h *HTTPCheck) reset(conf *Config) {
|
||||
h.config = conf
|
||||
}
|
||||
|
||||
// Stop 停止HTTPCheck,中止定时检查
|
||||
func (h *HTTPCheck) Stop() error {
|
||||
func (h *HTTPCheck) Stop() {
|
||||
h.cancel()
|
||||
return nil
|
||||
}
|
||||
|
||||
// stop 停止从属该agentID的所有节点的健康检查
|
||||
func (h *HTTPCheck) stop(agentID string) {
|
||||
h.delCh <- agentID
|
||||
}
|
||||
|
||||
// check 对待检查的节点集合进行检测,入参:nodes map[agentID][nodeID]*checkNode
|
||||
func (h *HTTPCheck) check(nodes map[string]map[string]*checkNode) map[string]map[string]*checkNode {
|
||||
//将待检测节点集合中地址相同的节点整合在一起,结构为:map[node.Addr][]*checkNode
|
||||
newNodes := make(map[string][]*checkNode)
|
||||
for _, ns := range nodes {
|
||||
for _, n := range ns {
|
||||
if n.node.Status() == discovery.Down {
|
||||
newNodes[n.node.Addr()] = append(newNodes[n.node.Addr()], n)
|
||||
}
|
||||
}
|
||||
}
|
||||
func (h *HTTPCheck) check(nodes []discovery.INode) {
|
||||
|
||||
/*对每个节点地址进行检测
|
||||
成功则将属于该地址的所有节点的状态都置于可运行,并从HTTPCheck维护的待检测节点列表中移除
|
||||
失败则下次定时检查再进行检测
|
||||
*/
|
||||
for addr, ns := range newNodes {
|
||||
uri := fmt.Sprintf("%s://%s/%s", h.config.Protocol, strings.TrimSuffix(addr, "/"), strings.TrimPrefix(h.config.URL, "/"))
|
||||
for _, ns := range nodes {
|
||||
if ns.Status() != discovery.Down {
|
||||
continue
|
||||
}
|
||||
uri := fmt.Sprintf("%s://%s/%s", h.config.Protocol, strings.TrimSuffix(ns.Addr(), "/"), strings.TrimPrefix(h.config.URL, "/"))
|
||||
h.client.Timeout = h.config.Timeout
|
||||
request, err := http.NewRequest(h.config.Method, uri, nil)
|
||||
if err != nil {
|
||||
@@ -149,16 +115,6 @@ func (h *HTTPCheck) check(nodes map[string]map[string]*checkNode) map[string]map
|
||||
log.Error(err)
|
||||
continue
|
||||
}
|
||||
for _, n := range ns {
|
||||
n.node.Up()
|
||||
delete(nodes[n.agentID], n.node.ID())
|
||||
}
|
||||
ns.Up()
|
||||
}
|
||||
return nodes
|
||||
}
|
||||
|
||||
// checkNode 进入检查channel的节点结构
|
||||
type checkNode struct {
|
||||
node discovery.BaseNode
|
||||
agentID string
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user