feat(config): add Least Time and Sticky configuration support

- Add least_time and sticky to valid algorithms list
- Add LeastTimeConfig and StickyConfig structures
- Update default config generation with new options
- Add configuration validation for new fields
This commit is contained in:
xfy 2026-06-08 17:57:06 +08:00
parent a73da4e14a
commit 88a2c1fc1b
4 changed files with 105 additions and 2 deletions

View File

@ -397,7 +397,7 @@ func GenerateConfigYAML(cfg *Config) ([]byte, error) {
buf.WriteString(" # backup: false # 备份服务器标记(仅当主服务器不可用时使用)\n")
buf.WriteString(" # down: false # 永久不可用标记\n")
buf.WriteString(" # proxy_uri: \"\" # 代理传递的 URI 路径\n")
buf.WriteString(" # load_balance: round_robin # 负载均衡算法(有效值: round_robin, weighted_round_robin, least_conn, ip_hash, consistent_hash, random\n")
buf.WriteString(" # load_balance: round_robin # 负载均衡算法(有效值: round_robin, weighted_round_robin, least_conn, ip_hash, consistent_hash, random, least_time, sticky\n")
buf.WriteString(" # hash_key: ip # 一致性哈希键(仅 load_balance=consistent_hash 时有效,有效值: ip, uri, header:X-Name\n")
buf.WriteString(" # virtual_nodes: 150 # 一致性哈希虚拟节点数(仅 load_balance=consistent_hash 时有效)\n")
buf.WriteString(" # health_check: # 健康检查\n")
@ -480,6 +480,17 @@ func GenerateConfigYAML(cfg *Config) ([]byte, error) {
buf.WriteString(" # # replacement: \"$scheme://$host:$server_port/\" # 替换目标(支持 $host, $scheme, $server_port 等变量)\n")
buf.WriteString(" # # - pattern: \"~^http://[^/]+:8000/(.*)$\" # 正则匹配示例\n")
buf.WriteString(" # # replacement: \"$scheme://$host/$1\" # 使用捕获组 $1\n")
buf.WriteString(" # least_time: # 最小时间负载均衡配置\n")
buf.WriteString(" # metric: last_byte # 指标类型header | last_byte\n")
buf.WriteString(" # default_time: 1ms # 无统计样本时的默认响应时间\n")
buf.WriteString(" # sticky: # Session Sticky 配置\n")
buf.WriteString(" # enabled: false # 是否启用\n")
buf.WriteString(" # name: lolly_route # cookie 名称\n")
buf.WriteString(" # expires: 1h # session 有效期\n")
buf.WriteString(" # path: / # cookie 路径\n")
buf.WriteString(" # http_only: true # HttpOnly flag\n")
buf.WriteString(" # same_site: Lax # SameSite 属性\n")
buf.WriteString(" # fallback_balance: round_robin # fallback 算法\n")
buf.WriteString("\n")
// SSL 配置

View File

@ -19,7 +19,7 @@ import (
// 注意事项:
// - Path 使用前缀匹配,较长路径优先匹配
// - 至少配置一个 Target 才能正常工作
// - 负载均衡算法支持round_robin、weighted_round_robin、least_conn、ip_hash、consistent_hash、random
// - 负载均衡算法支持round_robin、weighted_round_robin、least_conn、ip_hash、consistent_hash、random、least_time、sticky
// - 一致性哈希需要配置 HashKey
//
// 使用示例:
@ -56,6 +56,8 @@ type ProxyConfig struct {
NextUpstream NextUpstreamConfig `yaml:"next_upstream"`
Cache ProxyCacheConfig `yaml:"cache"`
Timeout ProxyTimeout `yaml:"timeout"`
LeastTime LeastTimeConfig `yaml:"least_time"`
Sticky StickyConfig `yaml:"sticky"`
// 基本类型字段
VirtualNodes int `yaml:"virtual_nodes"`
@ -440,6 +442,77 @@ type RedirectRewriteRule struct {
Replacement string `yaml:"replacement"`
}
// LeastTimeConfig 最小时间负载均衡配置。
//
// 基于后端响应时间选择最优后端。
//
// 注意事项:
// - Metric 决定时间统计方式
// - DefaultTime 用于首次请求无样本时
//
// 使用示例:
//
// least_time:
// metric: last_byte # 指标类型header | last_byte
// default_time: 1ms # 无统计样本时的默认响应时间
type LeastTimeConfig struct {
// Metric 时间指标类型
// 可选值header首字节时间、last_byte末字节时间
Metric string `yaml:"metric"`
// DefaultTime 无统计样本时的默认响应时间
// 用于首次请求或新后端加入时
DefaultTime time.Duration `yaml:"default_time"`
}
// StickyConfig Session Sticky 配置。
//
// 通过 Cookie 将同一客户端固定到同一后端。
//
// 注意事项:
// - Enabled 为 true 时启用
// - FallbackAlgo 指定当无法找到 sticky 后端时使用的算法
//
// 使用示例:
//
// sticky:
// enabled: true
// name: lolly_route # cookie 名称
// expires: 1h # session 有效期
// path: / # cookie 路径
// http_only: true # HttpOnly flag
// same_site: Lax # SameSite 属性
// fallback_balance: round_robin # fallback 算法
type StickyConfig struct {
// Enabled 是否启用 Session Sticky
Enabled bool `yaml:"enabled"`
// Name Cookie 名称
Name string `yaml:"name"`
// Expires session 有效期
Expires time.Duration `yaml:"expires"`
// Domain Cookie 域
Domain string `yaml:"domain"`
// Path Cookie 路径
Path string `yaml:"path"`
// Secure Secure flag
Secure bool `yaml:"secure"`
// HttpOnly HttpOnly flag
HttpOnly bool `yaml:"http_only"`
// SameSite SameSite 属性
// 可选值Lax, Strict, None
SameSite string `yaml:"same_site"`
// FallbackAlgo 无法找到 sticky 后端时的 fallback 算法
FallbackAlgo string `yaml:"fallback_balance"`
}
// NextUpstreamConfig 故障转移配置,定义后端失败时的自动重试行为。
//
// 当后端返回特定错误状态码或连接失败时,自动尝试下一个可用后端。

View File

@ -504,6 +504,23 @@ func validateProxy(p *ProxyConfig) error {
return fmt.Errorf("无效的负载均衡算法:%s", p.LoadBalance)
}
// validate least_time config
if p.LoadBalance == "least_time" {
if p.LeastTime.Metric != "" && p.LeastTime.Metric != "header" && p.LeastTime.Metric != "last_byte" {
return fmt.Errorf("无效的 least_time metric: %s有效值: header, last_byte", p.LeastTime.Metric)
}
}
// validate sticky config
if p.LoadBalance == "sticky" {
if !p.Sticky.Enabled {
return fmt.Errorf("load_balance=sticky 时 sticky.enabled 必须为 true")
}
if p.Sticky.FallbackAlgo != "" && !loadbalance.IsValidAlgorithm(p.Sticky.FallbackAlgo) {
return fmt.Errorf("无效的 sticky fallback_balance: %s", p.Sticky.FallbackAlgo)
}
}
// 验证故障转移配置
if err := validateNextUpstream(&p.NextUpstream); err != nil {
return fmt.Errorf("next_upstream: %w", err)

View File

@ -24,6 +24,8 @@ var validAlgorithms = []string{
"ip_hash",
"consistent_hash",
"random",
"least_time",
"sticky",
}
// IsValidAlgorithm 检查给定的算法名称是否有效。