diff --git a/go.mod b/go.mod index 2bb982e..85870b8 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.26.1 require ( github.com/andybalholm/brotli v1.2.1 github.com/fasthttp/router v1.5.4 + github.com/goccy/go-json v0.10.4 github.com/google/uuid v1.6.0 github.com/gorilla/websocket v1.5.3 github.com/hashicorp/golang-lru/v2 v2.0.7 @@ -41,7 +42,6 @@ require ( github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect - github.com/goccy/go-json v0.10.4 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.10 // indirect github.com/mattn/go-colorable v0.1.14 // indirect diff --git a/internal/benchmark/tools/AGENTS.md b/internal/benchmark/tools/AGENTS.md deleted file mode 100644 index b204270..0000000 --- a/internal/benchmark/tools/AGENTS.md +++ /dev/null @@ -1,42 +0,0 @@ - - - -# tools - -## Purpose -基准测试工具集,提供 Mock 后端服务器、负载生成器和测试数据生成功能,支持各种测试场景(延迟、错误、随机响应)。 - -## Key Files - -| File | Description | -|------|-------------| -| `mock_backend.go` | Mock 后端实现,支持多种响应模式(固定、延迟、错误、随机) | -| `loadgen.go` | 负载生成器,收集 QPS、延迟分布(P50/P90/P99)统计 | -| `testdata.go` | 测试数据生成,支持多种预定义大小(1KB~10MB) | - -## For AI Agents - -### Working In This Directory -- Mock 后端使用 `fasthttputil.InmemoryListener` 进行零网络开销测试 -- `BackendMode` 支持四种模式:ModeFixed、ModeDelay、ModeError、ModeRandomResponse -- 负载生成器支持并发执行和百分位延迟统计 -- 测试数据使用随机字节填充,适合压缩测试 - -### Testing Requirements -- 工具本身无独立测试,作为其他模块基准测试的基础设施 -- 使用示例见 `internal/proxy/proxy_bench_test.go` - -### Common Patterns -- 创建简单后端:`SimpleMockBackend(statusCode, body)` -- 创建延迟后端:`DelayedMockBackend(delay, body)` -- 创建错误后端:`ErrorMockBackend(errorRate, body)` -- 创建加权目标:`CreateWeightedTestTargets(n)` -- 运行负载测试:`loadGen.Run(n, concurrency)` - -## Dependencies - -### External -- `github.com/valyala/fasthttp` - HTTP 框架 -- `github.com/valyala/fasthttp/fasthttputil` - 内存监听器 - - \ No newline at end of file diff --git a/internal/benchmark/tools/benchmark_context.go b/internal/benchmark/tools/benchmark_context.go deleted file mode 100644 index b63e3b7..0000000 --- a/internal/benchmark/tools/benchmark_context.go +++ /dev/null @@ -1,359 +0,0 @@ -// Package tools 提供基准测试工具函数。 -// -// 该文件提供标准化的基准测试上下文构造器,用于: -// - 快速创建模拟的 fasthttp.RequestCtx -// - 标准化测试数据大小 -// - 简化组件级基准测试编写 -// -// 作者:xfy -package tools - -import ( - "bytes" - "math/rand" - "net" - "strconv" - "time" - - "github.com/valyala/fasthttp" -) - -// BenchmarkContext 提供标准化的基准测试上下文。 -// -// 包含构造模拟请求所需的所有配置。 -type BenchmarkContext struct { - // randSrc 随机数生成器 - randSrc *rand.Rand - - // RequestSize 请求数据大小 - RequestSize TestDataSize - - // ResponseSize 响应数据大小 - ResponseSize TestDataSize - - // Concurrency 并发级别(用于并行测试) - Concurrency int -} - -// NewBenchmarkContext 创建基准测试上下文。 -// -// 参数: -// - reqSize: 请求数据大小 -// - respSize: 响应数据大小 -// - concurrency: 并发级别 -// -// 返回值: -// - *BenchmarkContext: 配置好的基准测试上下文 -func NewBenchmarkContext(reqSize, respSize TestDataSize, concurrency int) *BenchmarkContext { - return &BenchmarkContext{ - RequestSize: reqSize, - ResponseSize: respSize, - Concurrency: concurrency, - randSrc: rand.New(rand.NewSource(time.Now().UnixNano())), - } -} - -// MockRequestCtx 构造模拟的 fasthttp.RequestCtx。 -// -// 创建一个可用于基准测试的请求上下文,包含: -// - 请求方法和路径 -// - 请求头 -// - 请求体 -// - 远程地址 -// -// 参数: -// - method: HTTP 方法 (GET, POST, etc.) -// - path: 请求路径 -// -// 返回值: -// - *fasthttp.RequestCtx: 模拟的请求上下文 -func (bc *BenchmarkContext) MockRequestCtx(method, path string) *fasthttp.RequestCtx { - ctx := &fasthttp.RequestCtx{} - - // 设置请求行 - ctx.Request.Header.SetMethod(method) - ctx.Request.SetRequestURI(path) - - // 设置远程地址 - ctx.Init(&fasthttp.Request{}, &net.TCPAddr{ - IP: net.ParseIP("192.168.1.100"), - Port: 12345, - }, nil) - - // 设置请求体 - if bc.RequestSize > 0 { - body := GenerateTestData(bc.RequestSize) - ctx.Request.SetBody(body) - } - - return ctx -} - -// MockRequestCtxWithHeaders 构造带自定义请求头的模拟上下文。 -// -// 参数: -// - method: HTTP 方法 -// - path: 请求路径 -// - headers: 请求头键值对 -// -// 返回值: -// - *fasthttp.RequestCtx: 模拟的请求上下文 -func (bc *BenchmarkContext) MockRequestCtxWithHeaders(method, path string, headers map[string]string) *fasthttp.RequestCtx { - ctx := bc.MockRequestCtx(method, path) - - // 设置请求头 - for key, value := range headers { - ctx.Request.Header.Set(key, value) - } - - return ctx -} - -// MockRequestCtxWithBody 构造带自定义请求体的模拟上下文。 -// -// 参数: -// - method: HTTP 方法 -// - path: 请求路径 -// - body: 请求体内容 -// -// 返回值: -// - *fasthttp.RequestCtx: 模拟的请求上下文 -func (bc *BenchmarkContext) MockRequestCtxWithBody(method, path string, body []byte) *fasthttp.RequestCtx { - ctx := bc.MockRequestCtx(method, path) - ctx.Request.SetBody(body) - return ctx -} - -// MockRequestCtxWithIP 构造带指定 IP 的模拟上下文。 -// -// 参数: -// - method: HTTP 方法 -// - path: 请求路径 -// - ip: 客户端 IP 地址 -// -// 返回值: -// - *fasthttp.RequestCtx: 模拟的请求上下文 -func (bc *BenchmarkContext) MockRequestCtxWithIP(method, path, ip string) *fasthttp.RequestCtx { - ctx := &fasthttp.RequestCtx{} - - ctx.Request.Header.SetMethod(method) - ctx.Request.SetRequestURI(path) - - ctx.Init(&fasthttp.Request{}, &net.TCPAddr{ - IP: net.ParseIP(ip), - Port: 12345, - }, nil) - - return ctx -} - -// MockResponse 构造模拟响应数据。 -// -// 根据 ResponseSize 生成响应体。 -// -// 返回值: -// - []byte: 模拟的响应数据 -func (bc *BenchmarkContext) MockResponse() []byte { - return GenerateTestData(bc.ResponseSize) -} - -// MockResponseWithContentType 构造带 Content-Type 的模拟响应。 -// -// 参数: -// - statusCode: HTTP 状态码 -// - contentType: 内容类型 -// -// 返回值: -// - []byte: 模拟的响应数据 -func (bc *BenchmarkContext) MockResponseWithContentType(_, _ string) []byte { - // 返回响应体,调用者负责设置状态码和 Content-Type - return GenerateTestData(bc.ResponseSize) -} - -// RandomIP 生成随机 IP 地址。 -// -// 用于测试多客户端场景。 -// -// 返回值: -// - string: 随机 IP 地址 -func (bc *BenchmarkContext) RandomIP() string { - return "192.168." + strconv.Itoa(bc.randSrc.Intn(256)) + "." + strconv.Itoa(bc.randSrc.Intn(256)) -} - -// RandomPath 生成随机请求路径。 -// -// 参数: -// - prefix: 路径前缀 -// -// 返回值: -// - string: 随机路径 -func (bc *BenchmarkContext) RandomPath(prefix string) string { - return prefix + "/" + strconv.Itoa(bc.randSrc.Intn(10000)) -} - -// MockJSONRequest 构造 JSON 格式的模拟请求。 -// -// 参数: -// - path: 请求路径 -// - data: JSON 数据 -// -// 返回值: -// - *fasthttp.RequestCtx: 模拟的请求上下文 -func (bc *BenchmarkContext) MockJSONRequest(path string, data []byte) *fasthttp.RequestCtx { - ctx := bc.MockRequestCtx("POST", path) - ctx.Request.Header.SetContentType("application/json") - ctx.Request.SetBody(data) - return ctx -} - -// MockFormRequest 构造表单格式的模拟请求。 -// -// 参数: -// - path: 请求路径 -// - form: 表单数据键值对 -// -// 返回值: -// - *fasthttp.RequestCtx: 模拟的请求上下文 -func (bc *BenchmarkContext) MockFormRequest(path string, form map[string]string) *fasthttp.RequestCtx { - ctx := bc.MockRequestCtx("POST", path) - ctx.Request.Header.SetContentType("application/x-www-form-urlencoded") - - // 构造表单数据 - var buf bytes.Buffer - first := true - for key, value := range form { - if !first { - buf.WriteByte('&') - } - buf.WriteString(key) - buf.WriteByte('=') - buf.WriteString(value) - first = false - } - ctx.Request.SetBody(buf.Bytes()) - - return ctx -} - -// SetResponse 设置模拟上下文的响应。 -// -// 用于测试响应处理逻辑。 -// -// 参数: -// - ctx: 请求上下文 -// - statusCode: HTTP 状态码 -// - body: 响应体 -func (bc *BenchmarkContext) SetResponse(ctx *fasthttp.RequestCtx, statusCode int, body []byte) { - ctx.Response.SetStatusCode(statusCode) - ctx.Response.SetBody(body) -} - -// SetJSONResponse 设置 JSON 格式的模拟响应。 -// -// 参数: -// - ctx: 请求上下文 -// - statusCode: HTTP 状态码 -// - json: JSON 数据 -func (bc *BenchmarkContext) SetJSONResponse(ctx *fasthttp.RequestCtx, statusCode int, json []byte) { - ctx.Response.SetStatusCode(statusCode) - ctx.Response.Header.SetContentType("application/json") - ctx.Response.SetBody(json) -} - -// DefaultBenchmarkContext 返回默认的基准测试上下文。 -// -// 配置: -// - RequestSize: 1KB -// - ResponseSize: 1KB -// - Concurrency: 1 -// -// 返回值: -// - *BenchmarkContext: 默认配置的上下文 -func DefaultBenchmarkContext() *BenchmarkContext { - return NewBenchmarkContext(Size1KB, Size1KB, 1) -} - -// SmallRequestContext 返回小请求的基准测试上下文。 -// -// 配置: -// - RequestSize: 100B -// - ResponseSize: 100B -// -// 返回值: -// - *BenchmarkContext: 小请求配置的上下文 -func SmallRequestContext() *BenchmarkContext { - return NewBenchmarkContext(100, 100, 1) -} - -// LargeRequestContext 返回大请求的基准测试上下文。 -// -// 配置: -// - RequestSize: 100KB -// - ResponseSize: 100KB -// -// 返回值: -// - *BenchmarkContext: 大请求配置的上下文 -func LargeRequestContext() *BenchmarkContext { - return NewBenchmarkContext(Size100KB, Size100KB, 1) -} - -// HighConcurrencyContext 返回高并发基准测试上下文。 -// -// 配置: -// - Concurrency: 100 -// -// 返回值: -// - *BenchmarkContext: 高并发配置的上下文 -func HighConcurrencyContext() *BenchmarkContext { - return NewBenchmarkContext(Size1KB, Size1KB, 100) -} - -// BenchmarkContextPool 提供基准测试上下文的池。 -// -// 用于减少内存分配开销。 -type BenchmarkContextPool struct { - pool chan *BenchmarkContext -} - -// NewBenchmarkContextPool 创建基准测试上下文池。 -// -// 参数: -// - size: 池大小 -// -// 返回值: -// - *BenchmarkContextPool: 上下文池 -func NewBenchmarkContextPool(size int) *BenchmarkContextPool { - p := &BenchmarkContextPool{ - pool: make(chan *BenchmarkContext, size), - } - // 预填充池 - for range size { - p.pool <- DefaultBenchmarkContext() - } - return p -} - -// Get 从池中获取基准测试上下文。 -// -// 返回值: -// - *BenchmarkContext: 基准测试上下文 -func (p *BenchmarkContextPool) Get() *BenchmarkContext { - select { - case ctx := <-p.pool: - return ctx - default: - return DefaultBenchmarkContext() - } -} - -// Put 将基准测试上下文放回池中。 -// -// 参数: -// - ctx: 基准测试上下文 -func (p *BenchmarkContextPool) Put(ctx *BenchmarkContext) { - select { - case p.pool <- ctx: - default: - // 池已满,丢弃 - } -} diff --git a/internal/benchmark/tools/loadgen.go b/internal/benchmark/tools/loadgen.go deleted file mode 100644 index 424f87b..0000000 --- a/internal/benchmark/tools/loadgen.go +++ /dev/null @@ -1,160 +0,0 @@ -// Package tools provides testing utilities and mock infrastructure for benchmark tests. -package tools - -import ( - "math" - "slices" - "sync" - "testing" - "time" - - "github.com/valyala/fasthttp" -) - -// FasthttpLoadGenerator is a load generator using fasthttp client. -type FasthttpLoadGenerator struct { - client *fasthttp.HostClient - addr string - stats LoadGenStats - mu sync.Mutex -} - -// LoadGenStats contains load generator statistics. -type LoadGenStats struct { - Latencies []time.Duration // For percentile calculation - TotalRequests int - SuccessCount int - ErrorCount int - TotalDuration time.Duration - MinLatency time.Duration - MaxLatency time.Duration - MeanLatency time.Duration - P50Latency time.Duration - P90Latency time.Duration - P99Latency time.Duration - QPS float64 -} - -// NewFasthttpLoadGenerator creates a new load generator for the given address. -func NewFasthttpLoadGenerator(addr string) *FasthttpLoadGenerator { - return &FasthttpLoadGenerator{ - client: &fasthttp.HostClient{ - Addr: addr, - MaxConns: 1000, - }, - addr: addr, - stats: LoadGenStats{ - MinLatency: time.Duration(math.MaxInt64), - }, - } -} - -// Run executes a load test with n requests using the specified concurrency. -// Returns collected statistics. -func (lg *FasthttpLoadGenerator) Run(n int, concurrency int) *LoadGenStats { - var wg sync.WaitGroup - requestsPerWorker := n / concurrency - - // Channels for collecting metrics - latencyChan := make(chan time.Duration, n) - errorChan := make(chan error, n) - - start := time.Now() - - for range concurrency { - wg.Go(func() { - req := fasthttp.AcquireRequest() - resp := fasthttp.AcquireResponse() - defer fasthttp.ReleaseRequest(req) - defer fasthttp.ReleaseResponse(resp) - - for range requestsPerWorker { - req.SetRequestURI("http://" + lg.addr + "/") - req.Header.SetMethod("GET") - - reqStart := time.Now() - err := lg.client.Do(req, resp) - latency := time.Since(reqStart) - - latencyChan <- latency - if err != nil { - errorChan <- err - } - } - }) - } - - wg.Wait() - close(latencyChan) - close(errorChan) - - totalDuration := time.Since(start) - - // Collect latencies - latencies := make([]time.Duration, 0, n) - for lat := range latencyChan { - latencies = append(latencies, lat) - } - - // Count errors - errorCount := 0 - for err := range errorChan { - _ = err // Error recorded, used for counting - errorCount++ - } - - // Calculate statistics - lg.mu.Lock() - defer lg.mu.Unlock() - - lg.stats.TotalRequests = n - lg.stats.ErrorCount = errorCount - lg.stats.SuccessCount = n - errorCount - lg.stats.TotalDuration = totalDuration - lg.stats.QPS = float64(n) / totalDuration.Seconds() - lg.stats.Latencies = latencies - - // Calculate latency distribution - if len(latencies) > 0 { - slices.Sort(latencies) - - lg.stats.MinLatency = latencies[0] - lg.stats.MaxLatency = latencies[len(latencies)-1] - - // Calculate mean - var sum time.Duration - for _, l := range latencies { - sum += l - } - lg.stats.MeanLatency = sum / time.Duration(len(latencies)) - - // Calculate percentiles - lg.stats.P50Latency = latencies[len(latencies)*50/100] - lg.stats.P90Latency = latencies[len(latencies)*90/100] - lg.stats.P99Latency = latencies[len(latencies)*99/100] - } - - return &lg.stats -} - -// GetStats returns current statistics without running a test. -func (lg *FasthttpLoadGenerator) GetStats() *LoadGenStats { - lg.mu.Lock() - defer lg.mu.Unlock() - return &lg.stats -} - -// RunParallel runs requests in parallel using testing.PB. -// This is designed for use with Go benchmark functions. -func (lg *FasthttpLoadGenerator) RunParallel(pb *testing.PB) { - req := fasthttp.AcquireRequest() - resp := fasthttp.AcquireResponse() - defer fasthttp.ReleaseRequest(req) - defer fasthttp.ReleaseResponse(resp) - - for pb.Next() { - req.SetRequestURI("http://" + lg.addr + "/") - req.Header.SetMethod("GET") - _ = lg.client.Do(req, resp) - } -} diff --git a/internal/benchmark/tools/mock_backend.go b/internal/benchmark/tools/mock_backend.go deleted file mode 100644 index d4035c7..0000000 --- a/internal/benchmark/tools/mock_backend.go +++ /dev/null @@ -1,151 +0,0 @@ -// Package tools provides testing utilities and mock infrastructure for benchmark tests. -package tools - -import ( - "math/rand" - "sync" - "time" - - "github.com/valyala/fasthttp" - "github.com/valyala/fasthttp/fasthttputil" -) - -// BackendMode defines the response behavior of the mock backend. -type BackendMode int - -const ( - // ModeFixed returns a fixed response with configurable status and body. - ModeFixed BackendMode = iota - // ModeDelay adds artificial delay before responding. - ModeDelay - // ModeError returns errors for a percentage of requests. - ModeError - // ModeRandomResponse returns random status codes. - ModeRandomResponse -) - -// MockBackendConfig configures the mock backend behavior. -type MockBackendConfig struct { - Body []byte - Mode BackendMode - StatusCode int - Delay time.Duration - ErrorRate float64 // 0.0 to 1.0, for ModeError -} - -// MockBackend represents a mock fasthttp server for testing. -type MockBackend struct { - server *fasthttp.Server - config MockBackendConfig - mu sync.RWMutex -} - -// StartMockFasthttpBackend starts a mock fasthttp backend server. -// Returns the server address and a cleanup function. -func StartMockFasthttpBackend(config MockBackendConfig) (string, func()) { - mb := &MockBackend{ - config: config, - } - - mb.server = &fasthttp.Server{ - Handler: mb.handler, - } - - // Use in-memory listener for testing - ln := fasthttputil.NewInmemoryListener() - - // Start server in background - go func() { - _ = mb.server.Serve(ln) - }() - - addr := "127.0.0.1:0" // In-memory listener address - - cleanup := func() { - _ = mb.server.Shutdown() - _ = ln.Close() - } - - return addr, cleanup -} - -// handler processes incoming requests based on the configured mode. -func (mb *MockBackend) handler(ctx *fasthttp.RequestCtx) { - mb.mu.RLock() - config := mb.config - mb.mu.RUnlock() - - switch config.Mode { - case ModeFixed: - ctx.SetStatusCode(config.StatusCode) - _, _ = ctx.Write(config.Body) - - case ModeDelay: - time.Sleep(config.Delay) - ctx.SetStatusCode(config.StatusCode) - _, _ = ctx.Write(config.Body) - - case ModeError: - if rand.Float64() < config.ErrorRate { - ctx.SetStatusCode(fasthttp.StatusInternalServerError) - _, _ = ctx.WriteString("internal server error") - return - } - ctx.SetStatusCode(config.StatusCode) - _, _ = ctx.Write(config.Body) - - case ModeRandomResponse: - codes := []int{ - fasthttp.StatusOK, - fasthttp.StatusCreated, - fasthttp.StatusNoContent, - fasthttp.StatusBadRequest, - fasthttp.StatusNotFound, - } - ctx.SetStatusCode(codes[rand.Intn(len(codes))]) - _, _ = ctx.Write(config.Body) - - default: // ModeFixed - ctx.SetStatusCode(config.StatusCode) - _, _ = ctx.Write(config.Body) - } -} - -// SetConfig updates the backend configuration at runtime. -func (mb *MockBackend) SetConfig(config MockBackendConfig) { - mb.mu.Lock() - defer mb.mu.Unlock() - mb.config = config -} - -// SimpleMockBackend creates a simple backend with fixed response. -// Returns address and cleanup function. -func SimpleMockBackend(statusCode int, body []byte) (string, func()) { - return StartMockFasthttpBackend(MockBackendConfig{ - Mode: ModeFixed, - StatusCode: statusCode, - Body: body, - }) -} - -// DelayedMockBackend creates a backend with delayed responses. -// Returns address and cleanup function. -func DelayedMockBackend(delay time.Duration, body []byte) (string, func()) { - return StartMockFasthttpBackend(MockBackendConfig{ - Mode: ModeDelay, - StatusCode: fasthttp.StatusOK, - Body: body, - Delay: delay, - }) -} - -// ErrorMockBackend creates a backend that returns errors at the specified rate. -// Returns address and cleanup function. -func ErrorMockBackend(errorRate float64, body []byte) (string, func()) { - return StartMockFasthttpBackend(MockBackendConfig{ - Mode: ModeError, - StatusCode: fasthttp.StatusOK, - Body: body, - ErrorRate: errorRate, - }) -} diff --git a/internal/benchmark/tools/testdata.go b/internal/benchmark/tools/testdata.go deleted file mode 100644 index 37af25b..0000000 --- a/internal/benchmark/tools/testdata.go +++ /dev/null @@ -1,182 +0,0 @@ -// Package tools provides testing utilities and mock infrastructure for benchmark tests. -package tools - -import ( - "fmt" - "math/rand" - "time" -) - -// TestDataSize represents predefined test data sizes. -type TestDataSize int - -const ( - // Size1KB represents 1KB test data. - Size1KB TestDataSize = 1024 - // Size10KB represents 10KB test data. - Size10KB TestDataSize = 10 * 1024 - // Size100KB represents 100KB test data. - Size100KB TestDataSize = 100 * 1024 - // Size1MB represents 1MB test data. - Size1MB TestDataSize = 1024 * 1024 - // Size10MB represents 10MB test data. - Size10MB TestDataSize = 10 * 1024 * 1024 -) - -// GenerateTestData generates test data of the specified size. -func GenerateTestData(size TestDataSize) []byte { - data := make([]byte, size) - // Fill with random data for compression testing - for i := range data { - data[i] = byte(rand.Intn(256)) - } - return data -} - -// GenerateTestDataString generates test data as string. -func GenerateTestDataString(size TestDataSize) string { - return string(GenerateTestData(size)) -} - -// TestTarget represents a backend target for testing. -type TestTarget struct { - Address string - Weight int -} - -// createTestTargets creates n test backend targets with mock servers. -// Returns the target configurations and a cleanup function. -func createTestTargets(n int) ([]TestTarget, func()) { - targets := make([]TestTarget, n) - cleanups := make([]func(), n) - - for i := range n { - body := GenerateTestData(Size1KB) - addr, cleanup := SimpleMockBackend(200, body) - targets[i] = TestTarget{ - Address: addr, - Weight: 1, - } - cleanups[i] = cleanup - } - - cleanupAll := func() { - for _, cleanup := range cleanups { - if cleanup != nil { - cleanup() - } - } - } - - return targets, cleanupAll -} - -// CreateTestTargets creates n test backend targets. -// Returns the target configurations and a cleanup function. -func CreateTestTargets(n int) ([]TestTarget, func()) { - return createTestTargets(n) -} - -// CreateWeightedTestTargets creates n test backend targets with varying weights. -// Returns the target configurations and a cleanup function. -func CreateWeightedTestTargets(n int) ([]TestTarget, func()) { - targets := make([]TestTarget, n) - cleanups := make([]func(), n) - - for i := range n { - body := GenerateTestData(Size1KB) - addr, cleanup := SimpleMockBackend(200, body) - // Vary weights: 1, 2, 3, etc. - targets[i] = TestTarget{ - Address: addr, - Weight: i + 1, - } - cleanups[i] = cleanup - } - - cleanupAll := func() { - for _, cleanup := range cleanups { - if cleanup != nil { - cleanup() - } - } - } - - return targets, cleanupAll -} - -// CreateDelayedTestTargets creates n test backend targets with varying delays. -// Useful for testing timeout and latency-related behavior. -func CreateDelayedTestTargets(n int, baseDelay time.Duration) ([]TestTarget, func()) { - targets := make([]TestTarget, n) - cleanups := make([]func(), n) - - for i := range n { - body := GenerateTestData(Size1KB) - // Each target has increasing delay - delay := baseDelay * time.Duration(i+1) - addr, cleanup := DelayedMockBackend(delay, body) - targets[i] = TestTarget{ - Address: addr, - Weight: 1, - } - cleanups[i] = cleanup - } - - cleanupAll := func() { - for _, cleanup := range cleanups { - if cleanup != nil { - cleanup() - } - } - } - - return targets, cleanupAll -} - -// CreateErrorTestTargets creates n test backend targets with varying error rates. -// Useful for testing error handling and circuit breaker behavior. -func CreateErrorTestTargets(n int, baseErrorRate float64) ([]TestTarget, func()) { - targets := make([]TestTarget, n) - cleanups := make([]func(), n) - - for i := range n { - body := GenerateTestData(Size1KB) - // Vary error rates slightly per target - errorRate := baseErrorRate + float64(i)*0.05 - if errorRate > 1.0 { - errorRate = 1.0 - } - addr, cleanup := ErrorMockBackend(errorRate, body) - targets[i] = TestTarget{ - Address: addr, - Weight: 1, - } - cleanups[i] = cleanup - } - - cleanupAll := func() { - for _, cleanup := range cleanups { - if cleanup != nil { - cleanup() - } - } - } - - return targets, cleanupAll -} - -// GenerateCacheKey generates a unique cache key for testing. -func GenerateCacheKey(prefix string, index int) string { - return fmt.Sprintf("%s-key-%d", prefix, index) -} - -// GenerateCacheValue generates a cache value of specified size. -func GenerateCacheValue(size TestDataSize) []byte { - return GenerateTestData(size) -} - -// GenerateRandomCacheKey generates a random cache key. -func GenerateRandomCacheKey() string { - return fmt.Sprintf("random-key-%d-%d", time.Now().UnixNano(), rand.Int()) -} diff --git a/internal/config/defaults.go b/internal/config/defaults.go index 290b29f..b4f4bce 100644 --- a/internal/config/defaults.go +++ b/internal/config/defaults.go @@ -69,8 +69,8 @@ func DefaultConfig() *Config { CodeCacheSize: 1000, EnableFileWatch: true, MaxExecutionTime: 30 * time.Second, - LStatePoolInitialSize: 100, - LStatePoolMaxSize: 1000, + LStatePoolInitialSize: 100, + LStatePoolMaxSize: 1000, }, }, Static: []StaticConfig{{ diff --git a/internal/loadbalance/algorithms.go b/internal/loadbalance/algorithms.go index ad073f8..e3fbbc8 100644 --- a/internal/loadbalance/algorithms.go +++ b/internal/loadbalance/algorithms.go @@ -1,7 +1,6 @@ // Package loadbalance 提供负载均衡算法实现。 // // 该文件包含负载均衡算法相关的辅助逻辑,包括: -// - ValidAlgorithms 有效算法列表定义 // - IsValidAlgorithm 算法有效性校验函数 // // 主要用途: @@ -9,7 +8,7 @@ // 用于校验和枚举系统支持的负载均衡算法类型,供配置解析和路由选择使用。 // // 注意事项: -// - 新增算法时必须同步更新 ValidAlgorithms 列表 +// - 新增算法时必须同步更新 validAlgorithms 列表 // - 空字符串被视为有效值,表示使用默认算法 // // 作者:xfy @@ -17,15 +16,8 @@ package loadbalance import "slices" -// ValidAlgorithms 定义系统支持的负载均衡算法名称列表。 -// -// 该列表用于配置校验,包含以下算法: -// - round_robin: 简单轮询,按顺序均匀分配请求 -// - weighted_round_robin: 加权轮询,按权重比例分配请求 -// - least_conn: 最少连接,选择活跃连接数最少的目标 -// - ip_hash: IP 哈希,基于客户端 IP 实现会话保持 -// - consistent_hash: 一致性哈希,使用虚拟节点实现均匀分布 -var ValidAlgorithms = []string{ +// validAlgorithms 定义系统支持的负载均衡算法名称列表。 +var validAlgorithms = []string{ "round_robin", "weighted_round_robin", "least_conn", @@ -43,11 +35,11 @@ var ValidAlgorithms = []string{ // - alg: 算法名称字符串,如 "round_robin"、"least_conn" 等 // // 返回值: -// - true: 算法有效(在 ValidAlgorithms 列表中或为空字符串) -// - false: 算法无效(不在 ValidAlgorithms 列表中且非空) +// - true: 算法有效(在 validAlgorithms 列表中或为空字符串) +// - false: 算法无效(不在 validAlgorithms 列表中且非空) func IsValidAlgorithm(alg string) bool { if alg == "" { return true } - return slices.Contains(ValidAlgorithms, alg) + return slices.Contains(validAlgorithms, alg) } diff --git a/internal/lua/api_socket_tcp.go b/internal/lua/api_socket_tcp.go index fc8a749..fa77071 100644 --- a/internal/lua/api_socket_tcp.go +++ b/internal/lua/api_socket_tcp.go @@ -869,7 +869,6 @@ func (c *LuaCoroutine) handleCosocketConnect(values []glua.LValue) ([]glua.LValu return []glua.LValue{glua.LNil, glua.LNil}, nil } - _ = result // 连接成功,返回 1 return []glua.LValue{glua.LNumber(1)}, nil } diff --git a/internal/lua/config.go b/internal/lua/config.go index 5ab60a5..1e353f9 100644 --- a/internal/lua/config.go +++ b/internal/lua/config.go @@ -87,8 +87,8 @@ func DefaultConfig() *Config { EnableLoadLib: false, CoroutineStackSize: 64, // 优化:较小的栈减少内存分配 MinimizeStackMemory: true, - CoroutinePoolWarmup: 4, // 预热4个协程结构 - LStatePoolInitialSize: 100, // LState 池预热 100 个 + CoroutinePoolWarmup: 4, // 预热4个协程结构 + LStatePoolInitialSize: 100, // LState 池预热 100 个 LStatePoolMaxSize: 1000, // LState 池最大 1000 个(与 MaxConcurrentCoroutines 匹配) } } diff --git a/internal/lua/engine.go b/internal/lua/engine.go index b704fd1..6bb5319 100644 --- a/internal/lua/engine.go +++ b/internal/lua/engine.go @@ -151,11 +151,11 @@ func NewEngine(config *Config) (*LuaEngine, error) { ctx, cancel := context.WithCancel(context.Background()) engine := &LuaEngine{ - config: config, - codeCache: NewCodeCache(config.CodeCacheSize, config.CodeCacheTTL, config.EnableFileWatch), - maxCoroutines: config.MaxConcurrentCoroutines, - ctx: ctx, - cancel: cancel, + config: config, + codeCache: NewCodeCache(config.CodeCacheSize, config.CodeCacheTTL, config.EnableFileWatch), + maxCoroutines: config.MaxConcurrentCoroutines, + ctx: ctx, + cancel: cancel, sharedDictManager: NewSharedDictManager(), coroutinePool: sync.Pool{ New: func() any { diff --git a/internal/lua/pool.go b/internal/lua/pool.go index 4b10f0b..fa89484 100644 --- a/internal/lua/pool.go +++ b/internal/lua/pool.go @@ -149,4 +149,4 @@ func (p *LStatePool) Available() int { p.mu.Lock() defer p.mu.Unlock() return len(p.pool) -} \ No newline at end of file +} diff --git a/internal/lua/route_handler.go b/internal/lua/route_handler.go index 27990b3..b5c0633 100644 --- a/internal/lua/route_handler.go +++ b/internal/lua/route_handler.go @@ -93,4 +93,4 @@ func (h *LuaRouteHandler) ServeHTTP(ctx *fasthttp.RequestCtx) { luaCtx.FlushOutput() luaCtx.Release() -} \ No newline at end of file +} diff --git a/internal/matcher/conflict.go b/internal/matcher/conflict.go index 3b7aefd..2278d67 100644 --- a/internal/matcher/conflict.go +++ b/internal/matcher/conflict.go @@ -5,9 +5,10 @@ // 作者:xfy package matcher -import "maps" - -import "fmt" +import ( + "fmt" + "maps" +) // ConflictDetector 路径冲突检测器。 // diff --git a/internal/middleware/middleware.go b/internal/middleware/middleware.go index f3eb4e3..f0fbee6 100644 --- a/internal/middleware/middleware.go +++ b/internal/middleware/middleware.go @@ -15,9 +15,11 @@ // 作者:xfy package middleware -import "slices" +import ( + "slices" -import "github.com/valyala/fasthttp" + "github.com/valyala/fasthttp" +) // Middleware 中间件接口,定义中间件的标准方法。 // diff --git a/internal/server/init.go b/internal/server/init.go index b65645a..34cbb8b 100644 --- a/internal/server/init.go +++ b/internal/server/init.go @@ -111,8 +111,8 @@ func initLuaEngine(luaCfg *config.LuaMiddlewareConfig) (*lua.LuaEngine, error) { EnableOSLib: false, // 安全默认值 EnableIOLib: false, EnableLoadLib: false, - LStatePoolInitialSize: luaCfg.GlobalSettings.LStatePoolInitialSize, - LStatePoolMaxSize: luaCfg.GlobalSettings.LStatePoolMaxSize, + LStatePoolInitialSize: luaCfg.GlobalSettings.LStatePoolInitialSize, + LStatePoolMaxSize: luaCfg.GlobalSettings.LStatePoolMaxSize, } // 设置协程栈优化选项