github.com/TeaOSLab/EdgeNode@v1.3.8/internal/nodes/origin_state_manager.go (about) 1 // Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. 2 3 package nodes 4 5 import ( 6 "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs" 7 teaconst "github.com/TeaOSLab/EdgeNode/internal/const" 8 "github.com/TeaOSLab/EdgeNode/internal/events" 9 "github.com/TeaOSLab/EdgeNode/internal/goman" 10 "github.com/TeaOSLab/EdgeNode/internal/remotelogs" 11 "github.com/TeaOSLab/EdgeNode/internal/trackers" 12 "github.com/iwind/TeaGo/Tea" 13 "sync" 14 "time" 15 ) 16 17 var SharedOriginStateManager = NewOriginStateManager() 18 19 func init() { 20 if !teaconst.IsMain { 21 return 22 } 23 24 events.On(events.EventLoaded, func() { 25 goman.New(func() { 26 SharedOriginStateManager.Start() 27 }) 28 }) 29 events.On(events.EventQuit, func() { 30 SharedOriginStateManager.Stop() 31 }) 32 } 33 34 const ( 35 maxOriginStates = 512 // 最多可以监控的源站状态数量 36 ) 37 38 // OriginStateManager 源站状态管理 39 type OriginStateManager struct { 40 stateMap map[int64]*OriginState // originId => *OriginState 41 42 ticker *time.Ticker 43 locker sync.RWMutex 44 } 45 46 // NewOriginStateManager 获取新管理对象 47 func NewOriginStateManager() *OriginStateManager { 48 return &OriginStateManager{ 49 stateMap: map[int64]*OriginState{}, 50 ticker: time.NewTicker(60 * time.Second), 51 } 52 } 53 54 // Start 启动 55 func (this *OriginStateManager) Start() { 56 if Tea.IsTesting() { 57 this.ticker = time.NewTicker(10 * time.Second) 58 } 59 for range this.ticker.C { 60 err := this.Loop() 61 if err != nil { 62 remotelogs.Error("ORIGIN_MANAGER", err.Error()) 63 } 64 } 65 } 66 67 func (this *OriginStateManager) Stop() { 68 if this.ticker != nil { 69 this.ticker.Stop() 70 } 71 } 72 73 // Loop 单次循环检查 74 func (this *OriginStateManager) Loop() error { 75 var nodeConfig = sharedNodeConfig // 复制 76 if nodeConfig == nil { 77 return nil 78 } 79 80 var tr = trackers.Begin("CHECK_ORIGIN_STATES") 81 defer tr.End() 82 83 var currentStates = []*OriginState{} 84 this.locker.Lock() 85 for originId, state := range this.stateMap { 86 // 检查Origin是否正在使用 87 var originConfig = nodeConfig.FindOrigin(originId) 88 if originConfig == nil || !originConfig.IsOn { 89 delete(this.stateMap, originId) 90 continue 91 } 92 state.Config = originConfig 93 currentStates = append(currentStates, state) 94 } 95 this.locker.Unlock() 96 97 if len(currentStates) == 0 { 98 return nil 99 } 100 101 var count = len(currentStates) 102 var wg = &sync.WaitGroup{} 103 wg.Add(count) 104 for _, state := range currentStates { 105 go func(state *OriginState) { 106 defer wg.Done() 107 conn, _, err := OriginConnect(state.Config, 0, "", state.TLSHost) 108 if err == nil { 109 _ = conn.Close() 110 111 // 已经恢复正常 112 this.locker.Lock() 113 state.Config.IsOk = true 114 delete(this.stateMap, state.Config.Id) 115 this.locker.Unlock() 116 117 var reverseProxy = state.ReverseProxy 118 if reverseProxy != nil { 119 reverseProxy.ResetScheduling() 120 } 121 } 122 }(state) 123 } 124 wg.Wait() 125 126 return nil 127 } 128 129 // Fail 添加失败的源站 130 func (this *OriginStateManager) Fail(origin *serverconfigs.OriginConfig, tlsHost string, reverseProxy *serverconfigs.ReverseProxyConfig, callback func()) { 131 if origin == nil || origin.Id <= 0 { 132 return 133 } 134 135 this.locker.Lock() 136 state, ok := this.stateMap[origin.Id] 137 var timestamp = time.Now().Unix() 138 if ok { 139 if state.UpdatedAt < timestamp-300 { // N 分钟之后重新计数 140 state.CountFails = 0 141 state.Config.IsOk = true 142 } 143 144 state.TLSHost = tlsHost 145 state.CountFails++ 146 state.Config = origin 147 state.ReverseProxy = reverseProxy 148 state.UpdatedAt = timestamp 149 150 if origin.IsOk { 151 origin.IsOk = state.CountFails < 5 // 超过 N 次之后认为是异常 152 153 if !origin.IsOk { 154 if callback != nil { 155 callback() 156 } 157 } 158 } 159 } else { 160 // 同时最多监控 N 个源站地址 161 if len(this.stateMap) < maxOriginStates { 162 this.stateMap[origin.Id] = &OriginState{ 163 CountFails: 1, 164 Config: origin, 165 TLSHost: tlsHost, 166 ReverseProxy: reverseProxy, 167 UpdatedAt: timestamp, 168 } 169 } 170 171 origin.IsOk = true 172 } 173 this.locker.Unlock() 174 } 175 176 // Success 添加成功的源站 177 func (this *OriginStateManager) Success(origin *serverconfigs.OriginConfig, callback func()) { 178 if origin == nil || origin.Id <= 0 { 179 return 180 } 181 182 if !origin.IsOk { 183 if callback != nil { 184 defer callback() 185 } 186 } 187 188 origin.IsOk = true 189 this.locker.Lock() 190 delete(this.stateMap, origin.Id) 191 this.locker.Unlock() 192 } 193 194 // IsAvailable 检查是否正常 195 func (this *OriginStateManager) IsAvailable(originId int64) bool { 196 if originId <= 0 { 197 return true 198 } 199 200 this.locker.RLock() 201 _, ok := this.stateMap[originId] 202 this.locker.RUnlock() 203 204 return !ok 205 }