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

949 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 配置解析
**配置结构体设计**
```go
// 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 命令行工具
**支持的命令**
```bash
lolly # 启动服务器(默认配置)
lolly -c /path/to.yaml # 指定配置文件
lolly -t # 测试配置语法
lolly -v # 显示版本
lolly -s reload # 重载配置(信号)
lolly -s stop # 停止服务
lolly -s quit # 优雅停止
```
**实现方式**
- 使用 `flag` 标准库处理参数
- 信号处理:`SIGTERM``SIGINT``SIGHUP`
### 验证方法
```bash
# 构建测试
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 服务器
**核心实现**
```go
// 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 配置:`ReadTimeout``WriteTimeout``IdleTimeout`
#### 2.2 静态文件服务
**实现**
```go
// 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 匹配)
**路由设计**
```go
// 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 多虚拟主机支持
**实现**
```go
// internal/server/vhost.go
// VHostManager 虚拟主机管理器
type VHostManager struct {
hosts map[string]*VirtualHost // 按 server_name 索引
}
```
**功能**
-`Host` 头选择虚拟主机
- 默认主机fallback
- SNI 支持SSL
### 验证方法
```bash
# 启动服务器
./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 反向代理核心
**实现**
```go
// 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 负载均衡算法
**实现**
```go
// 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 健康检查
**实现**
```go
// 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()
```
**类型**
- **被动检查**:请求失败时标记不健康
- **主动检查**:定期发送探测请求
**配置示例**
```yaml
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 代理缓存(可选)
**实现**
```go
// internal/cache/proxy_cache.go
// ProxyCache 代理响应缓存
type ProxyCache struct {
storage CacheStorage
rules []CacheRule
}
```
### 验证方法
```bash
# 启动后端服务(用于测试)
# 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 支持
**实现**
```go
// 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 访问控制
**实现**
```go
// 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
```
**配置示例**
```yaml
security:
access:
allow: [192.168.1.0/24, 10.0.0.0/8]
deny: [192.168.2.100]
default: deny
```
#### 4.3 请求限制
**实现**
```go
// 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 基础认证
**实现**
```go
// internal/security/auth.go
// BasicAuth 基础认证
type BasicAuth struct {
users map[string]string // username -> hashed_password
}
// Authenticate 验证认证信息
func (b *BasicAuth) Authenticate(r *http.Request) bool
```
**配置示例**
```yaml
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`
### 验证方法
```bash
# 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 重写
**实现**
```go
// 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 // 停止匹配
)
```
**配置示例**
```yaml
rewrite:
- pattern: "^/old/(.*)$"
replacement: "/new/$1"
flag: permanent # 301
- pattern: "^/api/v1/(.*)$"
replacement: "/api/v2/$1"
flag: last
```
#### 5.2 Gzip/Brotli 压缩
**实现**
```go
// internal/compression/compression.go
// CompressionHandler 压缩中间件
type CompressionHandler struct {
types []string // 压缩的 MIME 类型
level int // 压缩级别
minSize int // 最小压缩大小
}
```
**配置示例**
```yaml
compression:
type: gzip # gzip/brotli/both
level: 6 # 1-9
min_size: 1024 # 最小 1KB 才压缩
types: [text/html, text/css, application/json]
```
#### 5.3 缓存系统
**静态文件缓存**
```go
// internal/cache/file_cache.go
// FileCache 文件描述符缓存
type FileCache struct {
maxEntries int
inactive time.Duration
entries map[string]*FileEntry
}
```
**代理响应缓存**
```go
// internal/cache/proxy_cache.go
// ProxyCache 代理缓存
type ProxyCache struct {
storage Storage // 内存/磁盘存储
rules []CacheRule
maxAge time.Duration
}
```
#### 5.4 日志系统
**实现**
```go
// 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 - 请求耗时
```
**配置示例**
```yaml
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 状态监控端点
**实现**
```go
// internal/server/status.go
// StatusHandler 状态监控处理器
type StatusHandler struct {
server *Server
}
// 返回数据
type Status struct {
Connections int
Requests int64
BytesSent int64
BytesReceived int64
Uptime time.Duration
}
```
**配置示例**
```yaml
monitoring:
status:
path: /_status # 状态端点路径
allow: [127.0.0.1] # 仅允许本地访问
```
### 验证方法
```bash
# 重写测试
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 代理
**实现**
```go
// 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
}
```
**配置示例**
```yaml
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 优雅升级(热升级)
**实现**
```go
// internal/server/upgrade.go
// GracefulUpgrade 优雅升级
func GracefulUpgrade(newBinary string) error
// 逻辑:
// 1. 启动新进程,继承监听 socket
// 2. 新进程开始接受新连接
// 3. 旧进程停止接受新连接,完成现有请求后退出
```
**信号处理**
- `SIGUSR2`:触发升级
- `SIGWINCH`:优雅关闭 worker
#### 6.3 性能优化
**优化点**
- 连接复用:`http.Transport` 配置
- 缓冲池:减少内存分配
- 零拷贝:`io.Copy` 使用 `sendfile`Linux
- Goroutine 池:控制并发数(可选)
- 对象池:`sync.Pool` 复用对象
#### 6.4 信号处理完善
**完整信号支持**
| 信号 | 行为 |
|------|------|
| `SIGTERM/SIGINT` | 快速停止 |
| `SIGQUIT` | 优雅停止 |
| `SIGHUP` | 重载配置 |
| `SIGUSR1` | 重新打开日志 |
| `SIGUSR2` | 热升级 |
### 验证方法
```bash
# 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/HTTPS`docs/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`(必须遵循)