mirror of
https://github.com/wyx2685/V2bX.git
synced 2025-01-23 02:18:13 -05:00
performance optimization
This commit is contained in:
parent
5fd09079e3
commit
53b330b4e8
@ -11,19 +11,20 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UserInfo struct {
|
type UserLimitInfo struct {
|
||||||
UID int
|
UID int
|
||||||
SpeedLimit uint64
|
SpeedLimit uint64
|
||||||
ExpireTime int64
|
ExpireTime int64
|
||||||
DeviceLimit int
|
//DeviceLimit int
|
||||||
}
|
}
|
||||||
|
|
||||||
type InboundInfo struct {
|
type InboundInfo struct {
|
||||||
Tag string
|
Tag string
|
||||||
NodeSpeedLimit uint64
|
NodeSpeedLimit uint64
|
||||||
UserInfo *sync.Map // Key: Uid value: UserInfo
|
NodeDeviceLimit int
|
||||||
SpeedLimiter *sync.Map // key: Uid, value: *ratelimit.Bucket
|
UserLimitInfo *sync.Map // Key: Uid value: UserLimitInfo
|
||||||
UserOnlineIP *sync.Map // Key: Uid Value: *sync.Map: Key: IP, Value: bool
|
SpeedLimiter *sync.Map // key: Uid, value: *ratelimit.Bucket
|
||||||
|
UserOnlineIP *sync.Map // Key: Uid Value: *sync.Map: Key: IP, Value: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type Limiter struct {
|
type Limiter struct {
|
||||||
@ -36,47 +37,24 @@ func NewLimiter() *Limiter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Limiter) AddInboundLimiter(tag string, nodeInfo *panel.NodeInfo, userList []panel.UserInfo) error {
|
func (l *Limiter) AddInboundLimiter(tag string, nodeInfo *panel.NodeInfo) error {
|
||||||
inboundInfo := &InboundInfo{
|
inboundInfo := &InboundInfo{
|
||||||
Tag: tag,
|
Tag: tag,
|
||||||
NodeSpeedLimit: nodeInfo.SpeedLimit,
|
NodeSpeedLimit: nodeInfo.SpeedLimit,
|
||||||
SpeedLimiter: new(sync.Map),
|
NodeDeviceLimit: nodeInfo.DeviceLimit,
|
||||||
UserOnlineIP: new(sync.Map),
|
SpeedLimiter: new(sync.Map),
|
||||||
|
UserOnlineIP: new(sync.Map),
|
||||||
}
|
}
|
||||||
userMap := new(sync.Map)
|
inboundInfo.UserLimitInfo = new(sync.Map)
|
||||||
for i := range userList {
|
|
||||||
/*if (*userList)[i].SpeedLimit == 0 {
|
|
||||||
(*userList)[i].SpeedLimit = nodeInfo.SpeedLimit
|
|
||||||
}
|
|
||||||
if (*userList)[i].DeviceLimit == 0 {
|
|
||||||
(*userList)[i].DeviceLimit = nodeInfo.DeviceLimit
|
|
||||||
}*/
|
|
||||||
userMap.Store(fmt.Sprintf("%s|%s|%d", tag, (userList)[i].V2rayUser.Email, (userList)[i].UID),
|
|
||||||
&UserInfo{
|
|
||||||
UID: (userList)[i].UID,
|
|
||||||
SpeedLimit: nodeInfo.SpeedLimit,
|
|
||||||
DeviceLimit: nodeInfo.DeviceLimit,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
inboundInfo.UserInfo = userMap
|
|
||||||
l.InboundInfo.Store(tag, inboundInfo) // Replace the old inbound info
|
l.InboundInfo.Store(tag, inboundInfo) // Replace the old inbound info
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Limiter) UpdateInboundLimiter(tag string, nodeInfo *panel.NodeInfo, added, deleted []panel.UserInfo) error {
|
func (l *Limiter) UpdateInboundLimiter(tag string, deleted []panel.UserInfo) error {
|
||||||
if value, ok := l.InboundInfo.Load(tag); ok {
|
if value, ok := l.InboundInfo.Load(tag); ok {
|
||||||
inboundInfo := value.(*InboundInfo)
|
inboundInfo := value.(*InboundInfo)
|
||||||
// Update User info
|
|
||||||
for i := range added {
|
|
||||||
inboundInfo.UserInfo.Store(fmt.Sprintf("%s|%s|%d", tag,
|
|
||||||
(added)[i].V2rayUser.Email, (added)[i].UID), &UserInfo{
|
|
||||||
UID: (added)[i].UID,
|
|
||||||
SpeedLimit: nodeInfo.SpeedLimit,
|
|
||||||
DeviceLimit: nodeInfo.DeviceLimit,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
for i := range deleted {
|
for i := range deleted {
|
||||||
inboundInfo.UserInfo.Delete(fmt.Sprintf("%s|%s|%d", tag,
|
inboundInfo.UserLimitInfo.Delete(fmt.Sprintf("%s|%s|%d", tag,
|
||||||
(deleted)[i].V2rayUser.Email, (deleted)[i].UID))
|
(deleted)[i].V2rayUser.Email, (deleted)[i].UID))
|
||||||
inboundInfo.SpeedLimiter.Delete(fmt.Sprintf("%s|%s|%d", tag,
|
inboundInfo.SpeedLimiter.Delete(fmt.Sprintf("%s|%s|%d", tag,
|
||||||
(deleted)[i].V2rayUser.Email, (deleted)[i].UID)) // Delete limiter bucket
|
(deleted)[i].V2rayUser.Email, (deleted)[i].UID)) // Delete limiter bucket
|
||||||
@ -92,16 +70,14 @@ func (l *Limiter) DeleteInboundLimiter(tag string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Limiter) UpdateUserSpeedLimit(tag string, userInfo *panel.UserInfo, limit uint64, expire int64) error {
|
func (l *Limiter) AddUserSpeedLimit(tag string, userInfo *panel.UserInfo, limit uint64, expire int64) error {
|
||||||
if value, ok := l.InboundInfo.Load(tag); ok {
|
if value, ok := l.InboundInfo.Load(tag); ok {
|
||||||
inboundInfo := value.(*InboundInfo)
|
inboundInfo := value.(*InboundInfo)
|
||||||
if user, ok := inboundInfo.UserInfo.Load(fmt.Sprintf("%s|%s|%d", tag, userInfo.GetUserEmail(), userInfo.UID)); ok {
|
userLimit := &UserLimitInfo{
|
||||||
user.(*UserInfo).SpeedLimit = limit
|
SpeedLimit: limit,
|
||||||
user.(*UserInfo).ExpireTime = time.Now().Add(time.Duration(expire) * time.Second).Unix()
|
ExpireTime: time.Now().Add(time.Duration(expire) * time.Second).Unix(),
|
||||||
inboundInfo.SpeedLimiter.Delete(fmt.Sprintf("%s|%s|%d", tag, userInfo.GetUserEmail(), userInfo.UID))
|
|
||||||
} else {
|
|
||||||
return fmt.Errorf("no such user in limiter: %s", userInfo.GetUserEmail())
|
|
||||||
}
|
}
|
||||||
|
inboundInfo.UserLimitInfo.Store(fmt.Sprintf("%s|%s|%d", tag, userInfo.GetUserEmail(), userInfo.UID), userLimit)
|
||||||
return nil
|
return nil
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("no such inbound in limiter: %s", tag)
|
return fmt.Errorf("no such inbound in limiter: %s", tag)
|
||||||
@ -128,9 +104,9 @@ func (l *Limiter) ListOnlineUserIp(tag string) ([]UserIpList, error) {
|
|||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
if len(ip) > 0 {
|
if len(ip) > 0 {
|
||||||
if u, ok := inboundInfo.UserInfo.Load(key.(string)); ok {
|
if u, ok := inboundInfo.UserLimitInfo.Load(key.(string)); ok {
|
||||||
onlineUser = append(onlineUser, UserIpList{
|
onlineUser = append(onlineUser, UserIpList{
|
||||||
Uid: u.(*UserInfo).UID,
|
Uid: u.(*UserLimitInfo).UID,
|
||||||
IpList: ip,
|
IpList: ip,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -192,17 +168,15 @@ func (l *Limiter) CheckSpeedAndDeviceLimit(tag string, email string, ip string)
|
|||||||
inboundInfo := value.(*InboundInfo)
|
inboundInfo := value.(*InboundInfo)
|
||||||
nodeLimit := inboundInfo.NodeSpeedLimit
|
nodeLimit := inboundInfo.NodeSpeedLimit
|
||||||
var userLimit uint64 = 0
|
var userLimit uint64 = 0
|
||||||
var deviceLimit = 0
|
|
||||||
expired := false
|
expired := false
|
||||||
if v, ok := inboundInfo.UserInfo.Load(email); ok {
|
if v, ok := inboundInfo.UserLimitInfo.Load(email); ok {
|
||||||
u := v.(*UserInfo)
|
u := v.(*UserLimitInfo)
|
||||||
if u.ExpireTime < time.Now().Unix() && u.ExpireTime != 0 {
|
if u.ExpireTime < time.Now().Unix() && u.ExpireTime != 0 {
|
||||||
userLimit = 0
|
userLimit = 0
|
||||||
expired = true
|
expired = true
|
||||||
} else {
|
} else {
|
||||||
userLimit = u.SpeedLimit
|
userLimit = u.SpeedLimit
|
||||||
}
|
}
|
||||||
deviceLimit = u.DeviceLimit
|
|
||||||
}
|
}
|
||||||
ipMap := new(sync.Map)
|
ipMap := new(sync.Map)
|
||||||
ipMap.Store(ip, true)
|
ipMap.Store(ip, true)
|
||||||
@ -216,7 +190,7 @@ func (l *Limiter) CheckSpeedAndDeviceLimit(tag string, email string, ip string)
|
|||||||
counter++
|
counter++
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
if counter > deviceLimit && deviceLimit > 0 {
|
if counter > inboundInfo.NodeDeviceLimit && inboundInfo.NodeDeviceLimit > 0 {
|
||||||
ipMap.Delete(ip)
|
ipMap.Delete(ip)
|
||||||
return nil, false, true
|
return nil, false, true
|
||||||
}
|
}
|
||||||
@ -226,12 +200,13 @@ func (l *Limiter) CheckSpeedAndDeviceLimit(tag string, email string, ip string)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
limit := determineRate(nodeLimit, userLimit) // If need the Speed limit
|
limit := determineSpeedLimit(nodeLimit, userLimit) // If you need the Speed limit
|
||||||
if limit > 0 {
|
if limit > 0 {
|
||||||
limiter := ratelimit.NewBucketWithQuantum(time.Second, int64(limit), int64(limit)) // Byte/s
|
limiter := ratelimit.NewBucketWithQuantum(time.Second, int64(limit), int64(limit)) // Byte/s
|
||||||
if v, ok := inboundInfo.SpeedLimiter.LoadOrStore(email, limiter); ok {
|
if v, ok := inboundInfo.SpeedLimiter.LoadOrStore(email, limiter); ok {
|
||||||
if expired {
|
if expired {
|
||||||
inboundInfo.SpeedLimiter.Store(email, limiter)
|
inboundInfo.SpeedLimiter.Store(email, limiter)
|
||||||
|
inboundInfo.UserLimitInfo.Delete(email)
|
||||||
return limiter, true, false
|
return limiter, true, false
|
||||||
}
|
}
|
||||||
bucket := v.(*ratelimit.Bucket)
|
bucket := v.(*ratelimit.Bucket)
|
||||||
@ -270,8 +245,28 @@ func (w *Writer) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
|||||||
return w.writer.WriteMultiBuffer(mb)
|
return w.writer.WriteMultiBuffer(mb)
|
||||||
}
|
}
|
||||||
|
|
||||||
// determineRate returns the minimum non-zero rate
|
// determineSpeedLimit returns the minimum non-zero rate
|
||||||
func determineRate(nodeLimit, userLimit uint64) (limit uint64) {
|
func determineSpeedLimit(nodeLimit, userLimit uint64) (limit uint64) {
|
||||||
|
if nodeLimit == 0 || userLimit == 0 {
|
||||||
|
if nodeLimit > userLimit {
|
||||||
|
return nodeLimit
|
||||||
|
} else if nodeLimit < userLimit {
|
||||||
|
return userLimit
|
||||||
|
} else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if nodeLimit > userLimit {
|
||||||
|
return userLimit
|
||||||
|
} else if nodeLimit < userLimit {
|
||||||
|
return nodeLimit
|
||||||
|
} else {
|
||||||
|
return nodeLimit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func determineDeviceLimit(nodeLimit, userLimit int) (limit int) {
|
||||||
if nodeLimit == 0 || userLimit == 0 {
|
if nodeLimit == 0 || userLimit == 0 {
|
||||||
if nodeLimit > userLimit {
|
if nodeLimit > userLimit {
|
||||||
return nodeLimit
|
return nodeLimit
|
||||||
|
@ -28,8 +28,8 @@ func (p *Core) AddInbound(config *core.InboundHandlerConfig) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Core) AddInboundLimiter(tag string, nodeInfo *panel.NodeInfo, userList []panel.UserInfo) error {
|
func (p *Core) AddInboundLimiter(tag string, nodeInfo *panel.NodeInfo) error {
|
||||||
return p.dispatcher.Limiter.AddInboundLimiter(tag, nodeInfo, userList)
|
return p.dispatcher.Limiter.AddInboundLimiter(tag, nodeInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Core) GetInboundLimiter(tag string) (*dispatcher.InboundInfo, error) {
|
func (p *Core) GetInboundLimiter(tag string) (*dispatcher.InboundInfo, error) {
|
||||||
@ -40,8 +40,8 @@ func (p *Core) GetInboundLimiter(tag string) (*dispatcher.InboundInfo, error) {
|
|||||||
return nil, fmt.Errorf("not found limiter")
|
return nil, fmt.Errorf("not found limiter")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Core) UpdateInboundLimiter(tag string, nodeInfo *panel.NodeInfo, added, deleted []panel.UserInfo) error {
|
func (p *Core) UpdateInboundLimiter(tag string, deleted []panel.UserInfo) error {
|
||||||
return p.dispatcher.Limiter.UpdateInboundLimiter(tag, nodeInfo, added, deleted)
|
return p.dispatcher.Limiter.UpdateInboundLimiter(tag, deleted)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Core) DeleteInboundLimiter(tag string) error {
|
func (p *Core) DeleteInboundLimiter(tag string) error {
|
||||||
|
@ -80,8 +80,8 @@ func (p *Core) GetUserTraffic(email string, reset bool) (up int64, down int64) {
|
|||||||
return up, down
|
return up, down
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Core) UpdateUserSpeedLimit(tag string, user *panel.UserInfo, speedLimit uint64, expire int64) error {
|
func (p *Core) AddUserSpeedLimit(tag string, user *panel.UserInfo, speedLimit uint64, expire int64) error {
|
||||||
return p.dispatcher.Limiter.UpdateUserSpeedLimit(tag, user, speedLimit, expire)
|
return p.dispatcher.Limiter.AddUserSpeedLimit(tag, user, speedLimit, expire)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Core) ListOnlineIp(tag string) ([]dispatcher.UserIpList, error) {
|
func (p *Core) ListOnlineIp(tag string) ([]dispatcher.UserIpList, error) {
|
||||||
|
14
node/node.go
14
node/node.go
@ -59,17 +59,15 @@ func (c *Node) Start() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Update user
|
// Update user
|
||||||
userInfo, err := c.apiClient.GetUserList()
|
c.userList, err = c.apiClient.GetUserList()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = c.addNewUser(userInfo, newNodeInfo)
|
err = c.addNewUser(c.userList, newNodeInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
//sync controller userList
|
if err := c.server.AddInboundLimiter(c.Tag, c.nodeInfo); err != nil {
|
||||||
c.userList = userInfo
|
|
||||||
if err := c.server.AddInboundLimiter(c.Tag, c.nodeInfo, userInfo); err != nil {
|
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
}
|
}
|
||||||
// Add Rule Manager
|
// Add Rule Manager
|
||||||
@ -240,7 +238,7 @@ func (c *Node) nodeInfoMonitor() (err error) {
|
|||||||
}
|
}
|
||||||
newNodeInfo = nil
|
newNodeInfo = nil
|
||||||
// Add Limiter
|
// Add Limiter
|
||||||
if err := c.server.AddInboundLimiter(c.Tag, c.nodeInfo, c.userList); err != nil {
|
if err := c.server.AddInboundLimiter(c.Tag, c.nodeInfo); err != nil {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -267,7 +265,7 @@ func (c *Node) nodeInfoMonitor() (err error) {
|
|||||||
}
|
}
|
||||||
if len(added) > 0 || len(deleted) > 0 {
|
if len(added) > 0 || len(deleted) > 0 {
|
||||||
// Update Limiter
|
// Update Limiter
|
||||||
if err := c.server.UpdateInboundLimiter(c.Tag, c.nodeInfo, added, deleted); err != nil {
|
if err := c.server.UpdateInboundLimiter(c.Tag, deleted); err != nil {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -445,7 +443,7 @@ func (c *Node) DynamicSpeedLimit() error {
|
|||||||
for i := range c.userList {
|
for i := range c.userList {
|
||||||
up, down := c.server.GetUserTraffic(c.buildUserTag(&(c.userList)[i]), false)
|
up, down := c.server.GetUserTraffic(c.buildUserTag(&(c.userList)[i]), false)
|
||||||
if c.userList[i].Traffic+down+up/1024/1024 > c.config.DynamicSpeedLimitConfig.Traffic {
|
if c.userList[i].Traffic+down+up/1024/1024 > c.config.DynamicSpeedLimitConfig.Traffic {
|
||||||
err := c.server.UpdateUserSpeedLimit(c.Tag,
|
err := c.server.AddUserSpeedLimit(c.Tag,
|
||||||
&c.userList[i],
|
&c.userList[i],
|
||||||
c.config.DynamicSpeedLimitConfig.SpeedLimit,
|
c.config.DynamicSpeedLimitConfig.SpeedLimit,
|
||||||
time.Now().Add(time.Second*time.Duration(c.config.DynamicSpeedLimitConfig.ExpireTime)).Unix())
|
time.Now().Add(time.Second*time.Duration(c.config.DynamicSpeedLimitConfig.ExpireTime)).Unix())
|
||||||
|
Loading…
Reference in New Issue
Block a user