refactor: remove unused code and fix formatting

- Remove unused benchmark/tools package
- Make ValidAlgorithms private (validAlgorithms) in loadbalance
- Remove dead code (_ = result) in lua/api_socket_tcp.go
- Fix code formatting with goimports

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
xfy 2026-05-09 16:58:45 +08:00
parent ce80352e79
commit 25d93c25fa
16 changed files with 28 additions and 928 deletions

2
go.mod
View File

@ -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

View File

@ -1,42 +0,0 @@
<!-- Parent: ../AGENTS.md -->
<!-- Generated: 2026-04-07 | Updated: 2026-04-07 -->
# 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` - 内存监听器
<!-- MANUAL: -->

View File

@ -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:
// 池已满,丢弃
}
}

View File

@ -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)
}
}

View File

@ -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,
})
}

View File

@ -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())
}

View File

@ -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{{

View File

@ -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)
}

View File

@ -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
}

View File

@ -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 匹配)
}
}

View File

@ -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 {

View File

@ -149,4 +149,4 @@ func (p *LStatePool) Available() int {
p.mu.Lock()
defer p.mu.Unlock()
return len(p.pool)
}
}

View File

@ -93,4 +93,4 @@ func (h *LuaRouteHandler) ServeHTTP(ctx *fasthttp.RequestCtx) {
luaCtx.FlushOutput()
luaCtx.Release()
}
}

View File

@ -5,9 +5,10 @@
// 作者xfy
package matcher
import "maps"
import "fmt"
import (
"fmt"
"maps"
)
// ConflictDetector 路径冲突检测器。
//

View File

@ -15,9 +15,11 @@
// 作者xfy
package middleware
import "slices"
import (
"slices"
import "github.com/valyala/fasthttp"
"github.com/valyala/fasthttp"
)
// Middleware 中间件接口,定义中间件的标准方法。
//

View File

@ -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,
}
// 设置协程栈优化选项