Files
pansou/config/config.go

516 lines
14 KiB
Go
Raw Normal View History

2025-07-12 19:53:44 +08:00
package config
import (
"os"
"path/filepath"
2025-07-23 12:01:09 +08:00
"runtime"
2025-07-12 19:53:44 +08:00
"runtime/debug"
"strconv"
"strings"
"time"
)
// Config 应用配置结构
type Config struct {
DefaultChannels []string
DefaultConcurrency int
Port string
ProxyURL string
UseProxy bool
// 缓存相关配置
CacheEnabled bool
CachePath string
CacheMaxSizeMB int
CacheTTLMinutes int
// 压缩相关配置
EnableCompression bool
MinSizeToCompress int // 最小压缩大小(字节)
// GC相关配置
GCPercent int // GC触发阈值百分比
OptimizeMemory bool // 是否启用内存优化
// 插件相关配置
PluginTimeoutSeconds int // 插件超时时间(秒)
PluginTimeout time.Duration // 插件超时时间Duration
2025-07-15 00:03:02 +08:00
// 异步插件相关配置
AsyncPluginEnabled bool // 是否启用异步插件
2025-08-21 10:32:43 +08:00
EnabledPlugins []string // 启用的具体插件列表(空表示启用所有)
2025-07-15 00:03:02 +08:00
AsyncResponseTimeout int // 响应超时时间(秒)
AsyncResponseTimeoutDur time.Duration // 响应超时时间Duration
AsyncMaxBackgroundWorkers int // 最大后台工作者数量
AsyncMaxBackgroundTasks int // 最大后台任务数量
AsyncCacheTTLHours int // 异步缓存有效期(小时)
AsyncLogEnabled bool // 是否启用异步插件详细日志
2025-07-23 12:01:09 +08:00
// HTTP服务器配置
HTTPReadTimeout time.Duration // 读取超时
HTTPWriteTimeout time.Duration // 写入超时
HTTPIdleTimeout time.Duration // 空闲超时
HTTPMaxConns int // 最大连接数
2025-08-01 21:21:42 +08:00
2025-07-12 19:53:44 +08:00
}
// 全局配置实例
var AppConfig *Config
// 初始化配置
func Init() {
proxyURL := getProxyURL()
pluginTimeoutSeconds := getPluginTimeout()
2025-07-15 00:03:02 +08:00
asyncResponseTimeoutSeconds := getAsyncResponseTimeout()
2025-07-12 19:53:44 +08:00
AppConfig = &Config{
DefaultChannels: getDefaultChannels(),
DefaultConcurrency: getDefaultConcurrency(),
Port: getPort(),
ProxyURL: proxyURL,
UseProxy: proxyURL != "",
// 缓存相关配置
CacheEnabled: getCacheEnabled(),
CachePath: getCachePath(),
CacheMaxSizeMB: getCacheMaxSize(),
CacheTTLMinutes: getCacheTTL(),
// 压缩相关配置
EnableCompression: getEnableCompression(),
MinSizeToCompress: getMinSizeToCompress(),
// GC相关配置
GCPercent: getGCPercent(),
OptimizeMemory: getOptimizeMemory(),
// 插件相关配置
PluginTimeoutSeconds: pluginTimeoutSeconds,
PluginTimeout: time.Duration(pluginTimeoutSeconds) * time.Second,
2025-07-15 00:03:02 +08:00
// 异步插件相关配置
AsyncPluginEnabled: getAsyncPluginEnabled(),
2025-08-21 10:32:43 +08:00
EnabledPlugins: getEnabledPlugins(),
2025-07-15 00:03:02 +08:00
AsyncResponseTimeout: asyncResponseTimeoutSeconds,
AsyncResponseTimeoutDur: time.Duration(asyncResponseTimeoutSeconds) * time.Second,
AsyncMaxBackgroundWorkers: getAsyncMaxBackgroundWorkers(),
AsyncMaxBackgroundTasks: getAsyncMaxBackgroundTasks(),
AsyncCacheTTLHours: getAsyncCacheTTLHours(),
AsyncLogEnabled: getAsyncLogEnabled(),
2025-07-23 12:01:09 +08:00
// HTTP服务器配置
HTTPReadTimeout: getHTTPReadTimeout(),
HTTPWriteTimeout: getHTTPWriteTimeout(),
HTTPIdleTimeout: getHTTPIdleTimeout(),
HTTPMaxConns: getHTTPMaxConns(),
2025-08-01 21:21:42 +08:00
2025-07-12 19:53:44 +08:00
}
// 应用GC配置
applyGCSettings()
}
// 从环境变量获取默认频道列表,如果未设置则使用默认值
func getDefaultChannels() []string {
channelsEnv := os.Getenv("CHANNELS")
if channelsEnv == "" {
2025-08-15 15:38:06 +08:00
return []string{"tgsearchers3"}
2025-07-12 19:53:44 +08:00
}
return strings.Split(channelsEnv, ",")
}
2025-07-23 12:01:09 +08:00
// 从环境变量获取默认并发数,如果未设置则使用基于环境变量的简单计算
2025-07-12 19:53:44 +08:00
func getDefaultConcurrency() int {
concurrencyEnv := os.Getenv("CONCURRENCY")
2025-07-23 12:01:09 +08:00
if concurrencyEnv != "" {
concurrency, err := strconv.Atoi(concurrencyEnv)
if err == nil && concurrency > 0 {
return concurrency
}
2025-07-12 19:53:44 +08:00
}
2025-07-23 12:01:09 +08:00
// 环境变量未设置或无效,使用基于环境变量的简单计算
// 计算频道数
channelCount := len(getDefaultChannels())
// 估计插件数(从环境变量或默认值,实际在应用启动后会根据真实插件数调整)
pluginCountEnv := os.Getenv("PLUGIN_COUNT")
pluginCount := 0
if pluginCountEnv != "" {
count, err := strconv.Atoi(pluginCountEnv)
if err == nil && count > 0 {
pluginCount = count
}
2025-07-12 19:53:44 +08:00
}
2025-07-23 12:01:09 +08:00
// 如果没有指定插件数默认使用7个当前已知的插件数
if pluginCount == 0 {
pluginCount = 7
}
// 计算并发数 = 频道数 + 插件数 + 10
concurrency := channelCount + pluginCount + 10
if concurrency < 1 {
concurrency = 1 // 确保至少为1
}
2025-07-12 19:53:44 +08:00
return concurrency
}
2025-08-21 10:11:26 +08:00
// 更新默认并发数根据实际插件数或0调用
// pluginCount: 如果插件被禁用则为0否则为实际插件数
2025-07-23 12:01:09 +08:00
func UpdateDefaultConcurrency(pluginCount int) {
if AppConfig == nil {
return
}
// 只有当未通过环境变量指定并发数时才进行调整
concurrencyEnv := os.Getenv("CONCURRENCY")
if concurrencyEnv != "" {
return
}
// 计算频道数
channelCount := len(AppConfig.DefaultChannels)
2025-08-21 10:11:26 +08:00
// 计算并发数 = 频道数 + 插件数插件禁用时为0+ 10
2025-07-23 12:01:09 +08:00
concurrency := channelCount + pluginCount + 10
if concurrency < 1 {
concurrency = 1 // 确保至少为1
}
// 更新配置
AppConfig.DefaultConcurrency = concurrency
}
2025-07-12 19:53:44 +08:00
// 从环境变量获取服务端口,如果未设置则使用默认值
func getPort() string {
port := os.Getenv("PORT")
if port == "" {
2025-07-15 00:03:02 +08:00
return "8888"
2025-07-12 19:53:44 +08:00
}
return port
}
// 从环境变量获取SOCKS5代理URL如果未设置则返回空字符串
func getProxyURL() string {
return os.Getenv("PROXY")
}
// 从环境变量获取是否启用缓存,如果未设置则默认启用
func getCacheEnabled() bool {
enabled := os.Getenv("CACHE_ENABLED")
if enabled == "" {
return true
}
return enabled != "false" && enabled != "0"
}
// 从环境变量获取缓存路径,如果未设置则使用默认路径
func getCachePath() string {
path := os.Getenv("CACHE_PATH")
if path == "" {
// 默认在当前目录下创建cache文件夹
defaultPath, err := filepath.Abs("./cache")
if err != nil {
return "./cache"
}
return defaultPath
}
return path
}
// 从环境变量获取缓存最大大小(MB),如果未设置则使用默认值
func getCacheMaxSize() int {
sizeEnv := os.Getenv("CACHE_MAX_SIZE")
if sizeEnv == "" {
return 100 // 默认100MB
}
size, err := strconv.Atoi(sizeEnv)
if err != nil || size <= 0 {
return 100
}
return size
}
// 从环境变量获取缓存TTL(分钟),如果未设置则使用默认值
func getCacheTTL() int {
ttlEnv := os.Getenv("CACHE_TTL")
if ttlEnv == "" {
return 60 // 默认60分钟
}
ttl, err := strconv.Atoi(ttlEnv)
if err != nil || ttl <= 0 {
return 60
}
return ttl
}
// 从环境变量获取是否启用压缩,如果未设置则默认禁用
func getEnableCompression() bool {
enabled := os.Getenv("ENABLE_COMPRESSION")
if enabled == "" {
return false // 默认禁用因为通常由Nginx等处理
}
return enabled == "true" || enabled == "1"
}
// 从环境变量获取最小压缩大小,如果未设置则使用默认值
func getMinSizeToCompress() int {
sizeEnv := os.Getenv("MIN_SIZE_TO_COMPRESS")
if sizeEnv == "" {
return 1024 // 默认1KB
}
size, err := strconv.Atoi(sizeEnv)
if err != nil || size <= 0 {
return 1024
}
return size
}
// 从环境变量获取GC百分比如果未设置则使用默认值
func getGCPercent() int {
percentEnv := os.Getenv("GC_PERCENT")
if percentEnv == "" {
return 100 // 默认100%
}
percent, err := strconv.Atoi(percentEnv)
if err != nil || percent <= 0 {
return 100
}
return percent
}
// 从环境变量获取是否优化内存,如果未设置则默认启用
func getOptimizeMemory() bool {
enabled := os.Getenv("OPTIMIZE_MEMORY")
if enabled == "" {
return true // 默认启用
}
return enabled != "false" && enabled != "0"
}
// 从环境变量获取插件超时时间(秒),如果未设置则使用默认值
func getPluginTimeout() int {
timeoutEnv := os.Getenv("PLUGIN_TIMEOUT")
if timeoutEnv == "" {
return 30 // 默认30秒
}
timeout, err := strconv.Atoi(timeoutEnv)
if err != nil || timeout <= 0 {
return 30
}
return timeout
}
2025-07-15 00:03:02 +08:00
// 从环境变量获取是否启用异步插件,如果未设置则默认启用
func getAsyncPluginEnabled() bool {
enabled := os.Getenv("ASYNC_PLUGIN_ENABLED")
if enabled == "" {
return true // 默认启用
}
return enabled != "false" && enabled != "0"
}
// 从环境变量获取启用的插件列表
// 返回nil表示未设置环境变量不启用任何插件
// 返回[]string{}表示设置为空(不启用任何插件)
// 返回具体列表表示启用指定插件
2025-08-21 10:32:43 +08:00
func getEnabledPlugins() []string {
plugins, exists := os.LookupEnv("ENABLED_PLUGINS")
if !exists {
// 未设置环境变量时返回nil表示不启用任何插件
return nil
}
2025-08-21 10:32:43 +08:00
if plugins == "" {
// 设置为空字符串,也表示不启用任何插件
return []string{}
2025-08-21 10:32:43 +08:00
}
// 按逗号分割插件名
result := make([]string, 0)
for _, plugin := range strings.Split(plugins, ",") {
plugin = strings.TrimSpace(plugin)
if plugin != "" {
result = append(result, plugin)
}
}
return result
}
2025-07-15 00:03:02 +08:00
// 从环境变量获取异步响应超时时间(秒),如果未设置则使用默认值
func getAsyncResponseTimeout() int {
timeoutEnv := os.Getenv("ASYNC_RESPONSE_TIMEOUT")
if timeoutEnv == "" {
return 4 // 默认4秒
}
timeout, err := strconv.Atoi(timeoutEnv)
if err != nil || timeout <= 0 {
return 4
}
return timeout
}
2025-07-23 12:01:09 +08:00
// 从环境变量获取最大后台工作者数量,如果未设置则自动计算
2025-07-15 00:03:02 +08:00
func getAsyncMaxBackgroundWorkers() int {
sizeEnv := os.Getenv("ASYNC_MAX_BACKGROUND_WORKERS")
2025-07-23 12:01:09 +08:00
if sizeEnv != "" {
size, err := strconv.Atoi(sizeEnv)
if err == nil && size > 0 {
return size
}
2025-07-15 00:03:02 +08:00
}
2025-07-23 12:01:09 +08:00
// 自动计算根据CPU核心数计算
// 每个CPU核心分配5个工作者最小20个
cpuCount := runtime.NumCPU()
workers := cpuCount * 5
// 确保至少有20个工作者
if workers < 20 {
workers = 20
2025-07-15 00:03:02 +08:00
}
2025-07-23 12:01:09 +08:00
return workers
2025-07-15 00:03:02 +08:00
}
2025-07-23 12:01:09 +08:00
// 从环境变量获取最大后台任务数量,如果未设置则自动计算
2025-07-15 00:03:02 +08:00
func getAsyncMaxBackgroundTasks() int {
sizeEnv := os.Getenv("ASYNC_MAX_BACKGROUND_TASKS")
2025-07-23 12:01:09 +08:00
if sizeEnv != "" {
size, err := strconv.Atoi(sizeEnv)
if err == nil && size > 0 {
return size
}
2025-07-15 00:03:02 +08:00
}
2025-07-23 12:01:09 +08:00
// 自动计算工作者数量的5倍最小100个
workers := getAsyncMaxBackgroundWorkers()
tasks := workers * 5
// 确保至少有100个任务
if tasks < 100 {
tasks = 100
2025-07-15 00:03:02 +08:00
}
2025-07-23 12:01:09 +08:00
return tasks
2025-07-15 00:03:02 +08:00
}
// 从环境变量获取异步缓存有效期(小时),如果未设置则使用默认值
func getAsyncCacheTTLHours() int {
ttlEnv := os.Getenv("ASYNC_CACHE_TTL_HOURS")
if ttlEnv == "" {
return 1 // 默认1小时
}
ttl, err := strconv.Atoi(ttlEnv)
if err != nil || ttl <= 0 {
return 1
}
return ttl
}
2025-07-23 12:01:09 +08:00
// 从环境变量获取HTTP读取超时如果未设置则自动计算
func getHTTPReadTimeout() time.Duration {
timeoutEnv := os.Getenv("HTTP_READ_TIMEOUT")
if timeoutEnv != "" {
timeout, err := strconv.Atoi(timeoutEnv)
if err == nil && timeout > 0 {
return time.Duration(timeout) * time.Second
}
}
// 自动计算默认30秒异步模式下根据异步响应超时调整
timeout := 30 * time.Second
// 如果启用了异步插件,确保读取超时足够长
if getAsyncPluginEnabled() {
// 读取超时应该至少是异步响应超时的3倍确保有足够时间完成异步操作
asyncTimeoutSecs := getAsyncResponseTimeout()
asyncTimeoutExtended := time.Duration(asyncTimeoutSecs * 3) * time.Second
if asyncTimeoutExtended > timeout {
timeout = asyncTimeoutExtended
}
}
return timeout
}
// 从环境变量获取HTTP写入超时如果未设置则自动计算
func getHTTPWriteTimeout() time.Duration {
timeoutEnv := os.Getenv("HTTP_WRITE_TIMEOUT")
if timeoutEnv != "" {
timeout, err := strconv.Atoi(timeoutEnv)
if err == nil && timeout > 0 {
return time.Duration(timeout) * time.Second
}
}
// 自动计算默认60秒但根据插件超时和异步处理时间调整
timeout := 60 * time.Second
// 如果启用了异步插件,确保写入超时足够长
pluginTimeoutSecs := getPluginTimeout()
// 计算1.5倍的插件超时时间使用整数运算乘以3再除以2
pluginTimeoutExtended := time.Duration(pluginTimeoutSecs * 3 / 2) * time.Second
if pluginTimeoutExtended > timeout {
timeout = pluginTimeoutExtended
}
return timeout
}
// 从环境变量获取HTTP空闲超时如果未设置则自动计算
func getHTTPIdleTimeout() time.Duration {
timeoutEnv := os.Getenv("HTTP_IDLE_TIMEOUT")
if timeoutEnv != "" {
timeout, err := strconv.Atoi(timeoutEnv)
if err == nil && timeout > 0 {
return time.Duration(timeout) * time.Second
}
}
// 自动计算默认120秒考虑到保持连接的效益
return 120 * time.Second
}
// 从环境变量获取HTTP最大连接数如果未设置则自动计算
func getHTTPMaxConns() int {
maxConnsEnv := os.Getenv("HTTP_MAX_CONNS")
if maxConnsEnv != "" {
maxConns, err := strconv.Atoi(maxConnsEnv)
if err == nil && maxConns > 0 {
return maxConns
}
}
// 自动计算根据CPU核心数计算
// 每个CPU核心分配200个连接最小1000个
cpuCount := runtime.NumCPU()
maxConns := cpuCount * 200
// 确保至少有1000个连接
if maxConns < 1000 {
maxConns = 1000
}
return maxConns
}
// 从环境变量获取异步插件日志开关,如果未设置则使用默认值
func getAsyncLogEnabled() bool {
logEnv := os.Getenv("ASYNC_LOG_ENABLED")
if logEnv == "" {
return true // 默认启用日志
}
enabled, err := strconv.ParseBool(logEnv)
if err != nil {
return true // 解析失败时默认启用
}
return enabled
}
2025-07-12 19:53:44 +08:00
// 应用GC设置
func applyGCSettings() {
// 设置GC百分比
debug.SetGCPercent(AppConfig.GCPercent)
// 如果启用内存优化
if AppConfig.OptimizeMemory {
// 释放操作系统内存
debug.FreeOSMemory()
}
2025-08-01 21:21:42 +08:00
}