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