fix bug,optimize performance

This commit is contained in:
yuzuki999 2022-06-05 13:19:39 +08:00
parent 3eadd58da4
commit 5434e86d93
5 changed files with 81 additions and 51 deletions

View File

@ -50,6 +50,7 @@ type Client struct {
RemoteRuleCache *Rule RemoteRuleCache *Rule
access sync.Mutex access sync.Mutex
NodeInfoRspMd5 [16]byte NodeInfoRspMd5 [16]byte
NodeRuleRspMd5 [16]byte
UserListCheckNum int UserListCheckNum int
} }

View File

@ -2,6 +2,7 @@ package api
import ( import (
"bufio" "bufio"
"bytes"
md52 "crypto/md5" md52 "crypto/md5"
"fmt" "fmt"
"github.com/go-resty/resty/v2" "github.com/go-resty/resty/v2"
@ -76,7 +77,7 @@ type SSConfig struct {
type V2rayConfig struct { type V2rayConfig struct {
Inbounds []conf.InboundDetourConfig `json:"inbounds"` Inbounds []conf.InboundDetourConfig `json:"inbounds"`
Routing *struct { Routing *struct {
Rules []Rule `json:"rules"` Rules *json.RawMessage `json:"rules"`
} `json:"routing"` } `json:"routing"`
} }
@ -104,10 +105,6 @@ func (c *Client) GetNodeInfo() (nodeInfo *NodeInfo, err error) {
switch c.NodeType { switch c.NodeType {
case "V2ray": case "V2ray":
path = "/api/v1/server/Deepbwork/config" path = "/api/v1/server/Deepbwork/config"
res, err = c.client.R().
SetQueryParam("local_port", "1").
ForceContentType("application/json").
Get(path)
case "Trojan": case "Trojan":
path = "/api/v1/server/TrojanTidalab/config" path = "/api/v1/server/TrojanTidalab/config"
case "Shadowsocks": case "Shadowsocks":
@ -119,13 +116,6 @@ func (c *Client) GetNodeInfo() (nodeInfo *NodeInfo, err error) {
default: default:
return nil, fmt.Errorf("unsupported Node type: %s", c.NodeType) return nil, fmt.Errorf("unsupported Node type: %s", c.NodeType)
} }
md := md52.Sum(res.Body())
if c.NodeInfoRspMd5 != [16]byte{} {
if c.NodeInfoRspMd5 == md {
return nil, nil
}
}
c.NodeInfoRspMd5 = md
res, err = c.client.R(). res, err = c.client.R().
SetQueryParam("local_port", "1"). SetQueryParam("local_port", "1").
ForceContentType("application/json"). ForceContentType("application/json").
@ -134,12 +124,25 @@ func (c *Client) GetNodeInfo() (nodeInfo *NodeInfo, err error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
i := bytes.Index(res.Body(), []byte("outbo"))
md := md52.Sum(res.Body()[:i])
nodeIsNotChange := false
if c.NodeInfoRspMd5 != [16]byte{} {
if c.NodeInfoRspMd5 == md {
nodeIsNotChange = true
}
}
c.NodeInfoRspMd5 = md
c.access.Lock() c.access.Lock()
defer c.access.Unlock() defer c.access.Unlock()
switch c.NodeType { switch c.NodeType {
case "V2ray": case "V2ray":
nodeInfo, err = c.ParseV2rayNodeResponse(res.Body()) md2 := md52.Sum(res.Body()[i:])
nodeInfo, err = c.ParseV2rayNodeResponse(res.Body(), nodeIsNotChange, c.NodeRuleRspMd5 != md2)
case "Trojan": case "Trojan":
if nodeIsNotChange {
return nil, nil
}
nodeInfo, err = c.ParseTrojanNodeResponse(res.Body()) nodeInfo, err = c.ParseTrojanNodeResponse(res.Body())
} }
return nodeInfo, nil return nodeInfo, nil
@ -147,7 +150,7 @@ func (c *Client) GetNodeInfo() (nodeInfo *NodeInfo, err error) {
func (c *Client) GetNodeRule() (*[]DetectRule, error) { func (c *Client) GetNodeRule() (*[]DetectRule, error) {
ruleList := c.LocalRuleList ruleList := c.LocalRuleList
if c.NodeType != "V2ray" { if c.NodeType != "V2ray" || c.RemoteRuleCache == nil {
return &ruleList, nil return &ruleList, nil
} }
@ -162,6 +165,7 @@ func (c *Client) GetNodeRule() (*[]DetectRule, error) {
} }
ruleList = append(ruleList, ruleListItem) ruleList = append(ruleList, ruleListItem)
} }
c.RemoteRuleCache = nil
return &ruleList, nil return &ruleList, nil
} }
@ -211,18 +215,24 @@ func (c *Client) ParseSSNodeResponse() (*NodeInfo, error) {
} }
// ParseV2rayNodeResponse parse the response for the given nodeinfor format // ParseV2rayNodeResponse parse the response for the given nodeinfor format
func (c *Client) ParseV2rayNodeResponse(body []byte) (*NodeInfo, error) { func (c *Client) ParseV2rayNodeResponse(body []byte, notParseNode, parseRule bool) (*NodeInfo, error) {
node := &NodeInfo{V2ray: &V2rayConfig{}} node := &NodeInfo{V2ray: &V2rayConfig{}}
err := json.Unmarshal(body, node.V2ray) err := json.Unmarshal(body, node.V2ray)
if err != nil { if err != nil {
return nil, fmt.Errorf("unmarshal nodeinfo error: %s", err) return nil, fmt.Errorf("unmarshal nodeinfo error: %s", err)
} }
if parseRule {
json.Unmarshal(*node.V2ray.Routing.Rules, c.RemoteRuleCache)
}
node.V2ray.Routing = nil
if notParseNode {
return nil, nil
}
node.SpeedLimit = uint64(c.SpeedLimit * 1000000 / 8) node.SpeedLimit = uint64(c.SpeedLimit * 1000000 / 8)
node.DeviceLimit = c.DeviceLimit node.DeviceLimit = c.DeviceLimit
node.NodeType = c.NodeType node.NodeType = c.NodeType
node.NodeId = c.NodeID node.NodeId = c.NodeID
c.RemoteRuleCache = &node.V2ray.Routing.Rules[0]
node.V2ray.Routing = nil
if c.EnableXTLS { if c.EnableXTLS {
node.TLSType = "xtls" node.TLSType = "xtls"
} else { } else {

View File

@ -69,15 +69,18 @@ func (c *Client) GetUserList() (UserList *[]UserInfo, err error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("unmarshal userlist error: %s", err) return nil, fmt.Errorf("unmarshal userlist error: %s", err)
} }
checkNum := userList.Data[len(userList.Data)-1].UID + l := len(userList.Data)
userList.Data[len(userList.Data)/2-1].UID + checkNum := userList.Data[l-1].UID +
userList.Data[l/2-1].UID +
userList.Data[0].UID userList.Data[0].UID
if c.UserListCheckNum != 0 { if c.UserListCheckNum != 0 {
if c.UserListCheckNum == checkNum { if c.UserListCheckNum == checkNum {
return nil, nil return nil, nil
} }
} }
c.UserListCheckNum = userList.Data[len(userList.Data)-1].UID c.UserListCheckNum = userList.Data[l-1].UID +
userList.Data[l/2-1].UID +
userList.Data[0].UID
return &userList.Data, nil return &userList.Data, nil
} }

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"log" "log"
"math" "math"
"reflect"
"runtime" "runtime"
"time" "time"
@ -99,6 +100,7 @@ func (c *Controller) Start() error {
time.Sleep(time.Duration(c.config.UpdatePeriodic) * time.Second) time.Sleep(time.Duration(c.config.UpdatePeriodic) * time.Second)
_ = c.userReportPeriodic.Start() _ = c.userReportPeriodic.Start()
}() }()
runtime.GC()
return nil return nil
} }
@ -131,6 +133,7 @@ func (c *Controller) nodeInfoMonitor() (err error) {
var nodeInfoChanged = false var nodeInfoChanged = false
// If nodeInfo changed // If nodeInfo changed
if newNodeInfo != nil { if newNodeInfo != nil {
if !reflect.DeepEqual(c.nodeInfo, newNodeInfo) {
// Remove old tag // Remove old tag
oldtag := c.Tag oldtag := c.Tag
err := c.removeOldTag(oldtag) err := c.removeOldTag(oldtag)
@ -153,12 +156,13 @@ func (c *Controller) nodeInfoMonitor() (err error) {
return nil return nil
} }
} }
}
// Check Rule // Check Rule
if !c.config.DisableGetRule { if !c.config.DisableGetRule {
if ruleList, err := c.apiClient.GetNodeRule(); err != nil { if ruleList, err := c.apiClient.GetNodeRule(); err != nil {
log.Printf("Get rule list filed: %s", err) log.Printf("Get rule list filed: %s", err)
} else if len(*ruleList) > 0 { } else if ruleList != nil {
if err := c.UpdateRule(c.Tag, *ruleList); err != nil { if err := c.UpdateRule(c.Tag, *ruleList); err != nil {
log.Print(err) log.Print(err)
} }
@ -185,9 +189,6 @@ func (c *Controller) nodeInfoMonitor() (err error) {
log.Print(err) log.Print(err)
return nil return nil
} }
if newUserInfo == nil {
return nil
}
if nodeInfoChanged { if nodeInfoChanged {
if newUserInfo != nil { if newUserInfo != nil {
c.userList = newUserInfo c.userList = newUserInfo
@ -197,12 +198,15 @@ func (c *Controller) nodeInfoMonitor() (err error) {
log.Print(err) log.Print(err)
return nil return nil
} }
newNodeInfo = nil
// Add Limiter // Add Limiter
if err := c.AddInboundLimiter(c.Tag, newUserInfo); err != nil { if err := c.AddInboundLimiter(c.Tag, newUserInfo); err != nil {
log.Print(err) log.Print(err)
return nil return nil
} }
} else { newUserInfo = nil
runtime.GC()
} else if newUserInfo != nil {
deleted, added := compareUserList(c.userList, newUserInfo) deleted, added := compareUserList(c.userList, newUserInfo)
if len(deleted) > 0 { if len(deleted) > 0 {
deletedEmail := make([]string, len(deleted)) deletedEmail := make([]string, len(deleted))
@ -229,8 +233,9 @@ func (c *Controller) nodeInfoMonitor() (err error) {
log.Printf("[%s: %d] %d user deleted, %d user added", c.nodeInfo.NodeType, c.nodeInfo.NodeId, log.Printf("[%s: %d] %d user deleted, %d user added", c.nodeInfo.NodeType, c.nodeInfo.NodeId,
len(deleted), len(added)) len(deleted), len(added))
c.userList = newUserInfo c.userList = newUserInfo
} newUserInfo = nil
runtime.GC() runtime.GC()
}
return nil return nil
} }
@ -361,11 +366,11 @@ func compareUserList(old, new *[]api.UserInfo) (deleted, added []int) {
func (c *Controller) userInfoMonitor() (err error) { func (c *Controller) userInfoMonitor() (err error) {
// Get User traffic // Get User traffic
userTraffic := make([]api.UserTraffic, 0) userTraffic := make([]api.UserTraffic, 0)
for _, user := range *c.userList { for i := range *c.userList {
up, down := c.getTraffic(c.buildUserTag(&user)) up, down := c.getTraffic(c.buildUserTag(&(*c.userList)[i]))
if up > 0 || down > 0 { if up > 0 || down > 0 {
userTraffic = append(userTraffic, api.UserTraffic{ userTraffic = append(userTraffic, api.UserTraffic{
UID: user.UID, UID: (*c.userList)[i].UID,
Upload: up, Upload: up,
Download: down}) Download: down})
} }
@ -389,6 +394,8 @@ func (c *Controller) userInfoMonitor() (err error) {
} else { } else {
log.Printf("[%s: %d] Report %d illegal behaviors", c.nodeInfo.NodeType, c.nodeInfo.NodeId, len(*detectResult)) log.Printf("[%s: %d] Report %d illegal behaviors", c.nodeInfo.NodeType, c.nodeInfo.NodeId, len(*detectResult))
} }
userTraffic = nil
runtime.GC()
return nil return nil
} }

View File

@ -16,7 +16,9 @@ import (
func InboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.InboundHandlerConfig, error) { func InboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.InboundHandlerConfig, error) {
var proxySetting interface{} var proxySetting interface{}
if nodeInfo.NodeType == "V2ray" { if nodeInfo.NodeType == "V2ray" {
defer func() { nodeInfo.V2ray = nil }() defer func() {
nodeInfo.V2ray = nil
}()
if nodeInfo.EnableVless { if nodeInfo.EnableVless {
nodeInfo.V2ray.Inbounds[0].Protocol = "vless" nodeInfo.V2ray.Inbounds[0].Protocol = "vless"
// Enable fallback // Enable fallback
@ -40,7 +42,10 @@ func InboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.I
proxySetting = &conf.VMessInboundConfig{} proxySetting = &conf.VMessInboundConfig{}
} }
} else if nodeInfo.NodeType == "Trojan" { } else if nodeInfo.NodeType == "Trojan" {
defer func() { nodeInfo.V2ray = nil; nodeInfo.Trojan = nil }() defer func() {
nodeInfo.V2ray = nil
nodeInfo.Trojan = nil
}()
nodeInfo.V2ray = &api.V2rayConfig{} nodeInfo.V2ray = &api.V2rayConfig{}
nodeInfo.V2ray.Inbounds = make([]conf.InboundDetourConfig, 1) nodeInfo.V2ray.Inbounds = make([]conf.InboundDetourConfig, 1)
nodeInfo.V2ray.Inbounds[0].Protocol = "trojan" nodeInfo.V2ray.Inbounds[0].Protocol = "trojan"
@ -63,6 +68,10 @@ func InboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.I
t := conf.TransportProtocol(nodeInfo.SS.TransportProtocol) t := conf.TransportProtocol(nodeInfo.SS.TransportProtocol)
nodeInfo.V2ray.Inbounds[0].StreamSetting = &conf.StreamConfig{Network: &t} nodeInfo.V2ray.Inbounds[0].StreamSetting = &conf.StreamConfig{Network: &t}
} else if nodeInfo.NodeType == "Shadowsocks" { } else if nodeInfo.NodeType == "Shadowsocks" {
defer func() {
nodeInfo.V2ray = nil
nodeInfo.SS = nil
}()
defer func() { nodeInfo.V2ray = nil; nodeInfo.SS = nil }() defer func() { nodeInfo.V2ray = nil; nodeInfo.SS = nil }()
nodeInfo.V2ray = &api.V2rayConfig{} nodeInfo.V2ray = &api.V2rayConfig{}
nodeInfo.V2ray.Inbounds = []conf.InboundDetourConfig{{Protocol: "shadowsocks"}} nodeInfo.V2ray.Inbounds = []conf.InboundDetourConfig{{Protocol: "shadowsocks"}}