移除不必要的 user_host 字段及相关索引;优化通道缓存方式,直接缓存通道授权信息

This commit is contained in:
2025-05-12 17:04:20 +08:00
parent 2c37dcc2be
commit 2be1a18e91
5 changed files with 43 additions and 68 deletions

View File

@@ -3,7 +3,6 @@ package services
import (
"context"
"database/sql"
"encoding/json"
"errors"
"fmt"
"log/slog"
@@ -97,12 +96,6 @@ func (s *channelService) RemoveChannels(ctx context.Context, authCtx *auth.Conte
return ChannelServiceErr("删除通道失败")
}
// 删除缓存
err = deleteCache(ctx, channels)
if err != nil {
return err
}
// 禁用代理端口并下线用过的节点
if env.DebugExternalChange {
var step = time.Now()
@@ -276,7 +269,7 @@ func (s *channelService) CreateChannel(
}
// 缓存通道数据
err = cacheChannels(ctx, rid, newChannels)
err = cacheChannels(ctx, rid, newChannels, whitelist)
if err != nil {
return err
}
@@ -612,8 +605,28 @@ func saveChannels(channels []*m.Channel) (err error) {
return nil
}
func cacheChannels(ctx context.Context, rid string, channels []*m.Channel) (err error) {
err = cache(ctx, channels)
func cacheChannels(ctx context.Context, rid string, channels []*m.Channel, whitelists *[]string) (err error) {
if len(channels) == 0 {
return nil
}
pipe := g.Redis.TxPipeline()
zList := make([]redis.Z, 0, len(channels))
for _, channel := range channels {
expiration := time.Time(channel.Expiration)
keys := chAuthItems(channel, whitelists)
for _, key := range keys {
pipe.Set(ctx, key, true, time.Since(expiration))
}
zList = append(zList, redis.Z{
Score: float64(expiration.Unix()),
Member: channel.ID,
})
}
pipe.ZAdd(ctx, "tasks:channel", zList...)
_, err = pipe.Exec(ctx)
if err != nil {
return err
}
@@ -642,62 +655,35 @@ func genPassPair() (string, string) {
return string(username), string(password)
}
func chKey(channel *m.Channel) string {
return fmt.Sprintf("channel:%d", channel.ID)
}
func cache(ctx context.Context, channels []*m.Channel) error {
if len(channels) == 0 {
return nil
func chAuthItems(channel *m.Channel, whitelists *[]string) []string {
var count = 1
var ips = make([]string, 0)
if channel.AuthIP && whitelists != nil {
count = len(*whitelists)
ips = *whitelists
}
pipe := g.Redis.TxPipeline()
zList := make([]redis.Z, 0, len(channels))
for _, channel := range channels {
marshal, err := json.Marshal(channel)
if err != nil {
return err
var proxy = channel.ProxyHost + ":" + strconv.Itoa(int(channel.ProxyPort))
var sb = strings.Builder{}
var items = make([]string, count)
for i := range items {
// 权限 key 格式:<proxy_host>:<proxy_port>:<user_ip>?:<username>?:<password>?
sb.WriteString(proxy)
if channel.AuthIP {
sb.WriteString(":" + ips[i])
}
if channel.AuthPass {
sb.WriteString(":" + channel.Username + ":" + channel.Password)
}
expiration := time.Time(channel.Expiration)
pipe.Set(ctx, chKey(channel), string(marshal), time.Until(expiration))
zList = append(zList, redis.Z{
Score: float64(expiration.Unix()),
Member: channel.ID,
})
}
pipe.ZAdd(ctx, "tasks:channel", zList...)
_, err := pipe.Exec(ctx)
if err != nil {
return err
}
return nil
}
func deleteCache(ctx context.Context, channels []*m.Channel) error {
if len(channels) == 0 {
return nil
}
keys := make([]string, len(channels))
for i := range channels {
keys[i] = chKey(channels[i])
}
_, err := g.Redis.Del(ctx, keys...).Result()
if err != nil {
return err
}
return nil
return items
}
type ChannelAuthType int
const (
ChannelAuthTypeAll ChannelAuthType = iota
ChannelAuthTypeIp
ChannelAuthTypeIp ChannelAuthType = iota + 1
ChannelAuthTypePass
)