Skip to content

Commit 40517f5

Browse files
peerless1024evelynwei
andauthored
feat/default-instance-circuitbreaker (#256)
* feat: support default instance circuit breaker --------- Co-authored-by: evelynwei <[email protected]>
1 parent 6937fb0 commit 40517f5

File tree

19 files changed

+589
-36
lines changed

19 files changed

+589
-36
lines changed

examples/README.md

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@
1919

2020
## 🛠️ 管理脚本
2121

22-
本目录还提供了三个便捷的管理脚本,用于批量管理所有示例模块:
22+
本目录还提供了四个便捷的管理脚本,用于批量管理所有示例模块:
2323

2424
### 脚本功能对比
2525

2626
| 脚本名称 | 主要功能 | 使用场景 | 执行效果 |
27-
|---------|---------|---------|---------|
28-
| **check_versions.sh** | 版本一致性检查 | 检查所有模块的依赖版本是否一致 | 显示版本分布统计,识别版本不一致问题 |
27+
|---------|---------|---------|---------| | **check_versions.sh** | 版本一致性检查 | 检查所有模块的依赖版本是否一致 | 显示版本分布统计,识别版本不一致问题 |
2928
| **update_polaris_versions.sh** | 批量版本更新 | 统一更新所有模块的polaris-go和Go版本 | 更新require依赖版本,忽略replace指令 |
3029
| **batch_mod_tidy.sh** | 批量依赖整理 | 清理和整理所有模块的依赖关系 | 执行go mod tidy,统计成功/失败数量 |
30+
| **batch_make_clean.sh** | 批量清理构建 | 清理所有子目录的构建产物 | 递归执行make clean,统计成功/失败数量 |
3131

3232
### 详细使用说明
3333

@@ -109,6 +109,31 @@ chmod +x batch_mod_tidy.sh
109109
- 成功/失败统计
110110
- 详细的使用说明
111111

112+
#### 4. batch_make_clean.sh - 批量清理构建脚本
113+
114+
**功能**:批量执行 `make clean` 清理所有子目录的构建产物
115+
116+
**使用方法**
117+
```bash
118+
# 给脚本执行权限
119+
chmod +x batch_make_clean.sh
120+
121+
# 执行批量清理
122+
./batch_make_clean.sh
123+
```
124+
125+
**执行特点**
126+
- 🚀 自动发现所有包含Makefile的子目录
127+
- 📁 跳过根目录的Makefile文件
128+
- 🧹 递归执行make clean清理构建产物
129+
- ✅/❌ 实时显示每个模块的执行状态
130+
- 📊 提供执行结果统计
131+
132+
**输出信息**
133+
- 处理进度和状态
134+
- 成功/失败统计
135+
- 详细的使用说明
136+
112137
## 🚀 快速开始
113138

114139
1. **选择示例**:根据需要的功能选择对应的示例目录
@@ -122,6 +147,7 @@ chmod +x batch_mod_tidy.sh
122147
- 建议先运行 `check_versions.sh` 检查版本一致性
123148
- 如需更新版本,请使用 `update_polaris_versions.sh` 统一更新
124149
- 定期使用 `batch_mod_tidy.sh` 整理依赖关系
150+
- 使用 `batch_make_clean.sh` 可以快速清理所有子目录的构建产物
125151

126152
## 🔗 相关链接
127153

examples/batch_make_clean.sh

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#!/bin/bash
2+
3+
# 批量执行 make clean 脚本
4+
# 用于递归清理所有包含 Makefile 的子目录
5+
6+
set -e # 遇到错误立即退出
7+
8+
echo "🚀 开始批量执行 make clean..."
9+
10+
# 计数器
11+
success_count=0
12+
fail_count=0
13+
total_count=0
14+
15+
# 查找所有包含 Makefile 或 makefile 的目录
16+
find . \( -name "Makefile" -o -name "makefile" \) -type f | while read -r makefile; do
17+
# 获取目录路径
18+
dir=$(dirname "$makefile")
19+
20+
# 跳过根目录的 Makefile(如果存在)
21+
if [ "$dir" = "." ]; then
22+
continue
23+
fi
24+
25+
total_count=$((total_count + 1))
26+
27+
echo "📁 处理目录: $dir"
28+
29+
# 进入目录并执行 make clean
30+
if cd "$dir"; then
31+
echo " 🧹 执行: make clean"
32+
33+
if make clean 2>&1; then
34+
echo " ✅ 成功: $dir"
35+
success_count=$((success_count + 1))
36+
else
37+
echo " ❌ 失败: $dir"
38+
fail_count=$((fail_count + 1))
39+
fi
40+
41+
# 返回上级目录
42+
cd - > /dev/null
43+
else
44+
echo " ❌ 无法进入目录: $dir"
45+
fail_count=$((fail_count + 1))
46+
fi
47+
48+
echo "---"
49+
done
50+
51+
echo "📊 执行结果统计:"
52+
echo " 总模块数: $total_count"
53+
echo " 成功数: $success_count"
54+
echo " 失败数: $fail_count"
55+
56+
if [ $fail_count -eq 0 ]; then
57+
echo "🎉 所有模块的 make clean 执行成功!"
58+
else
59+
echo "⚠️ 有 $fail_count 个模块执行失败,请检查相关目录"
60+
fi
61+
62+
# 可选:显示使用说明
63+
echo ""
64+
echo "💡 使用说明:"
65+
echo " 1. 给脚本执行权限: chmod +x batch_make_clean.sh"
66+
echo " 2. 运行脚本: ./batch_make_clean.sh"
67+
echo " 3. 脚本会自动跳过根目录的 Makefile 文件(如果存在)"
68+
echo " 4. 每个模块执行完成后会显示状态"

examples/circuitbreaker/instance/consumer/main.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
"time"
3434

3535
"github.com/polarismesh/polaris-go"
36+
"github.com/polarismesh/polaris-go/api"
3637
"github.com/polarismesh/polaris-go/pkg/config"
3738
"github.com/polarismesh/polaris-go/pkg/model"
3839
)
@@ -46,6 +47,7 @@ var (
4647
port int
4748
token string
4849
configPath string
50+
debug bool
4951
)
5052

