refactor(mcp): use ECDS for golang filter configuration to avoid connection drain (#2931)

This commit is contained in:
澄潭
2025-09-17 16:32:38 +08:00
committed by GitHub
parent e70b9ec437
commit 78860ce399
3 changed files with 144 additions and 126 deletions

View File

@@ -137,9 +137,9 @@ endif
# for now docker is limited to Linux compiles - why ?
include docker/docker.mk
docker-build-amd64: docker.higress-amd64 ## Build and push amdd64 docker images to registry defined by $HUB and $TAG
docker-build-amd64: clean-higress docker.higress-amd64 ## Build and push amdd64 docker images to registry defined by $HUB and $TAG
docker-build: docker.higress ## Build and push docker images to registry defined by $HUB and $TAG
docker-build: clean-higress docker.higress ## Build and push docker images to registry defined by $HUB and $TAG
docker-buildx-push: clean-env docker.higress-buildx

View File

@@ -328,9 +328,26 @@ func (m *McpServerController) ConstructEnvoyFilters() ([]*config.Config, error)
return configs, nil
}
// mcp-session envoy filter
// mcp-session envoy filter with ECDS
mcpSessionStruct := m.constructMcpSessionStruct(mcpServer)
if mcpSessionStruct != "" {
// HTTP_FILTER configuration with config_discovery reference
sessionFilterRef := `{
"name": "golang-filter-mcp-session",
"config_discovery": {
"config_source": {
"ads": {}
},
"type_urls": ["type.googleapis.com/envoy.extensions.filters.http.golang.v3alpha.Config"]
}
}`
// EXTENSION_CONFIG configuration with actual filter config
sessionExtensionConfig := fmt.Sprintf(`{
"name": "golang-filter-mcp-session",
"typed_config": %s
}`, mcpSessionStruct)
sessionConfig := &config.Config{
Meta: config.Meta{
GroupVersionKind: gvk.EnvoyFilter,
@@ -358,7 +375,14 @@ func (m *McpServerController) ConstructEnvoyFilters() ([]*config.Config, error)
},
Patch: &networking.EnvoyFilter_Patch{
Operation: networking.EnvoyFilter_Patch_INSERT_AFTER,
Value: util.BuildPatchStruct(mcpSessionStruct),
Value: util.BuildPatchStruct(sessionFilterRef),
},
},
{
ApplyTo: networking.EnvoyFilter_EXTENSION_CONFIG,
Patch: &networking.EnvoyFilter_Patch{
Operation: networking.EnvoyFilter_Patch_ADD,
Value: util.BuildPatchStruct(sessionExtensionConfig),
},
},
},
@@ -367,9 +391,26 @@ func (m *McpServerController) ConstructEnvoyFilters() ([]*config.Config, error)
configs = append(configs, sessionConfig)
}
// mcp-server envoy filter
// mcp-server envoy filter with ECDS
mcpServerStruct := m.constructMcpServerStruct(mcpServer)
if mcpServerStruct != "" {
// HTTP_FILTER configuration with config_discovery reference
serverFilterRef := `{
"name": "golang-filter-mcp-server",
"config_discovery": {
"config_source": {
"ads": {}
},
"type_urls": ["type.googleapis.com/envoy.extensions.filters.http.golang.v3alpha.Config"]
}
}`
// EXTENSION_CONFIG configuration with actual filter config
serverExtensionConfig := fmt.Sprintf(`{
"name": "golang-filter-mcp-server",
"typed_config": %s
}`, mcpServerStruct)
serverConfig := &config.Config{
Meta: config.Meta{
GroupVersionKind: gvk.EnvoyFilter,
@@ -397,7 +438,14 @@ func (m *McpServerController) ConstructEnvoyFilters() ([]*config.Config, error)
},
Patch: &networking.EnvoyFilter_Patch{
Operation: networking.EnvoyFilter_Patch_INSERT_BEFORE,
Value: util.BuildPatchStruct(mcpServerStruct),
Value: util.BuildPatchStruct(serverFilterRef),
},
},
{
ApplyTo: networking.EnvoyFilter_EXTENSION_CONFIG,
Patch: &networking.EnvoyFilter_Patch{
Operation: networking.EnvoyFilter_Patch_ADD,
Value: util.BuildPatchStruct(serverExtensionConfig),
},
},
},
@@ -478,26 +526,20 @@ func (m *McpServerController) constructMcpSessionStruct(mcp *McpServer) string {
}`, mcp.Ratelimit.Limit, mcp.Ratelimit.Window, whiteList)
}
// Build complete configuration structure
// Build complete configuration structure for EXTENSION_CONFIG
return fmt.Sprintf(`{
"name": "envoy.filters.http.golang",
"typed_config": {
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct",
"type_url": "type.googleapis.com/envoy.extensions.filters.http.golang.v3alpha.Config",
"@type": "type.googleapis.com/envoy.extensions.filters.http.golang.v3alpha.Config",
"library_id": "mcp-session",
"library_path": "/var/lib/istio/envoy/golang-filter.so",
"plugin_name": "mcp-session",
"plugin_config": {
"@type": "type.googleapis.com/xds.type.v3.TypedStruct",
"value": {
"library_id": "mcp-session",
"library_path": "/var/lib/istio/envoy/golang-filter.so",
"plugin_name": "mcp-session",
"plugin_config": {
"@type": "type.googleapis.com/xds.type.v3.TypedStruct",
"value": {
"redis": %s,
"rate_limit": %s,
"sse_path_suffix": "%s",
"match_list": %s,
"enable_user_level_server": %t
}
}
"redis": %s,
"rate_limit": %s,
"sse_path_suffix": "%s",
"match_list": %s,
"enable_user_level_server": %t
}
}
}`,
@@ -540,22 +582,16 @@ func (m *McpServerController) constructMcpServerStruct(mcp *McpServer) string {
servers = fmt.Sprintf("[%s]", strings.Join(serverConfigs, ","))
}
// Build complete configuration structure
// Build complete configuration structure for EXTENSION_CONFIG
return fmt.Sprintf(`{
"name": "envoy.filters.http.golang",
"typed_config": {
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct",
"type_url": "type.googleapis.com/envoy.extensions.filters.http.golang.v3alpha.Config",
"@type": "type.googleapis.com/envoy.extensions.filters.http.golang.v3alpha.Config",
"library_id": "mcp-server",
"library_path": "/var/lib/istio/envoy/golang-filter.so",
"plugin_name": "mcp-server",
"plugin_config": {
"@type": "type.googleapis.com/xds.type.v3.TypedStruct",
"value": {
"library_id": "mcp-server",
"library_path": "/var/lib/istio/envoy/golang-filter.so",
"plugin_name": "mcp-server",
"plugin_config": {
"@type": "type.googleapis.com/xds.type.v3.TypedStruct",
"value": {
"servers": %s
}
}
"servers": %s
}
}
}`, servers)

View File

@@ -599,29 +599,23 @@ func TestMcpServerController_constructMcpSessionStruct(t *testing.T) {
Servers: []*SSEServer{},
},
wantJSON: `{
"name": "envoy.filters.http.golang",
"typed_config": {
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct",
"type_url": "type.googleapis.com/envoy.extensions.filters.http.golang.v3alpha.Config",
"@type": "type.googleapis.com/envoy.extensions.filters.http.golang.v3alpha.Config",
"library_id": "mcp-session",
"library_path": "/var/lib/istio/envoy/golang-filter.so",
"plugin_name": "mcp-session",
"plugin_config": {
"@type": "type.googleapis.com/xds.type.v3.TypedStruct",
"value": {
"library_id": "mcp-session",
"library_path": "/var/lib/istio/envoy/golang-filter.so",
"plugin_name": "mcp-session",
"plugin_config": {
"@type": "type.googleapis.com/xds.type.v3.TypedStruct",
"value": {
"redis": {
"address": "localhost:6379",
"username": "",
"password": "",
"db": 0
},
"rate_limit": null,
"sse_path_suffix": "",
"match_list": [],
"enable_user_level_server": false
}
}
"redis": {
"address": "localhost:6379",
"username": "",
"password": "",
"db": 0
},
"rate_limit": null,
"sse_path_suffix": "",
"match_list": [],
"enable_user_level_server": false
}
}
}`,
@@ -666,54 +660,48 @@ func TestMcpServerController_constructMcpSessionStruct(t *testing.T) {
},
},
wantJSON: `{
"name": "envoy.filters.http.golang",
"typed_config": {
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct",
"type_url": "type.googleapis.com/envoy.extensions.filters.http.golang.v3alpha.Config",
"@type": "type.googleapis.com/envoy.extensions.filters.http.golang.v3alpha.Config",
"library_id": "mcp-session",
"library_path": "/var/lib/istio/envoy/golang-filter.so",
"plugin_name": "mcp-session",
"plugin_config": {
"@type": "type.googleapis.com/xds.type.v3.TypedStruct",
"value": {
"library_id": "mcp-session",
"library_path": "/var/lib/istio/envoy/golang-filter.so",
"plugin_name": "mcp-session",
"plugin_config": {
"@type": "type.googleapis.com/xds.type.v3.TypedStruct",
"value": {
"redis": {
"address": "localhost:6379",
"username": "user",
"password": "pass",
"db": 1
},
"rate_limit": {
"limit": 100,
"window": 3600,
"white_list": ["user1","user2"]
},
"sse_path_suffix": "/sse",
"match_list": [{
"match_rule_domain": "*",
"match_rule_path": "/test",
"match_rule_type": "exact",
"upstream_type": "",
"enable_path_rewrite": false,
"path_rewrite_prefix": ""
},{
"match_rule_domain": "*",
"match_rule_path": "/sse-test-1",
"match_rule_type": "prefix",
"upstream_type": "sse",
"enable_path_rewrite": false,
"path_rewrite_prefix": ""
},{
"match_rule_domain": "*",
"match_rule_path": "/sse-test-2",
"match_rule_type": "prefix",
"upstream_type": "sse",
"enable_path_rewrite": true,
"path_rewrite_prefix": "/mcp"
}],
"enable_user_level_server": true
}
}
"redis": {
"address": "localhost:6379",
"username": "user",
"password": "pass",
"db": 1
},
"rate_limit": {
"limit": 100,
"window": 3600,
"white_list": ["user1","user2"]
},
"sse_path_suffix": "/sse",
"match_list": [{
"match_rule_domain": "*",
"match_rule_path": "/test",
"match_rule_type": "exact",
"upstream_type": "",
"enable_path_rewrite": false,
"path_rewrite_prefix": ""
},{
"match_rule_domain": "*",
"match_rule_path": "/sse-test-1",
"match_rule_type": "prefix",
"upstream_type": "sse",
"enable_path_rewrite": false,
"path_rewrite_prefix": ""
},{
"match_rule_domain": "*",
"match_rule_path": "/sse-test-2",
"match_rule_type": "prefix",
"upstream_type": "sse",
"enable_path_rewrite": true,
"path_rewrite_prefix": "/mcp"
}],
"enable_user_level_server": true
}
}
}`,
@@ -762,26 +750,20 @@ func TestMcpServerController_constructMcpServerStruct(t *testing.T) {
},
},
wantJSON: `{
"name": "envoy.filters.http.golang",
"typed_config": {
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct",
"type_url": "type.googleapis.com/envoy.extensions.filters.http.golang.v3alpha.Config",
"@type": "type.googleapis.com/envoy.extensions.filters.http.golang.v3alpha.Config",
"library_id": "mcp-server",
"library_path": "/var/lib/istio/envoy/golang-filter.so",
"plugin_name": "mcp-server",
"plugin_config": {
"@type": "type.googleapis.com/xds.type.v3.TypedStruct",
"value": {
"library_id": "mcp-server",
"library_path": "/var/lib/istio/envoy/golang-filter.so",
"plugin_name": "mcp-server",
"plugin_config": {
"@type": "type.googleapis.com/xds.type.v3.TypedStruct",
"value": {
"servers": [{
"name": "test-server",
"path": "/test",
"type": "test",
"domain_list": ["example.com"],
"config": {"key":"value"}
}]
}
}
"servers": [{
"name": "test-server",
"path": "/test",
"type": "test",
"domain_list": ["example.com"],
"config": {"key":"value"}
}]
}
}
}`,