refactor: 代码改进与注释补充
- logging: 补充包文档说明 - pool: 修复 workers 计数器并发安全 (atomic 操作) - stream: 完善注释与错误处理 - handler/static: 添加预压缩文件支持接口 - loadbalance: 补充算法注释 - vhost: 改进虚拟主机路由逻辑 - ssl: 优化证书加载注释 - main: 补充启动流程注释 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
03b0df2c69
commit
92cd93d4c0
@ -4,6 +4,7 @@
|
||||
// - 静态文件请求处理
|
||||
// - 目录索引文件支持
|
||||
// - 文件缓存和零拷贝传输优化
|
||||
// - 预压缩文件支持
|
||||
//
|
||||
// 主要用途:
|
||||
//
|
||||
@ -12,6 +13,7 @@
|
||||
// 注意事项:
|
||||
// - 自动处理目录遍历攻击防护
|
||||
// - 支持多索引文件(如 index.html、index.htm)
|
||||
// - 支持预压缩 .gz 文件
|
||||
//
|
||||
// 作者:xfy
|
||||
package handler
|
||||
@ -24,6 +26,7 @@ import (
|
||||
|
||||
"github.com/valyala/fasthttp"
|
||||
"rua.plus/lolly/internal/cache"
|
||||
"rua.plus/lolly/internal/middleware/compression"
|
||||
)
|
||||
|
||||
// StaticHandler 静态文件处理器。
|
||||
@ -41,6 +44,9 @@ type StaticHandler struct {
|
||||
|
||||
// fileCache 文件缓存实例(可选)
|
||||
fileCache *cache.FileCache
|
||||
|
||||
// gzipStatic 预压缩文件支持(可选)
|
||||
gzipStatic *compression.GzipStatic
|
||||
}
|
||||
|
||||
// NewStaticHandler 创建静态文件处理器
|
||||
@ -57,6 +63,13 @@ func (h *StaticHandler) SetFileCache(fc *cache.FileCache) {
|
||||
h.fileCache = fc
|
||||
}
|
||||
|
||||
// SetGzipStatic 设置预压缩文件支持
|
||||
func (h *StaticHandler) SetGzipStatic(enabled bool, extensions []string) {
|
||||
if enabled {
|
||||
h.gzipStatic = compression.NewGzipStatic(true, h.root, extensions)
|
||||
}
|
||||
}
|
||||
|
||||
// Handle 处理静态文件请求
|
||||
func (h *StaticHandler) Handle(ctx *fasthttp.RequestCtx) {
|
||||
path := string(ctx.Path())
|
||||
@ -96,6 +109,14 @@ func (h *StaticHandler) Handle(ctx *fasthttp.RequestCtx) {
|
||||
|
||||
// serveFile 提供文件服务,支持缓存和零拷贝传输
|
||||
func (h *StaticHandler) serveFile(ctx *fasthttp.RequestCtx, filePath string, info os.FileInfo) {
|
||||
// 尝试发送预压缩文件
|
||||
if h.gzipStatic != nil {
|
||||
relPath := strings.TrimPrefix(filePath, h.root)
|
||||
if h.gzipStatic.ServeFile(ctx, relPath) {
|
||||
return // 预压缩文件已发送
|
||||
}
|
||||
}
|
||||
|
||||
// 尝试从缓存获取
|
||||
if h.fileCache != nil {
|
||||
if entry, ok := h.fileCache.Get(filePath); ok {
|
||||
|
||||
@ -1,4 +1,17 @@
|
||||
// Package loadbalance 负载均衡包为 Lolly HTTP 服务器提供负载均衡算法。
|
||||
// Package loadbalance 负载均衡包,提供多种负载均衡算法实现。
|
||||
//
|
||||
// 该文件包含负载均衡相关的核心逻辑,包括:
|
||||
// - 轮询算法(Round Robin)
|
||||
// - 加权轮询算法(Weighted Round Robin)
|
||||
// - 最少连接算法(Least Connections)
|
||||
// - IP 哈希算法(IP Hash)
|
||||
// - 一致性哈希算法(Consistent Hash)
|
||||
//
|
||||
// 主要用途:
|
||||
//
|
||||
// 用于在后端服务器之间分发请求,提高服务可用性和性能。
|
||||
//
|
||||
// 作者:xfy
|
||||
package loadbalance
|
||||
|
||||
// ValidAlgorithms 是支持的负载均衡算法列表。
|
||||
|
||||
@ -1,3 +1,20 @@
|
||||
// Package logging 提供日志管理功能,支持访问日志和错误日志分离。
|
||||
//
|
||||
// 该文件包含日志相关的核心逻辑,包括:
|
||||
// - 访问日志记录(请求方法、路径、状态码、耗时)
|
||||
// - 错误日志记录(Debug、Info、Warn、Error 级别)
|
||||
// - 日志格式配置(text 或 json)
|
||||
// - 应用生命周期日志(启动、停止、信号)
|
||||
//
|
||||
// 主要用途:
|
||||
//
|
||||
// 用于记录服务器运行时的各类日志信息,便于监控和排查问题。
|
||||
//
|
||||
// 注意事项:
|
||||
// - 支持 zerolog 高性能日志库
|
||||
// - 访问日志和错误日志可分离输出到不同文件
|
||||
//
|
||||
// 作者:xfy
|
||||
package logging
|
||||
|
||||
import (
|
||||
|
||||
@ -157,13 +157,13 @@ func (p *GoroutinePool) Submit(ctx *fasthttp.RequestCtx, task Task) error {
|
||||
case p.taskQueue <- task:
|
||||
// 任务入队成功
|
||||
// 如果有空闲 worker 不足,可能需要启动新 worker
|
||||
if p.idleWorkers == 0 && p.workers < p.maxWorkers {
|
||||
if atomic.LoadInt32(&p.idleWorkers) == 0 && atomic.LoadInt32(&p.workers) < p.maxWorkers {
|
||||
p.startWorker()
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
// 队列满,需要启动新 worker 或直接执行
|
||||
if p.workers < p.maxWorkers {
|
||||
if atomic.LoadInt32(&p.workers) < p.maxWorkers {
|
||||
p.startWorker()
|
||||
// 重新尝试入队
|
||||
p.taskQueue <- task
|
||||
@ -180,7 +180,7 @@ func (p *GoroutinePool) Submit(ctx *fasthttp.RequestCtx, task Task) error {
|
||||
//
|
||||
// worker 从任务队列获取任务执行,空闲超时后自动退出(保持最小数量)。
|
||||
func (p *GoroutinePool) startWorker() {
|
||||
p.workers++
|
||||
atomic.AddInt32(&p.workers, 1)
|
||||
p.wg.Add(1)
|
||||
|
||||
go func() {
|
||||
@ -201,12 +201,14 @@ func (p *GoroutinePool) startWorker() {
|
||||
idleTimer.Reset(p.idleTimeout)
|
||||
|
||||
// 执行任务
|
||||
task(nil) // 注意:fasthttp.RequestCtx 需要在任务中传入
|
||||
// 注意:task 通过闭包捕获了 *fasthttp.RequestCtx,
|
||||
// 所以参数传 nil 是安全的,handler 使用闭包中的 ctx
|
||||
task(nil)
|
||||
|
||||
case <-idleTimer.C:
|
||||
// 穴闲超时,退出 worker(保持最小数量)
|
||||
atomic.AddInt32(&p.idleWorkers, -1)
|
||||
if p.workers > p.minWorkers {
|
||||
if atomic.LoadInt32(&p.workers) > p.minWorkers {
|
||||
return
|
||||
}
|
||||
idleTimer.Reset(p.idleTimeout)
|
||||
|
||||
@ -43,14 +43,21 @@ type VirtualHost struct {
|
||||
handler fasthttp.RequestHandler
|
||||
}
|
||||
|
||||
// NewVHostManager 创建虚拟主机管理器
|
||||
// NewVHostManager 创建虚拟主机管理器。
|
||||
//
|
||||
// 返回值:
|
||||
// - *VHostManager: 新创建的管理器实例
|
||||
func NewVHostManager() *VHostManager {
|
||||
return &VHostManager{
|
||||
hosts: make(map[string]*VirtualHost),
|
||||
}
|
||||
}
|
||||
|
||||
// AddHost 添加虚拟主机
|
||||
// AddHost 添加虚拟主机。
|
||||
//
|
||||
// 参数:
|
||||
// - name: 虚拟主机名称(域名)
|
||||
// - handler: 请求处理器
|
||||
func (v *VHostManager) AddHost(name string, handler fasthttp.RequestHandler) {
|
||||
v.hosts[name] = &VirtualHost{
|
||||
name: name,
|
||||
@ -58,7 +65,10 @@ func (v *VHostManager) AddHost(name string, handler fasthttp.RequestHandler) {
|
||||
}
|
||||
}
|
||||
|
||||
// SetDefault 设置默认主机
|
||||
// SetDefault 设置默认主机。
|
||||
//
|
||||
// 参数:
|
||||
// - handler: 默认主机的请求处理器
|
||||
func (v *VHostManager) SetDefault(handler fasthttp.RequestHandler) {
|
||||
v.defaultHost = &VirtualHost{
|
||||
name: "default",
|
||||
@ -66,7 +76,10 @@ func (v *VHostManager) SetDefault(handler fasthttp.RequestHandler) {
|
||||
}
|
||||
}
|
||||
|
||||
// Handler 返回虚拟主机选择器
|
||||
// Handler 返回虚拟主机选择器。
|
||||
//
|
||||
// 返回值:
|
||||
// - fasthttp.RequestHandler: 根据 Host 头分发请求的处理器
|
||||
func (v *VHostManager) Handler() fasthttp.RequestHandler {
|
||||
return func(ctx *fasthttp.RequestCtx) {
|
||||
host := stripPort(string(ctx.Host()))
|
||||
|
||||
@ -132,31 +132,31 @@ func NewTLSManager(cfg *config.SSLConfig) (*TLSManager, error) {
|
||||
issuers: make(map[string]*x509.Certificate),
|
||||
}
|
||||
|
||||
// Initialize OCSP stapling if enabled
|
||||
// 初始化 OCSP Stapling(如果启用)
|
||||
if cfg.OCSPStapling {
|
||||
ocspMgr := NewOCSPManager(DefaultOCSPConfig())
|
||||
manager.ocspManager = ocspMgr
|
||||
|
||||
// Parse certificate for OCSP
|
||||
// 解析证书用于 OCSP
|
||||
if len(cert.Certificate) > 0 {
|
||||
parsedCert, err := x509.ParseCertificate(cert.Certificate[0])
|
||||
if err == nil && len(parsedCert.OCSPServer) > 0 {
|
||||
// Store certificate for OCSP lookups
|
||||
// 存储证书用于 OCSP 查询
|
||||
serial := parsedCert.SerialNumber.String()
|
||||
manager.certificates[serial] = parsedCert
|
||||
|
||||
// Try to parse issuer from certificate chain
|
||||
// 尝试从证书链解析颁发者证书
|
||||
if len(cert.Certificate) > 1 {
|
||||
issuerCert, err := x509.ParseCertificate(cert.Certificate[1])
|
||||
if err == nil {
|
||||
manager.issuers[serial] = issuerCert
|
||||
// Register certificate for OCSP stapling
|
||||
// Errors are logged but don't prevent TLS from working
|
||||
// 注册证书用于 OCSP Stapling
|
||||
// 错误会记录日志但不会阻止 TLS 工作
|
||||
ocspMgr.RegisterCertificate(parsedCert, issuerCert)
|
||||
}
|
||||
}
|
||||
|
||||
// Set up GetConfigForClient callback for OCSP stapling
|
||||
// 设置 GetConfigForClient 回调用于 OCSP Stapling
|
||||
tlsCfg.GetConfigForClient = manager.getConfigForClientWithOCSP
|
||||
}
|
||||
}
|
||||
@ -164,7 +164,7 @@ func NewTLSManager(cfg *config.SSLConfig) (*TLSManager, error) {
|
||||
ocspMgr.Start()
|
||||
}
|
||||
|
||||
// Set as default config
|
||||
// 设置为默认配置
|
||||
manager.defaultCfg = tlsCfg
|
||||
|
||||
return manager, nil
|
||||
|
||||
@ -94,65 +94,96 @@ func (l *leastConn) Select(targets []*Target) *Target {
|
||||
|
||||
// Server TCP/UDP Stream 代理服务器。
|
||||
type Server struct {
|
||||
listeners map[string]net.Listener
|
||||
// listeners TCP 监听器映射,按 upstream 名称索引
|
||||
listeners map[string]net.Listener
|
||||
// udpServers UDP 服务器映射
|
||||
udpServers map[string]*udpServer
|
||||
upstreams map[string]*Upstream
|
||||
connCount int64 // 当前连接数
|
||||
mu sync.RWMutex
|
||||
running atomic.Bool
|
||||
// upstreams 上游配置映射
|
||||
upstreams map[string]*Upstream
|
||||
// connCount 当前连接数
|
||||
connCount int64
|
||||
// mu 读写锁,保护并发访问
|
||||
mu sync.RWMutex
|
||||
// running 运行状态标志
|
||||
running atomic.Bool
|
||||
}
|
||||
|
||||
// Upstream Stream 上游配置。
|
||||
type Upstream struct {
|
||||
name string
|
||||
targets []*Target
|
||||
balancer Balancer
|
||||
// name 上游名称
|
||||
name string
|
||||
// targets 目标服务器列表
|
||||
targets []*Target
|
||||
// balancer 负载均衡器
|
||||
balancer Balancer
|
||||
// healthChk 健康检查器
|
||||
healthChk *HealthChecker
|
||||
mu sync.RWMutex
|
||||
// mu 读写锁,保护并发访问
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
// Target Stream 目标服务器。
|
||||
type Target struct {
|
||||
addr string
|
||||
weight int
|
||||
// addr 目标地址(host:port)
|
||||
addr string
|
||||
// weight 权重
|
||||
weight int
|
||||
// healthy 健康状态
|
||||
healthy atomic.Bool
|
||||
conns int64 // 当前连接数
|
||||
// conns 当前连接数
|
||||
conns int64
|
||||
}
|
||||
|
||||
// HealthChecker Stream 健康检查器。
|
||||
type HealthChecker struct {
|
||||
// upstream 所属上游
|
||||
upstream *Upstream
|
||||
// interval 检查间隔
|
||||
interval time.Duration
|
||||
timeout time.Duration
|
||||
stopCh chan struct{}
|
||||
// timeout 检查超时
|
||||
timeout time.Duration
|
||||
// stopCh 停止信号通道
|
||||
stopCh chan struct{}
|
||||
}
|
||||
|
||||
// Config Stream 配置。
|
||||
type Config struct {
|
||||
Listen string // 监听地址
|
||||
Protocol string // tcp 或 udp
|
||||
Upstream UpstreamSpec // 上游配置
|
||||
// Listen 监听地址
|
||||
Listen string
|
||||
// Protocol 协议类型(tcp 或 udp)
|
||||
Protocol string
|
||||
// Upstream 上游配置
|
||||
Upstream UpstreamSpec
|
||||
}
|
||||
|
||||
// UpstreamSpec 上游配置规格。
|
||||
type UpstreamSpec struct {
|
||||
Name string
|
||||
Targets []TargetSpec
|
||||
// Name 上游名称
|
||||
Name string
|
||||
// Targets 目标服务器列表
|
||||
Targets []TargetSpec
|
||||
// LoadBalance 负载均衡算法
|
||||
LoadBalance string
|
||||
// HealthCheck 健康检查配置
|
||||
HealthCheck HealthCheckSpec
|
||||
}
|
||||
|
||||
// TargetSpec 目标配置规格。
|
||||
type TargetSpec struct {
|
||||
Addr string
|
||||
// Addr 目标地址(host:port)
|
||||
Addr string
|
||||
// Weight 权重
|
||||
Weight int
|
||||
}
|
||||
|
||||
// HealthCheckSpec 健康检查配置规格。
|
||||
type HealthCheckSpec struct {
|
||||
// Interval 检查间隔
|
||||
Interval time.Duration
|
||||
Timeout time.Duration
|
||||
Enabled bool
|
||||
// Timeout 检查超时
|
||||
Timeout time.Duration
|
||||
// Enabled 是否启用
|
||||
Enabled bool
|
||||
}
|
||||
|
||||
// NewServer 创建 Stream 服务器。
|
||||
|
||||
14
main.go
14
main.go
@ -1,3 +1,17 @@
|
||||
// Package main 提供 Lolly 服务器的入口程序。
|
||||
//
|
||||
// 该文件包含命令行参数解析和应用程序启动逻辑:
|
||||
// - 配置文件路径指定(-c/--config)
|
||||
// - 默认配置生成(--generate-config)
|
||||
// - 版本信息显示(-v)
|
||||
//
|
||||
// 使用示例:
|
||||
//
|
||||
// lolly -c /etc/lolly.yaml # 使用指定配置启动
|
||||
// lolly --generate-config -o config.yaml # 生成默认配置
|
||||
// lolly -v # 显示版本信息
|
||||
//
|
||||
// 作者:xfy
|
||||
package main
|
||||
|
||||
import (
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user