5153
func initArgs() {
@@ -57,6 +59,7 @@ func initArgs() {
5759
flag.IntVar(&port, "port", 18080, "port")
5860
flag.StringVar(&token, "token", "", "token")
5961
flag.StringVar(&configPath, "config", "./polaris.yaml", "path for config file")
62+
flag.BoolVar(&debug, "debug", false, "debug")
6063
}
6164

6265
// PolarisClient is a consumer of the circuit breaker calleeService.
@@ -69,6 +72,26 @@ type PolarisClient struct {
6972
webSvr *http.Server
7073
}
7174

75+
// reportServiceCallResult 上报服务调用结果的辅助方法
76+
func (svr *PolarisClient) reportServiceCallResult(instance model.Instance, retStatus model.RetStatus, statusCode int, delay time.Duration) {
77+
ret := &polaris.ServiceCallResult{
78+
ServiceCallResult: model.ServiceCallResult{
79+
EmptyInstanceGauge: model.EmptyInstanceGauge{},
80+
CalledInstance: instance,
81+
Method: "/echo",
82+
RetStatus: retStatus,
83+
},
84+
}
85+
ret.SetDelay(delay)
86+
ret.SetRetCode(int32(statusCode))
87+
if err := svr.consumer.UpdateServiceCallResult(ret); err != nil {
88+
log.Printf("do report service call result : %+v", err)
89+
} else {
90+
log.Printf("report service call result success: instance=%s:%d, status=%v, retCode=%d, delay=%v",
91+
instance.GetHost(), instance.GetPort(), ret.RetStatus, ret.GetRetCode(), delay)
92+
}
93+
}
94+
7295
func (svr *PolarisClient) discoverInstance() (model.Instance, error) {
7396
svr.printAllInstances()
7497
getOneRequest := &polaris.GetOneInstanceRequest{}
@@ -111,6 +134,11 @@ func (svr *PolarisClient) runWebServer() {
111134
instance.GetHost(), instance.GetPort(), err)))
112135

