add node fail filter

This commit is contained in:
rui.zheng
2017-11-14 17:50:02 +08:00
parent da30584df1
commit 3befde0128
4 changed files with 217 additions and 144 deletions
+73 -19
View File
@@ -1,16 +1,17 @@
package gost
import (
"fmt"
"net/url"
"strings"
"sync"
"sync/atomic"
"time"
)
// Node is a proxy node, mainly used to construct a proxy chain.
type Node struct {
ID int
Addr string
IPs []string
Host string
Protocol string
Transport string
@@ -20,7 +21,9 @@ type Node struct {
DialOptions []DialOption
HandshakeOptions []HandshakeOption
Client *Client
Selector IPSelector
group *NodeGroup
failCount uint32
failTime time.Time
}
// ParseNode parses the node info.
@@ -83,38 +86,89 @@ func ParseNode(s string) (node Node, err error) {
return
}
// MarkDead marks the node fail status.
func (node *Node) MarkDead() {
atomic.AddUint32(&node.failCount, 1)
node.failTime = time.Now()
if node.group == nil {
return
}
for i := range node.group.nodes {
if node.group.nodes[i].ID == node.ID {
atomic.AddUint32(&node.group.nodes[i].failCount, 1)
node.group.nodes[i].failTime = time.Now()
break
}
}
}
// ResetDead resets the node fail status.
func (node *Node) ResetDead() {
atomic.StoreUint32(&node.failCount, 0)
node.failTime = time.Time{}
if node.group == nil {
return
}
for i := range node.group.nodes {
if node.group.nodes[i].ID == node.ID {
atomic.StoreUint32(&node.group.nodes[i].failCount, 0)
node.group.nodes[i].failTime = time.Time{}
break
}
}
}
func (node *Node) String() string {
return fmt.Sprintf("%d@%s", node.ID, node.Addr)
}
// NodeGroup is a group of nodes.
type NodeGroup struct {
nodes []Node
Options []SelectOption
Selector NodeSelector
mutex sync.Mutex
mFails map[string]int // node -> fail count
MaxFails int
FailTimeout int
Retries int
ID int
nodes []Node
Options []SelectOption
Selector NodeSelector
}
// NewNodeGroup creates a node group
func NewNodeGroup(nodes ...Node) *NodeGroup {
return &NodeGroup{
nodes: nodes,
mFails: make(map[string]int),
nodes: nodes,
}
}
// AddNode adds node or node list into group
func (ng *NodeGroup) AddNode(node ...Node) {
if ng == nil {
func (group *NodeGroup) AddNode(node ...Node) {
if group == nil {
return
}
ng.nodes = append(ng.nodes, node...)
group.nodes = append(group.nodes, node...)
}
// Nodes returns node list in the group
func (ng *NodeGroup) Nodes() []Node {
if ng == nil {
func (group *NodeGroup) Nodes() []Node {
if group == nil {
return nil
}
return ng.nodes
return group.nodes
}
// Next selects the next node from group.
// It also selects IP if the IP list exists.
func (group *NodeGroup) Next() (node Node, err error) {
selector := group.Selector
if selector == nil {
selector = &defaultSelector{}
}
// select node from node group
node, err = selector.Select(group.Nodes(), group.Options...)
if err != nil {
return
}
node.group = group
return
}