lolly/docs/plan.md
xfy 9cae5ad8cf chore(init): initialize project with nginx documentation
- Add Go module initialization (go 1.26)
- Add comprehensive NGINX documentation covering:
  - Overview, installation, HTTP core module
  - Proxy/load balancing, SSL/TLS, URL rewrite
  - Compression/caching, logging/monitoring
  - Security, TCP/UDP stream, mail proxy
  - Performance tuning, Git commit guide
- Add standard Go .gitignore

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-02 11:45:53 +08:00

21 KiB
Raw Blame History

Lolly 实现计划

概述

目标:创建一个类似 nginx 的高性能 HTTP 服务器,纯 Go 实现YAML 配置,单二进制运行。

核心原则

  • 不是 1:1 复刻 nginx而是更现代、更易用
  • 充分利用 Go 特性goroutine、channel、标准库
  • 功能完整性优先于极致性能
  • 选择"更简单易用"的设计方案

第一阶段:项目骨架与配置系统

目标

搭建项目基础结构,实现配置解析和命令行工具。

任务列表

1.1 项目目录结构

lolly/
├── cmd/lolly/main.go           # 程序入口
├── internal/
│   ├── config/                 # 配置解析模块
│   ├── server/                 # HTTP 服务器核心
│   ├── handler/                # 请求处理器
│   └── middleware/             # 中间件系统
├── pkg/
│   └── utils/                  # 公共工具函数
├── configs/
│   └── lolly.yaml              # 默认配置示例
├── go.mod
├── go.sum
├── Makefile                    # 构建脚本
└── README.md

关键文件

  • cmd/lolly/main.go - 入口点,初始化和启动逻辑
  • internal/config/config.go - 配置结构体定义和解析

1.2 YAML 配置解析

配置结构体设计

// internal/config/config.go

// Config 根配置结构
type Config struct {
    Server     ServerConfig     `yaml:"server"`
    Servers    []ServerConfig   `yaml:"servers"`    // 多虚拟主机
    Logging    LoggingConfig    `yaml:"logging"`
    Performance PerformanceConfig `yaml:"performance"`
}

// ServerConfig 服务器配置
type ServerConfig struct {
    Listen      string         `yaml:"listen"`       // 监听地址 ":8080"
    Name        string         `yaml:"name"`         // server_name
    Static      StaticConfig   `yaml:"static"`       // 静态文件
    Proxy       []ProxyConfig  `yaml:"proxy"`        // 反向代理规则
    SSL         SSLConfig      `yaml:"ssl"`          // SSL 配置
}

// StaticConfig 静态文件配置
type StaticConfig struct {
    Root   string   `yaml:"root"`    // 根目录
    Index  []string `yaml:"index"`   // 索引文件
}

// ProxyConfig 反向代理配置
type ProxyConfig struct {
    Path        string   `yaml:"path"`         // 路径匹配
    Target      string   `yaml:"target"`       // 目标地址
    LoadBalance string   `yaml:"load_balance"` // 负载均衡算法
}

实现要点

  • 使用 gopkg.in/yaml.v3 解析 YAML
  • 支持配置文件路径命令行参数 -c/--config
  • 配置验证:必填字段检查、路径有效性
  • 默认配置:最小配置即可运行

1.3 命令行工具

支持的命令

lolly                    # 启动服务器(默认配置)
lolly -c /path/to.yaml   # 指定配置文件
lolly -t                 # 测试配置语法
lolly -v                 # 显示版本
lolly -s reload          # 重载配置(信号)
lolly -s stop            # 停止服务
lolly -s quit            # 优雅停止

实现方式

  • 使用 flag 标准库处理参数
  • 信号处理:SIGTERMSIGINTSIGHUP

验证方法

# 构建测试
go build -o lolly cmd/lolly/main.go

# 配置解析测试
./lolly -t -c configs/lolly.yaml
# 输出:配置有效

# 版本显示
./lolly -v
# 输出lolly version 0.1.0

提交信息

feat(config): 实现项目骨架和 YAML 配置解析