113136
time.Sleep(time.Millisecond * time.Duration(rand.Intn(10)))
137+
138+
// 上报服务调用结果
139+
delay := time.Since(start)
140+
svr.reportServiceCallResult(instance, model.RetFail, http.StatusInternalServerError, delay)
141+
114142
// 上报熔断结果,用于熔断计算
115143
svr.reportCircuitBreak(instance, model.RetFail, strconv.Itoa(http.StatusInternalServerError), start)
116144
return
@@ -119,6 +147,16 @@ func (svr *PolarisClient) runWebServer() {
119147

120148
defer resp.Body.Close()
121149

150+
// 上报服务调用结果
151+
delay := time.Since(start)
152+
retStatus := model.RetSuccess
153+
if resp.StatusCode == http.StatusTooManyRequests {
154+
retStatus = model.RetFlowControl
155+
} else if resp.StatusCode != http.StatusOK {
156+
retStatus = model.RetFail
157+
}
158+
svr.reportServiceCallResult(instance, retStatus, resp.StatusCode, delay)
159+
122160
// 上报熔断结果,用于熔断计算
123161
if resp.StatusCode != http.StatusOK {
124162
svr.reportCircuitBreak(instance, model.RetFail,
@@ -271,6 +309,14 @@ func main() {
271309
log.Print("calleeNamespace and calleeService are required")
272310
return
273311
}
312+
if debug {
313+
// 设置日志级别为DEBUG
314+
if err := api.SetLoggersLevel(api.DebugLog); err != nil {
315+
log.Printf("fail to set log level to DEBUG, err is %v", err)
316+
} else {
317+
log.Printf("successfully set log level to DEBUG")
318+
}
319+
}
274320
cfg, err := config.LoadConfigurationByFile(configPath)
275321
if err != nil {
276322
log.Fatalf("load configuration by file %s failed: %v", configPath, err)

examples/circuitbreaker/instance/consumer/polaris.yaml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,45 @@ global:
1212
type: push
1313
address: ${POLARIS_SERVER}:9091
1414
interval: 10s
15+
#描述:主调端配置
16+
consumer:
17+
#描述:节点熔断相关配置
18+
circuitBreaker:
19+
#描述:是否启用节点熔断功能
20+
#类型:bool
21+
#默认值:true
22+
enable: true
23+
# 描述:是否启用默认熔断规则
24+
#类型:bool
25+
#默认值:true
26+
defaultRuleEnable: true
27+
# 描述:连续错误数熔断器默认连续错误数
28+
#类型:int
29+
#默认值:10
30+
defaultErrorCount: 10
31+
# 描述:错误率熔断器默认错误率
32+
#类型:int
33+
#默认值:50
34+
defaultErrorPercent: 50
35+
# 描述:错误率熔断器默认统计周期
36+
#类型:int64
37+
#默认值:60s
38+
defaultInterval: 60s
39+
# 描述:错误率熔断器默认最小请求数
40+
#类型:int
41+
#默认值:10
42+
defaultMinimumRequest: 10
43+
#描述:熔断周期,被熔断后多久可以变为半开
44+
#类型:duration
45+
#默认值:30s
46+
sleepWindow: 30s
47+
#描述:半开状态后多少个成功请求则恢复
48+
#类型:int
49+
#默认值:3
50+
successCountAfterHalfOpen: 3
51+
#描述:熔断策略,SDK会根据策略名称加载对应的熔断器插件
52+
#类型:list
53+
#范围:已注册的熔断器插件名
54+
#默认值:composite 适配服务/接口/实例 熔断插件
55+
chain:
56+
- composite

examples/quickstart/consumer/main.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,14 @@ import (
3737
var (
3838
namespace string
3939
service string
40+
hashkey string
4041
port int64
4142
)
4243

4344
func initArgs() {
4445
flag.StringVar(&namespace, "namespace", "default", "namespace")
4546
flag.StringVar(&service, "service", "DiscoverEchoServer", "service")
47+
flag.StringVar(&hashkey, "hashkey", "", "")
4648
flag.Int64Var(&port, "port", 18080, "port")
4749
}
4850

@@ -106,6 +108,7 @@ func (svr *PolarisConsumer) runWebServer() {
106108
getOneRequest := &polaris.GetOneInstanceRequest{}
107109
getOneRequest.Namespace = req.Namespace
108110
getOneRequest.Service = req.Service
111+
getOneRequest.HashKey = []byte(hashkey)
109112
oneInstResp, err := svr.consumer.GetOneInstance(getOneRequest)
110113
if err != nil {
111114
log.Printf("[error] fail to getOneInstance, err is %v", err)

pkg/config/api.go

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -432,16 +432,13 @@ type CircuitBreakerConfig interface {
432432
// SetChain 设置熔断器插件链
433433
SetChain([]string)
434434
// GetCheckPeriod 熔断器定时检测时间
435-
// Deprecated: 不在使用
436435
GetCheckPeriod() time.Duration
437436
// SetCheckPeriod 设置熔断器定时检测时间
438437
// Deprecated: 不在使用
439438
SetCheckPeriod(time.Duration)
440439
// GetSleepWindow 获取熔断周期
441-
// Deprecated: 不在使用
442440
GetSleepWindow() time.Duration
443441
// SetSleepWindow 设置熔断周期
444-
// Deprecated: 不在使用
445442
SetSleepWindow(interval time.Duration)
446443
// GetRequestCountAfterHalfOpen 获取半开状态后最多分配多少个探测请求
447444
// Deprecated: 不在使用
@@ -450,10 +447,8 @@ type CircuitBreakerConfig interface {
450447
// Deprecated: 不在使用
451448
SetRequestCountAfterHalfOpen(count int)
452449
// GetSuccessCountAfterHalfOpen 获取半开状态后多少个成功请求则恢复
453-
// Deprecated: 不在使用
454450
GetSuccessCountAfterHalfOpen() int
455451
// SetSuccessCountAfterHalfOpen 设置半开状态后多少个成功请求则恢复
456-
// Deprecated: 不在使用
457452
SetSuccessCountAfterHalfOpen(count int)
458453
// GetRecoverWindow 获取半开后的恢复周期,按周期来进行半开放量的统计
459454
// Deprecated: 不在使用
@@ -473,6 +468,26 @@ type CircuitBreakerConfig interface {
473468
// GetErrorRateConfig 错误率熔断配置
474469
// Deprecated: 不在使用
475470
GetErrorRateConfig() ErrorRateConfig
471+
// IsDefaultRuleEnable 是否启用默认实例级熔断规则
472+
IsDefaultRuleEnable() bool
473+
// SetDefaultRuleEnable 设置是否启用默认实例级熔断规则
474+
SetDefaultRuleEnable(enable bool)
475+
// GetDefaultErrorCount 获取默认实例级熔断连续错误数阈值
476+
GetDefaultErrorCount() int
477+
// SetDefaultErrorCount 设置默认实例级熔断连续错误数阈值
478+
SetDefaultErrorCount(count int)
479+
// GetDefaultErrorPercent 获取默认实例级熔断错误率阈值(百分比)
480+
GetDefaultErrorPercent() int
481+
// SetDefaultErrorPercent 设置默认实例级熔断错误率阈值(百分比)
482+
SetDefaultErrorPercent(rate int)
483+
// GetDefaultInterval 获取默认实例级熔断统计时间窗口
484+
GetDefaultInterval() time.Duration
485+
// SetDefaultInterval 设置默认实例级熔断统计时间窗口
486+
SetDefaultInterval(interval time.Duration)
487+
// GetDefaultMinimumRequest 获取默认实例级熔断最小请求数阈值
488+
GetDefaultMinimumRequest() int
489+
// SetDefaultMinimumRequest 设置默认实例级熔断最小请求数阈值
490+
SetDefaultMinimumRequest(count int)
476491
}
477492

478493
// Configuration 全量配置对象.

0 commit comments

Comments
 (0)