视频讲解:Envoy手把手入门视频讲解
go-control-plane 中的 filter 定义与下发
Filter 是填充在 listener 中作为 listener 配置下发的,listener 在 go-control-plane/envoy/api/v2/lds.pb.go 中定义,filter 的接口在 envoy/api/v2/listener/listener.pb.go 中定义,filter 的实现在 go-control-plane/envoy/config/filter/ 中。
listener_filters 的定义
Listener 中的 listener_filters 的在 go-control-plane 中定义如下:
// go-control-plane/envoy/api/v2/lds.pb.go
ListenerFilters []*listener.ListenerFilter
// go-control-plane/envoy/api/v2/listener/listener.pb.go
type ListenerFilter struct {
Name string
ConfigType isListenerFilter_ConfigType
XXX_NoUnkeyedLiteral struct{}
XXX_unrecognized []byte
XXX_sizecache int32
}
filter_chains 的定义
Listener 中的 filter_chains 在 go-control-plane 中定义如下,其中FilterChain 继续包含 Filter 链:
FilterChains []*listener.FilterChain
type FilterChain struct {
FilterChainMatch *FilterChainMatch
TlsContext *auth.DownstreamTlsContext
Filters []*Filter
UseProxyProto *types.BoolValue
Metadata *core.Metadata
TransportSocket *core.TransportSocket
XXX_NoUnkeyedLiteral struct{}
XXX_unrecognized []byte
XXX_sizecache int32
}
type Filter struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
ConfigType isFilter_ConfigType `protobuf_oneof:"config_type"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
filter 的定义
filter 的定义在 go-control-plane/envoy/config/filter 中,不同类型的 filter 都有各自的定义。用 go-control-plane 下发时,需要用 util.MessageToStruct() 转换成 *types.Struct 类型,或者用 ptypes.MarshalAny() 转换成 * any.Any 类型后,填充到 Listener 中。
以 listener_filters 的为例,ListenerFilter 中的 ConfigType 是一个接口变量:
// go-control-plane/envoy/api/v2/listener/listener.pb.go
type ListenerFilter struct {
Name string
ConfigType isListenerFilter_ConfigType
XXX_NoUnkeyedLiteral struct{}
XXX_unrecognized []byte
XXX_sizecache int32
}
// go-control-plane/envoy/api/v2/listener/listener.pb.go: 585
type isListenerFilter_ConfigType interface {
isListenerFilter_ConfigType()
Equal(interface{}) bool
MarshalTo([]byte) (int, error)
Size() int
}
isListenerFilter_ConfigType 是一个很简单的接口,实现该接口的 struct 是 ListenerFilter_Config 和 ListenerFilter_TypedConfig 。
// go-control-plane/envoy/api/v2/listener/listener.pb.go: 592
type ListenerFilter_Config struct {
Config *types.Struct
}
type ListenerFilter_TypedConfig struct {
TypedConfig *types.Any
}
func (*ListenerFilter_Config) isListenerFilter_ConfigType() {}
func (*ListenerFilter_TypedConfig) isListenerFilter_ConfigType() {}
上面的 Config 和 TypedConfig 就是 filter 转化而成的。
filter_chains 的情况类似,对应的 struct 是 Filter_Config 和 Filter_TypedConfig。
XX_Config 和 XX_TypedConfig 的区别
将 filter 填充到 listener 时,可以用 XX_Config 类型,也可以用 XX_TypedConfig 的类型,区别如下:
XX_Config:
- name: envoy.http_connection_manager
config:
stat_prefix: ingress_http
generate_request_id: true
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["webshell.com"]
routes:
- match:
prefix: "/"
route:
host_rewrite: webshell.com
cluster: service_webshell
http_filters:
- name: envoy.router
config:
dynamic_stats: false
XX_TypedConfig:
- name: envoy.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match:
prefix: "/"
route:
host_rewrite: www.baidu.com
cluster: service_baidu
http_filters:
- name: envoy.router
HTTP Connection Manager 的填充过程
以 HTTP Connection Manager 为例,填充操作如下:
// 创建一个 HttpConnectionManager
listen_filter_http_conn_ := &http_conn_manager.HttpConnectionManager{
StatPrefix: "ingress_http",
RouteSpecifier: &http_conn_manager.HttpConnectionManager_RouteConfig{
RouteConfig: &api_v2.RouteConfiguration{
Name: "None",
VirtualHosts: virtualHosts,
},
},
HttpFilters: httpFilters,
}
// 转换成 *types.Struct
listen_filter_http_conn, err := util.MessageToStruct(listen_filter_http_conn_)
if err != nil {
glog.Error(err)
return
}
// 用转换得到 *types.Struct 构造 listener.Filter_Config,继而构造 Filter
filter := &listener.Filter{
Name: "envoy.http_connection_manager",
ConfigType: &listener.Filter_Config{
Config: listen_filter_http_conn,
},
}
//然后把 filter 放入 filterChains 的一个成员的 filters 链中。
filters = append(filters, filter)
filterChain := &listener.FilterChain{
Filters: filters,
}
//最后将 filterChains 装入 listener
filterChains = append(filterChains, filterChain)
lis := &api_v2.Listener{
Name: "listener_with_static_route_port_9000",
Address: address,
FilterChains: filterChains,
}