- 创建项目目录结构cmd/internal/pkg/configs
- 定义配置结构体Server、Static、Proxy、Logging
- 实现 YAML 配置文件解析
- 添加命令行参数支持(-c、-t、-v、-s
- 添加默认配置示例文件

第二阶段HTTP 核心功能

目标

实现基础 HTTP 服务器、静态文件服务、请求路由。

任务列表

2.1 基础 HTTP 服务器

核心实现

// internal/server/server.go

// Server HTTP 服务器
type Server struct {
    config    *config.Config
    handler   *handler.Handler
    listeners map[string]*net.Listener
    running   bool
    stopChan  chan struct{}
}

// Start 启动服务器
func (s *Server) Start() error

// Stop 停止服务器
func (s *Server) Stop() error

// GracefulStop 优雅停止(等待请求完成)
func (s *Server) GracefulStop(timeout time.Duration) error

实现要点

  • 使用 net/http 标准库为基础
  • 支持 multiple listeners多端口/多虚拟主机)
  • 优雅关闭:Shutdown() 方法
  • keep-alive 配置:ReadTimeoutWriteTimeoutIdleTimeout

2.2 静态文件服务

实现

// internal/handler/static.go

// StaticHandler 静态文件处理器
type StaticHandler struct {
    root  string
    index []string
}

