diff --git a/plugins/wasm-go/extensions/frontend-gray/README.md b/plugins/wasm-go/extensions/frontend-gray/README.md
index 3cf64cdab8..6c36b3a2e9 100644
--- a/plugins/wasm-go/extensions/frontend-gray/README.md
+++ b/plugins/wasm-go/extensions/frontend-gray/README.md
@@ -12,7 +12,6 @@
| `baseDeployment` | object | 非必填 | - | 配置Base基线规则的配置 |
| `grayDeployments` | array of object | 非必填 | - | 配置Gray灰度的生效规则,以及生效版本 |
| `backendGrayTag` | string | 非必填 | `x-mse-tag` | 后端灰度版本Tag,如果配置了,cookie中将携带值为`${backendGrayTag}:${grayDeployments[].backendVersion}` |
-| `debugGrayWeight` | boolean | 非必填 | - | 开启按照比例灰度的Debug模式,用于观测按比例灰度效果, |
| `injection` | object | 非必填 | - | 往首页HTML中注入全局信息,比如`` |
@@ -52,7 +51,9 @@
| `backendVersion` | string | 必填 | - | 后端灰度版本,配合`key`为`${backendGrayTag}`,写入cookie中 |
| `name` | string | 必填 | - | 规则名称和`rules[].name`关联, |
| `enabled` | boolean | 必填 | - | 是否启动当前灰度规则 |
-| `weight` | int | 非必填 | - | 按照比例灰度,比如`50`。注意:灰度规则权重总和不能超过100,如果配置了`weight`,则优先生效 |
+| `weight` | int | 非必填 | - | 按照比例灰度,比如`50`。注意:灰度规则权重总和不能超过100,如果同时配置了`grayKey`以及`grayDeployments[0].weight`按照比例灰度优先生效 |
+> 为了实现按比例(weight) 进行灰度发布,并确保用户粘滞,我们需要确认客户端的唯一性。如果配置了 grayKey,则将其用作唯一标识;如果未配置 grayKey,则使用客户端的访问 IP 地址作为唯一标识。
+
`injection`字段配置说明:
@@ -119,7 +120,7 @@ grayDeployments:
enabled: true
weight: 80
```
-总的灰度规则为100%,其中灰度版本的权重为`80%`,基线版本为`20%`。一旦用户命中了灰度规则,会根据IP固定这个用户的灰度版本(否则会在下次请求时随机选择一个灰度版本)。如果需要观测按比例灰度是否生效,使用`debugGrayWeight`开启Debug模式。
+总的灰度规则为100%,其中灰度版本的权重为`80%`,基线版本为`20%`。一旦用户命中了灰度规则,会根据IP固定这个用户的灰度版本(否则会在下次请求时随机选择一个灰度版本)。
### 用户信息存在JSON中
diff --git a/plugins/wasm-go/extensions/frontend-gray/config/config.go b/plugins/wasm-go/extensions/frontend-gray/config/config.go
index 3c0735544e..2be58209e4 100644
--- a/plugins/wasm-go/extensions/frontend-gray/config/config.go
+++ b/plugins/wasm-go/extensions/frontend-gray/config/config.go
@@ -8,7 +8,7 @@ import (
const (
XHigressTag = "x-higress-tag"
- XForwardedFor = "x-forwarded-for"
+ XUniqueClient = "x-unique-client"
XPreHigressTag = "x-pre-higress-tag"
IsIndex = "is-index"
IsNotFound = "is-not-found"
@@ -58,7 +58,6 @@ type GrayConfig struct {
Rewrite *Rewrite
BaseDeployment *Deployment
GrayDeployments []*Deployment
- DebugGrayWeight bool
BackendGrayTag string
Injection *Injection
}
@@ -84,7 +83,6 @@ func JsonToGrayConfig(json gjson.Result, grayConfig *GrayConfig) {
// 解析 GrayKey
grayConfig.GrayKey = json.Get("grayKey").String()
grayConfig.GraySubKey = json.Get("graySubKey").String()
- grayConfig.DebugGrayWeight = json.Get("debugGrayWeight").Bool()
grayConfig.BackendGrayTag = json.Get("backendGrayTag").String()
if grayConfig.BackendGrayTag == "" {
diff --git a/plugins/wasm-go/extensions/frontend-gray/envoy.yaml b/plugins/wasm-go/extensions/frontend-gray/envoy.yaml
index 8dfccd46af..3d57170380 100644
--- a/plugins/wasm-go/extensions/frontend-gray/envoy.yaml
+++ b/plugins/wasm-go/extensions/frontend-gray/envoy.yaml
@@ -89,10 +89,10 @@ static_resources:
{
"name": "beta-user",
"version": "0.0.1",
- "enabled": true
+ "enabled": true,
+ "weight": 50
}
],
- "debugGrayWeight": true,
"injection": {
"head": [
""
diff --git a/plugins/wasm-go/extensions/frontend-gray/main.go b/plugins/wasm-go/extensions/frontend-gray/main.go
index cae4306329..59d2f8d4d7 100644
--- a/plugins/wasm-go/extensions/frontend-gray/main.go
+++ b/plugins/wasm-go/extensions/frontend-gray/main.go
@@ -62,12 +62,18 @@ func onHttpRequestHeaders(ctx wrapper.HttpContext, grayConfig config.GrayConfig,
xPreHigressVersion := util.ExtractCookieValueByKey(cookies, config.XPreHigressTag)
preVersions := strings.Split(xPreHigressVersion, ",")
- xForwardedFor, _ := proxywasm.GetHttpRequestHeader("X-Forwarded-For")
+ // 客户端唯一ID,用于在按照比率灰度时候 客户访问黏贴
+ uniqueClientId := grayKeyValue
+ if uniqueClientId == "" {
+ xForwardedFor, _ := proxywasm.GetHttpRequestHeader("X-Forwarded-For")
+ uniqueClientId = util.GetRealIpFromXff(xForwardedFor)
+ }
// 如果没有配置比例,则进行灰度规则匹配
if isIndex {
+ log.Infof("grayConfig.TotalGrayWeight==== %v", grayConfig.TotalGrayWeight)
if grayConfig.TotalGrayWeight > 0 {
- deployment = util.FilterGrayWeight(&grayConfig, preVersions, xForwardedFor)
+ deployment = util.FilterGrayWeight(&grayConfig, preVersions, uniqueClientId)
} else {
deployment = util.FilterGrayRule(&grayConfig, grayKeyValue)
}
@@ -80,7 +86,7 @@ func onHttpRequestHeaders(ctx wrapper.HttpContext, grayConfig config.GrayConfig,
ctx.SetContext(config.XPreHigressTag, deployment.Version)
ctx.SetContext(grayConfig.BackendGrayTag, deployment.BackendVersion)
ctx.SetContext(config.IsIndex, isIndex)
- ctx.SetContext(config.XForwardedFor, xForwardedFor)
+ ctx.SetContext(config.XUniqueClient, uniqueClientId)
rewrite := grayConfig.Rewrite
if rewrite.Host != "" {
@@ -154,10 +160,10 @@ func onHttpResponseHeader(ctx wrapper.HttpContext, grayConfig config.GrayConfig,
proxywasm.ReplaceHttpResponseHeader("Cache-Control", "no-cache, no-store")
frontendVersion := ctx.GetContext(config.XPreHigressTag).(string)
- xForwardedFor := ctx.GetContext(config.XForwardedFor).(string)
+ xUniqueClient := ctx.GetContext(config.XUniqueClient).(string)
// 设置前端的版本
- proxywasm.AddHttpResponseHeader("Set-Cookie", fmt.Sprintf("%s=%s,%s; Max-Age=%s; Path=/;", config.XPreHigressTag, frontendVersion, util.GetRealIpFromXff(xForwardedFor), config.MaxAgeCookie))
+ proxywasm.AddHttpResponseHeader("Set-Cookie", fmt.Sprintf("%s=%s,%s; Max-Age=%s; Path=/;", config.XPreHigressTag, frontendVersion, xUniqueClient, config.MaxAgeCookie))
// 设置后端的版本
if util.IsBackendGrayEnabled(grayConfig) {
backendVersion := ctx.GetContext(grayConfig.BackendGrayTag).(string)
diff --git a/plugins/wasm-go/extensions/frontend-gray/util/utils.go b/plugins/wasm-go/extensions/frontend-gray/util/utils.go
index 852d8a97d7..5e3b1aaec6 100644
--- a/plugins/wasm-go/extensions/frontend-gray/util/utils.go
+++ b/plugins/wasm-go/extensions/frontend-gray/util/utils.go
@@ -4,7 +4,6 @@ import (
"fmt"
"math/rand"
"net/url"
- "os"
"path"
"path/filepath"
"sort"
@@ -20,9 +19,7 @@ import (
func LogInfof(format string, args ...interface{}) {
format = fmt.Sprintf("[%s] %s", "frontend-gray", format)
- if os.Getenv("TEST_MODE") != "" {
- proxywasm.LogInfof(format, args...)
- }
+ proxywasm.LogInfof(format, args...)
}
// 从xff中获取真实的IP
@@ -234,31 +231,21 @@ func FilterGrayRule(grayConfig *config.GrayConfig, grayKeyValue string) *config.
return grayConfig.BaseDeployment
}
-func FilterGrayWeight(grayConfig *config.GrayConfig, preVersions []string, xForwardedFor string) *config.Deployment {
- deployments := append(grayConfig.GrayDeployments, grayConfig.BaseDeployment)
- realIp := GetRealIpFromXff(xForwardedFor)
-
- LogInfof("DebugGrayWeight enabled: %s, realIp: %s, preVersions: %v", grayConfig.DebugGrayWeight, realIp, preVersions)
- // 开启Debug模式,否则无法观测到效果
- if !grayConfig.DebugGrayWeight {
- // 如果没有获取到真实IP,则返回不走灰度规则
- if realIp == "" {
- return grayConfig.BaseDeployment
- }
-
- // 确保每个用户每次访问的都是走同一版本
- if len(preVersions) > 1 && preVersions[1] != "" && realIp == preVersions[1] {
- for _, deployment := range deployments {
- if deployment.Version == strings.Trim(preVersions[0], " ") {
- return deployment
- }
- }
- }
+func FilterGrayWeight(grayConfig *config.GrayConfig, preVersions []string, uniqueClientId string) *config.Deployment {
+ // 如果没有灰度权重,直接返回基础版本
+ if grayConfig.TotalGrayWeight == 0 {
return grayConfig.BaseDeployment
}
- if grayConfig.TotalGrayWeight == 0 {
- return grayConfig.BaseDeployment
+ deployments := append(grayConfig.GrayDeployments, grayConfig.BaseDeployment)
+ LogInfof("uniqueClientId: %s, preVersions: %v", uniqueClientId, preVersions)
+ // 用户粘滞,确保每个用户每次访问的都是走同一版本
+ if len(preVersions) > 1 && preVersions[1] != "" && uniqueClientId == preVersions[1] {
+ for _, deployment := range deployments {
+ if deployment.Version == strings.Trim(preVersions[0], " ") {
+ return deployment
+ }
+ }
}
totalWeight := 100