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 ? # for now docker is limited to Linux compiles - why ?
include docker/docker.mk 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 docker-buildx-push: clean-env docker.higress-buildx

View File

@@ -328,9 +328,26 @@ func (m *McpServerController) ConstructEnvoyFilters() ([]*config.Config, error)
return configs, nil return configs, nil
} }
// mcp-session envoy filter // mcp-session envoy filter with ECDS
mcpSessionStruct := m.constructMcpSessionStruct(mcpServer) mcpSessionStruct := m.constructMcpSessionStruct(mcpServer)
if mcpSessionStruct != "" { 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{ sessionConfig := &config.Config{
Meta: config.Meta{ Meta: config.Meta{
GroupVersionKind: gvk.EnvoyFilter, GroupVersionKind: gvk.EnvoyFilter,
@@ -358,7 +375,14 @@ func (m *McpServerController) ConstructEnvoyFilters() ([]*config.Config, error)
}, },
Patch: &networking.EnvoyFilter_Patch{ Patch: &networking.EnvoyFilter_Patch{
Operation: networking.EnvoyFilter_Patch_INSERT_AFTER, 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) configs = append(configs, sessionConfig)
} }
// mcp-server envoy filter // mcp-server envoy filter with ECDS
mcpServerStruct := m.constructMcpServerStruct(mcpServer) mcpServerStruct := m.constructMcpServerStruct(mcpServer)
if mcpServerStruct != "" { 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{ serverConfig := &config.Config{
Meta: config.Meta{ Meta: config.Meta{
GroupVersionKind: gvk.EnvoyFilter, GroupVersionKind: gvk.EnvoyFilter,
@@ -397,7 +438,14 @@ func (m *McpServerController) ConstructEnvoyFilters() ([]*config.Config, error)
}, },
Patch: &networking.EnvoyFilter_Patch{ Patch: &networking.EnvoyFilter_Patch{
Operation: networking.EnvoyFilter_Patch_INSERT_BEFORE, 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) }`, mcp.Ratelimit.Limit, mcp.Ratelimit.Window, whiteList)
} }
// Build complete configuration structure // Build complete configuration structure for EXTENSION_CONFIG
return fmt.Sprintf(`{ return fmt.Sprintf(`{
"name": "envoy.filters.http.golang", "@type": "type.googleapis.com/envoy.extensions.filters.http.golang.v3alpha.Config",
"typed_config": { "library_id": "mcp-session",
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", "library_path": "/var/lib/istio/envoy/golang-filter.so",
"type_url": "type.googleapis.com/envoy.extensions.filters.http.golang.v3alpha.Config", "plugin_name": "mcp-session",
"plugin_config": {
"@type": "type.googleapis.com/xds.type.v3.TypedStruct",
"value": { "value": {
"library_id": "mcp-session", "redis": %s,
"library_path": "/var/lib/istio/envoy/golang-filter.so", "rate_limit": %s,
"plugin_name": "mcp-session", "sse_path_suffix": "%s",
"plugin_config": { "match_list": %s,
"@type": "type.googleapis.com/xds.type.v3.TypedStruct", "enable_user_level_server": %t
"value": {
"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, ",")) servers = fmt.Sprintf("[%s]", strings.Join(serverConfigs, ","))
} }
// Build complete configuration structure // Build complete configuration structure for EXTENSION_CONFIG
return fmt.Sprintf(`{ return fmt.Sprintf(`{
"name": "envoy.filters.http.golang", "@type": "type.googleapis.com/envoy.extensions.filters.http.golang.v3alpha.Config",
"typed_config": { "library_id": "mcp-server",
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", "library_path": "/var/lib/istio/envoy/golang-filter.so",
"type_url": "type.googleapis.com/envoy.extensions.filters.http.golang.v3alpha.Config", "plugin_name": "mcp-server",
"plugin_config": {
"@type": "type.googleapis.com/xds.type.v3.TypedStruct",
"value": { "value": {
"library_id": "mcp-server", "servers": %s
"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) }`, servers)

View File

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