// ServeHTTP 处理静态文件请求
func (h *StaticHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

功能清单

  • 文件路径安全检查(防止目录遍历)
  • MIME 类型自动识别(mime.TypeByExtension
  • 索引文件支持index.html、index.htm
  • 目录列表(可选,默认禁用)
  • Range 请求支持(部分下载)
  • 文件缓存优化(可选)

2.3 请求路由Location 匹配)

路由设计

// internal/handler/router.go

// Router 请求路由器
type Router struct {
    routes []*Route
}

// Route 路由规则
type Route struct {
    Path     string      // 路径模式
    Type     MatchType   // 匹配类型:精确/前缀/正则
    Handler  http.Handler
}

// 匹配类型
type MatchType int
const (
    MatchExact  MatchType = iota  // 精确匹配 (=)
    MatchPrefix                    // 前缀匹配 (^~)
    MatchRegex                     // 正则匹配 (~)
)

匹配优先级(同 nginx

  1. 精确匹配 =
  2. 前缀匹配(优先)^~
  3. 正则匹配 ~(按顺序)
  4. 最长前缀匹配

2.4 多虚拟主机支持

实现

// internal/server/vhost.go

// VHostManager 虚拟主机管理器
type VHostManager struct {
    hosts map[string]*VirtualHost  // 按 server_name 索引
}

功能

  • Host 头选择虚拟主机
  • 默认主机fallback
  • SNI 支持SSL

验证方法

# 启动服务器
./lolly -c configs/lolly.yaml

# 静态文件测试
curl http://localhost:8080/index.html

# 路由测试
curl http://localhost:8080/static/test.txt
curl http://localhost:8080/api/health  # 应返回 404代理未实现

提交信息

feat(server): 实现 HTTP 服务器核心功能

- 实现基础 HTTP 服务器(启动/停止/优雅关闭)
- 实现静态文件服务MIME 类型、索引文件、Range 请求)
- 实现请求路由器(精确/前缀/正则匹配)
- 支持多虚拟主机配置
- 支持 keep-alive 长连接配置

第三阶段:反向代理与负载均衡

目标

实现反向代理功能、多种负载均衡算法、健康检查。

任务列表

3.1 反向代理核心

实现

// internal/proxy/proxy.go

// Proxy 反向代理
type Proxy struct {
    targets    []*Target
    transport  *http.Transport
    bufferPool *bufferPool
}

// Target 后端目标
type Target struct {
    URL        *url.URL
    Weight     int
    Healthy    bool
    Connections int
}

功能清单

  • 请求转发:修改请求头、请求体
  • 响应处理:修改响应头
  • 超时配置:连接超时、响应超时
  • WebSocket 支持Upgrade 协议检测和转发
  • 错误处理:后端不可用时的响应

3.2 负载均衡算法

实现

// internal/loadbalance/balancer.go

// Balancer 负载均衡器接口
type Balancer interface {
    Select(targets []*Target) *Target
}

// RoundRobin 轮询算法
type RoundRobin struct {
    current uint64
}

// WeightedRoundRobin 权重轮询
type WeightedRoundRobin struct {
    weights []int
    current int
}

// LeastConnections 最少连接
type LeastConnections struct{}

// IPHash IP 哈希
type IPHash struct{}

算法实现

算法 说明
round_robin 简单轮询
weighted_round_robin 按权重轮询
least_conn 选择连接数最少的目标
ip_hash 按客户端 IP 哈希固定目标

3.3 健康检查

实现

// internal/proxy/health.go

// HealthChecker 健康检查器
type HealthChecker struct {
    interval   time.Duration
    timeout    time.Duration
    path       string  // 健康检查路径
    targets    []*Target
}

// Check 执行健康检查
func (h *HealthChecker) Check()

// Start 后台定期检查
func (h *HealthChecker) Start()

类型

  • 被动检查:请求失败时标记不健康
  • 主动检查:定期发送探测请求

配置示例

proxy:
  - path: /api
    targets:
      - url: http://backend1:8080
        weight: 3
      - url: http://backend2:8080
        weight: 1
    load_balance: weighted_round_robin
    health_check:
      interval: 10s
      path: /health
      timeout: 5s

3.4 代理缓存(可选)

实现

// internal/cache/proxy_cache.go

// ProxyCache 代理响应缓存
type ProxyCache struct {
    storage CacheStorage
    rules   []CacheRule
}

验证方法

# 启动后端服务(用于测试)
# backend1: python3 -m http.server 8001
# backend2: python3 -m http.server 8002

# 配置代理
# lolly.yaml:
#   proxy:
#     - path: /api
#       targets: [http://localhost:8001, http://localhost:8002]

# 测试代理
curl http://localhost:8080/api/test

# 测试负载均衡(多次请求)
for i in {1..10}; do curl http://localhost:8080/api/test; done

提交信息

feat(proxy): 实现反向代理和负载均衡功能

- 实现反向代理核心(请求转发、响应处理)
- 实现负载均衡算法轮询、权重、最少连接、IP哈希
- 实现被动健康检查(请求失败标记)
- 实现主动健康检查(定期探测)
- 支持 WebSocket 协议升级代理

第四阶段:安全与 SSL/TLS

目标

实现 HTTPS 支持、访问控制、请求限制。

任务列表

4.1 SSL/TLS 支持

实现

// internal/ssl/ssl.go

// SSLConfig SSL 配置
type SSLConfig struct {
    Cert       string   `yaml:"cert"`       // 证书路径
    Key        string   `yaml:"key"`        // 私钥路径
    Protocols  []string `yaml:"protocols"`  // TLS 版本
    Ciphers    []string `yaml:"ciphers"`    // 加密套件
}

// TLSManager TLS 管理器
type TLSManager struct {
    configs map[string*tls.Config  // 按 server_name
}

功能清单

  • 证书加载PEM 格式
  • TLS 版本控制TLSv1.2、TLSv1.3
  • 加密套件配置
  • SSL 会话缓存(减少握手开销)
  • SNI 支持(多证书)
  • HTTP/2 自动启用TLS 时)

4.2 IP 访问控制

实现

// internal/security/access.go

// AccessControl IP 访问控制
type AccessControl struct {
    allowList []net.IPNet
    denyList  []net.IPNet
    default   Action  // 默认动作
}

// Check 检查 IP 是否允许
func (a *AccessControl) Check(ip net.IP) bool

配置示例

security:
  access:
    allow: [192.168.1.0/24, 10.0.0.0/8]
    deny: [192.168.2.100]
    default: deny

4.3 请求限制

实现

// internal/security/ratelimit.go

// RateLimiter 速率限制器
type RateLimiter struct {
    requests int
    per      time.Duration
    buckets  map[string]*Bucket
    mu       sync.RWMutex
}

// ConnLimiter 连接数限制器
type ConnLimiter struct {
    max      int
    current  int
    mu       sync.Mutex
}

功能

  • 请求速率限制(limit_req
  • 连接数限制(limit_conn
  • 按 IP 或按 key 限制
  • 超限响应429 Too Many Requests

4.4 基础认证

实现

// internal/security/auth.go

// BasicAuth 基础认证
type BasicAuth struct {
    users map[string]string  // username -> hashed_password
}

// Authenticate 验证认证信息
func (b *BasicAuth) Authenticate(r *http.Request) bool

配置示例

security:
  auth:
    type: basic
    users:
      - name: admin
        password: $apr1$...  # htpasswd 格式
    realm: "Restricted Area"

4.5 安全头部

自动添加的安全头

  • X-Frame-Options: DENY
  • X-Content-Type-Options: nosniff
  • X-XSS-Protection: 1; mode=block
  • Strict-Transport-Security: max-age=31536000

验证方法

# HTTPS 测试
curl -k https://localhost:8443/

# IP 访问控制测试
curl --interface 192.168.1.100 http://localhost:8080/  # 应允许
curl --interface 192.168.2.100 http://localhost:8080/  # 应拒绝

# 速率限制测试
for i in {1..20}; do curl http://localhost:8080/; done  # 部分应返回 429

# 基础认证测试
curl -u admin:password http://localhost:8080/protected/

提交信息

feat(security): 实现 SSL/TLS 和安全访问控制

- 实现 SSL/TLS 支持证书加载、TLS版本、加密套件
- 实现 SSL 会话缓存
- 实现 SNI 多证书支持
- 实现 IP 访问控制(白名单/黑名单)
- 实现请求速率限制
- 实现连接数限制
- 实现基础认证Basic Auth
- 添加安全响应头部

第五阶段:增强功能

目标

实现 URL 重写、压缩、缓存、日志系统。

任务列表

5.1 URL 重写

实现

// internal/rewrite/rewrite.go

// RewriteRule 重写规则
type RewriteRule struct {
    Pattern     string  // 匹配模式
    Replacement string  // 替换目标
    Flag        RewriteFlag  // last/redirect/break
}

type RewriteFlag int
const (
    FlagLast     RewriteFlag = iota  // 继续匹配其他规则
    FlagRedirect                      // 302 重定向
    FlagPermanent                     // 301 重定向
    FlagBreak                         // 停止匹配
)

配置示例

rewrite:
  - pattern: "^/old/(.*)$"
    replacement: "/new/$1"
    flag: permanent  # 301
  - pattern: "^/api/v1/(.*)$"
    replacement: "/api/v2/$1"
    flag: last

5.2 Gzip/Brotli 压缩

实现

// internal/compression/compression.go

// CompressionHandler 压缩中间件
type CompressionHandler struct {
    types    []string  // 压缩的 MIME 类型
    level    int       // 压缩级别
    minSize  int       // 最小压缩大小
}

配置示例

compression:
  type: gzip  # gzip/brotli/both
  level: 6    # 1-9
  min_size: 1024  # 最小 1KB 才压缩
  types: [text/html, text/css, application/json]

5.3 缓存系统

静态文件缓存

// internal/cache/file_cache.go

// FileCache 文件描述符缓存
type FileCache struct {
    maxEntries int
    inactive   time.Duration
    entries    map[string]*FileEntry
}

代理响应缓存

// internal/cache/proxy_cache.go

// ProxyCache 代理缓存
type ProxyCache struct {
    storage   Storage  // 内存/磁盘存储
    rules     []CacheRule
    maxAge    time.Duration
}

5.4 日志系统

实现

// internal/logging/logging.go

// Logger 日志管理器
type Logger struct {
    accessLog *AccessLogger
    errorLog  *ErrorLogger
    level     LogLevel
}

// AccessLogger 访问日志
type AccessLogger struct {
    format string  // 日志格式
    output io.Writer
}

// LogFormat 日志格式变量
// $remote_addr - 客户端 IP
// $request - 请求行
// $status - 响应状态码
// $body_bytes_sent - 响应体大小
// $request_time - 请求耗时

配置示例

logging:
  access:
    path: /var/log/lolly/access.log
    format: "$remote_addr - $request - $status - $body_bytes_sent"
  error:
    path: /var/log/lolly/error.log
    level: info  # debug/info/warn/error

5.5 状态监控端点

实现

// internal/server/status.go

// StatusHandler 状态监控处理器
type StatusHandler struct {
    server *Server
}

// 返回数据
type Status struct {
    Connections   int
    Requests      int64
    BytesSent     int64
    BytesReceived int64
    Uptime        time.Duration
}

配置示例

monitoring:
  status:
    path: /_status  # 状态端点路径
    allow: [127.0.0.1]  # 仅允许本地访问

验证方法

# 重写测试
curl http://localhost:8080/old/page  # 应重定向到 /new/page

# 压缩测试
curl -H "Accept-Encoding: gzip" -I http://localhost:8080/index.html
# 应返回 Content-Encoding: gzip

# 缓存测试
curl -I http://localhost:8080/static/test.txt
# 应返回缓存相关头部

# 日志测试
cat /var/log/lolly/access.log

# 状态监控测试
curl http://localhost:8080/_status

提交信息

feat(enhance): 实现重写、压缩、缓存和日志功能

- 实现 URL 重写规则正则匹配、301/302重定向
- 实现 Gzip 响应压缩
- 实现静态文件缓存(文件描述符缓存)
- 实现代理响应缓存
- 实现访问日志(可定制格式)
- 实现分级错误日志
- 实现状态监控端点

第六阶段:高级功能

目标

实现 TCP/UDP Stream 代理、性能优化、优雅升级。

任务列表

6.1 TCP/UDP Stream 代理

实现

// internal/stream/stream.go

// StreamServer TCP/UDP 代理服务器
type StreamServer struct {
    listeners map[string]*net.Listener
    upstreams map[string]*StreamUpstream
}

// StreamUpstream Stream 上游
type StreamUpstream struct {
    targets  []*StreamTarget
    balancer Balancer
}

// StreamTarget Stream 目标
type StreamTarget struct {
    addr      string
    healthy   bool
}

配置示例

stream:
  - listen: 3306
    protocol: tcp
    upstream:
      targets: [mysql1:3306, mysql2:3306]
      load_balance: round_robin
  - listen: 53
    protocol: udp
    upstream:
      targets: [dns1:53, dns2:53]

6.2 优雅升级(热升级)

实现

// internal/server/upgrade.go

// GracefulUpgrade 优雅升级
func GracefulUpgrade(newBinary string) error

// 逻辑:
// 1. 启动新进程,继承监听 socket
// 2. 新进程开始接受新连接
// 3. 旧进程停止接受新连接,完成现有请求后退出

信号处理

  • SIGUSR2:触发升级
  • SIGWINCH:优雅关闭 worker

6.3 性能优化

优化点

  • 连接复用:http.Transport 配置
  • 缓冲池:减少内存分配
  • 零拷贝:io.Copy 使用 sendfileLinux
  • Goroutine 池:控制并发数(可选)
  • 对象池:sync.Pool 复用对象

6.4 信号处理完善

完整信号支持

信号 行为
SIGTERM/SIGINT 快速停止
SIGQUIT 优雅停止
SIGHUP 重载配置
SIGUSR1 重新打开日志
SIGUSR2 热升级

验证方法

# TCP Stream 测试
# 启动 MySQL 后端
mysql -h localhost -P 3306  # 应通过 lolly 代理连接

# 热升级测试
kill -USR2 <pid>  # 触发升级
ps aux | grep lolly  # 应有两个进程

# 性能测试
# 使用 wrk 或 ab 进行压力测试
wrk -t4 -c1000 -d30s http://localhost:8080/

提交信息

feat(advanced): 实现 Stream 代理和高级功能

- 实现 TCP Stream 代理和负载均衡
- 实现 UDP Stream 代理
- 实现优雅升级(热升级)
- 完善信号处理SIGHUP、SIGUSR1、SIGUSR2
- 实现性能优化(连接复用、缓冲池)

文件依赖关系图

Phase 1:
  cmd/lolly/main.go → internal/config/config.go

Phase 2:
  internal/server/server.go → internal/config/config.go
  internal/server/server.go → internal/handler/router.go
  internal/handler/router.go → internal/handler/static.go

Phase 3:
  internal/handler/router.go → internal/proxy/proxy.go
  internal/proxy/proxy.go → internal/loadbalance/balancer.go
  internal/proxy/proxy.go → internal/proxy/health.go

Phase 4:
  internal/server/server.go → internal/ssl/ssl.go
  internal/handler/router.go → internal/security/access.go
  internal/handler/router.go → internal/security/ratelimit.go
  internal/handler/router.go → internal/security/auth.go

Phase 5:
  internal/handler/router.go → internal/rewrite/rewrite.go
  internal/server/server.go → internal/compression/compression.go
  internal/proxy/proxy.go → internal/cache/proxy_cache.go
  internal/server/server.go → internal/logging/logging.go

Phase 6:
  cmd/lolly/main.go → internal/stream/stream.go
  internal/server/server.go → internal/server/upgrade.go

总体进度追踪

阶段 状态 主要功能
Phase 1 待开始 项目骨架、配置系统
Phase 2 待开始 HTTP 核心、静态文件、路由
Phase 3 待开始 反向代理、负载均衡
Phase 4 待开始 SSL/TLS、安全控制
Phase 5 待开始 重写、压缩、缓存、日志
Phase 6 待开始 Stream、性能优化

参考文档

详细功能参考 docs/ 目录:

  • HTTP 核心:docs/03-nginx-http-core.md
  • 代理负载均衡:docs/04-nginx-proxy-loadbalancing.md
  • SSL/HTTPSdocs/05-nginx-ssl-https.md
  • URL 重写:docs/06-nginx-rewrite.md
  • 压缩缓存:docs/07-nginx-compression-caching.md
  • 日志监控:docs/08-nginx-logging-monitoring.md
  • 安全控制:docs/09-nginx-security.md
  • Stream 代理:docs/10-nginx-stream-tcp-udp.md
  • 性能优化:docs/12-nginx-performance-tuning.md

代码注释规范docs/comments.md(必须遵循)