golang实现故障注入的中间件插件库go-fault的使用
Golang实现故障注入的中间件插件库go-fault的使用
go-fault是一个Golang HTTP中间件库,可以方便地在服务中注入故障。使用该库可以拒绝传入请求、响应HTTP错误、延迟部分请求或注入自定义故障。
主要特性
go-fault通过标准的Go HTTP中间件工作。首先创建一个Injector
(包含要运行的注入代码的中间件),然后用Fault
包装该Injector
,后者控制何时运行Injector
。
目前有三种类型的注入器:
SlowInjector
:注入延迟ErrorInjector
:注入错误RejectInjector
:拒绝请求
示例代码
// main.go
package main
import (
"net/http"
"time"
"github.com/lingrino/go-fault"
)
// 主处理函数
var mainHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.Error(w, http.StatusText(http.StatusOK), http.StatusOK)
})
func main() {
// 创建延迟注入器,延迟2秒
slowInjector, _ := fault.NewSlowInjector(time.Second * 2)
// 创建故障配置:
// - 启用故障注入
// - 25%的请求受影响
// - 排除/ping和/health路径
slowFault, _ := fault.NewFault(slowInjector,
fault.WithEnabled(true),
fault.WithParticipation(0.25),
fault.WithPathBlocklist([]string{"/ping", "/health"}),
)
// 将故障注入器添加到处理链中
handlerChain := slowFault.Handler(mainHandler)
// 启动HTTP服务器
http.ListenAndServe("127.0.0.1:3000", handlerChain)
}
使用说明
- 延迟注入:使用
NewSlowInjector
创建延迟注入器 - 错误注入:使用
NewErrorInjector
创建错误注入器 - 拒绝请求:使用
NewRejectInjector
创建拒绝请求注入器
配置选项:
WithEnabled
:启用/禁用故障注入WithParticipation
:设置受影响请求的百分比WithPathBlocklist
:设置排除路径列表WithPathAllowlist
:设置仅影响指定路径
局限性
该库无法完美模拟请求被丢弃的场景(请求无响应的情况)。建议使用长时间延迟的SlowInjector
配合RejectInjector
来模拟这种情况。
性能
当故障注入禁用时,性能影响可以忽略不计。启用时会有轻微性能差异,但仅在注入故障时才会出现。
测试
该库有完善的测试覆盖,包括:
$ go test -v -cover -race ./...
[...]
PASS
coverage: 100.0% of statements
ok github.com/lingrino/go-fault 0.575s
基准测试
$ go test -run=XXX -bench=.
goos: darwin
goarch: amd64
pkg: github.com/lingrino/go-fault
BenchmarkNoFault-8 684826 1734 ns/op
BenchmarkFaultDisabled-8 675291 1771 ns/op
BenchmarkFaultErrorZeroPercent-8 667903 1823 ns/op
BenchmarkFaultError100Percent-8 663661 1833 ns/op
PASS
ok github.com/lingrino/go-fault 8.814s
更多关于golang实现故障注入的中间件插件库go-fault的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang实现故障注入的中间件插件库go-fault的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Go-Fault: Golang故障注入中间件库使用指南
go-fault 是一个用于Golang的故障注入中间件库,允许开发者在服务中模拟各种故障场景,如延迟、错误响应等,以测试系统的弹性和容错能力。
安装
go get github.com/lingrino/go-fault
基本使用
1. 注入延迟
package main
import (
"fmt"
"net/http"
"time"
"github.com/lingrino/go-fault"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!")
}
func main() {
// 创建故障注入器 - 50%概率注入500ms延迟
injector := fault.NewFault(
fault.WithProbability(0.5),
fault.WithDelay(time.Millisecond * 500),
)
// 包装原始handler
http.Handle("/", injector.Handler(http.HandlerFunc(handler)))
http.ListenAndServe(":8080", nil)
}
2. 注入错误响应
package main
import (
"net/http"
"github.com/lingrino/go-fault"
)
func handler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Normal response"))
}
func main() {
// 创建故障注入器 - 30%概率返回500错误
injector := fault.NewFault(
fault.WithProbability(0.3),
fault.WithError(http.StatusInternalServerError, []byte("Injected error")),
)
http.Handle("/", injector.Handler(http.HandlerFunc(handler)))
http.ListenAndServe(":8080", nil)
}
高级功能
1. 组合多种故障
injector := fault.NewFault(
fault.WithProbability(0.2),
fault.WithDelay(time.Second),
fault.WithError(http.StatusServiceUnavailable, []byte("Service unavailable")),
fault.WithCallback(func(w http.ResponseWriter, r *http.Request) {
// 自定义回调逻辑
w.Header().Set("X-Fault-Injected", "true")
}),
)
2. 条件触发
injector := fault.NewFault(
fault.WithCondition(func(r *http.Request) bool {
// 只对特定路径注入故障
return r.URL.Path == "/api/v1/payments"
}),
fault.WithError(http.StatusPaymentRequired, []byte("Payment required")),
)
3. 自定义故障逻辑
injector := fault.NewFault(
fault.WithCallback(func(w http.ResponseWriter, r *http.Request) {
// 50%概率返回错误,50%概率注入延迟
if rand.Float32() < 0.5 {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("Custom error"))
} else {
time.Sleep(2 * time.Second)
}
}),
)
实际应用示例
微服务中的故障注入
package main
import (
"log"
"net/http"
"time"
"github.com/lingrino/go-fault"
)
func paymentHandler(w http.ResponseWriter, r *http.Request) {
// 模拟支付处理
time.Sleep(100 * time.Millisecond)
w.Write([]byte("Payment processed"))
}
func main() {
// 为支付服务创建故障注入
paymentInjector := fault.NewFault(
fault.WithProbability(0.1), // 10%故障率
fault.WithError(http.StatusInternalServerError, []byte("Payment service unavailable")),
fault.WithDelay(time.Second * 3), // 3秒延迟
)
mux := http.NewServeMux()
mux.Handle("/pay", paymentInjector.Handler(http.HandlerFunc(paymentHandler)))
log.Println("Server started on :8080")
log.Fatal(http.ListenAndServe(":8080", mux))
}
最佳实践
- 生产环境谨慎使用:确保只在测试环境启用故障注入
- 动态配置:考虑通过环境变量或配置中心控制故障注入参数
- 监控:记录所有注入的故障以便分析
- 渐进式实施:从低故障率开始,逐步增加
替代方案
如果 go-fault 不能满足需求,还可以考虑:
- Chaos Mesh (Kubernetes环境)
- Gremlin (企业级混沌工程平台)
- 自定义中间件实现
go-fault 是一个轻量级的解决方案,特别适合HTTP服务的故障注入测试,能有效帮助开发者验证系统的容错能力。