|
|
|
@ -21,71 +21,89 @@ import ( |
|
|
|
|
"github.com/go-kratos/kratos/v2/transport/http" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
type router struct { |
|
|
|
|
service string |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type RouterOption func(o *router) |
|
|
|
|
|
|
|
|
|
// WithRouterService set the caller service name used by the route
|
|
|
|
|
func WithRouterService(service string) RouterOption { |
|
|
|
|
return func(o *router) { |
|
|
|
|
o.service = service |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// NodeFilter polaris dynamic router selector
|
|
|
|
|
func (p *Polaris) NodeFilter() selector.NodeFilter { |
|
|
|
|
func (p *Polaris) NodeFilter(opts ...RouterOption) selector.NodeFilter { |
|
|
|
|
o := router{service: p.service} |
|
|
|
|
for _, opt := range opts { |
|
|
|
|
opt(&o) |
|
|
|
|
} |
|
|
|
|
return func(ctx context.Context, nodes []selector.Node) []selector.Node { |
|
|
|
|
if len(nodes) == 0 { |
|
|
|
|
return nodes |
|
|
|
|
} |
|
|
|
|
req := &polaris.ProcessRoutersRequest{ |
|
|
|
|
ProcessRoutersRequest: model.ProcessRoutersRequest{ |
|
|
|
|
SourceService: model.ServiceInfo{Namespace: p.namespace, Service: o.service}, |
|
|
|
|
DstInstances: buildPolarisInstance(p.namespace, nodes), |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
if appInfo, ok := kratos.FromContext(ctx); ok { |
|
|
|
|
req := &polaris.ProcessRoutersRequest{ |
|
|
|
|
ProcessRoutersRequest: model.ProcessRoutersRequest{ |
|
|
|
|
SourceService: model.ServiceInfo{ |
|
|
|
|
Service: appInfo.Name(), |
|
|
|
|
Namespace: p.namespace, |
|
|
|
|
}, |
|
|
|
|
DstInstances: buildPolarisInstance(p.namespace, nodes), |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
req.AddArguments(model.BuildCallerServiceArgument(p.namespace, appInfo.Name())) |
|
|
|
|
req.SourceService.Service = appInfo.Name() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// process transport
|
|
|
|
|
if tr, ok := transport.FromServerContext(ctx); ok { |
|
|
|
|
req.AddArguments(model.BuildMethodArgument(tr.Operation())) |
|
|
|
|
req.AddArguments(model.BuildPathArgument(tr.Operation())) |
|
|
|
|
req.AddArguments(model.BuildCallerServiceArgument(p.namespace, req.ProcessRoutersRequest.SourceService.Service)) |
|
|
|
|
|
|
|
|
|
for _, key := range tr.RequestHeader().Keys() { |
|
|
|
|
req.AddArguments(model.BuildHeaderArgument(key, tr.RequestHeader().Get(key))) |
|
|
|
|
} |
|
|
|
|
// process transport
|
|
|
|
|
if tr, ok := transport.FromClientContext(ctx); ok { |
|
|
|
|
req.AddArguments(model.BuildMethodArgument(tr.Operation())) |
|
|
|
|
req.AddArguments(model.BuildPathArgument(tr.Operation())) |
|
|
|
|
|
|
|
|
|
for _, key := range tr.RequestHeader().Keys() { |
|
|
|
|
req.AddArguments(model.BuildHeaderArgument(strings.ToLower(key), tr.RequestHeader().Get(key))) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// http
|
|
|
|
|
if ht, ok := tr.(http.Transporter); ok { |
|
|
|
|
req.AddArguments(model.BuildPathArgument(ht.Request().URL.Path)) |
|
|
|
|
req.AddArguments(model.BuildCallerIPArgument(ht.Request().RemoteAddr)) |
|
|
|
|
// http
|
|
|
|
|
if ht, ok := tr.(http.Transporter); ok { |
|
|
|
|
req.AddArguments(model.BuildPathArgument(ht.Request().URL.Path)) |
|
|
|
|
req.AddArguments(model.BuildCallerIPArgument(ht.Request().RemoteAddr)) |
|
|
|
|
|
|
|
|
|
// cookie
|
|
|
|
|
for _, cookie := range ht.Request().Cookies() { |
|
|
|
|
req.AddArguments(model.BuildCookieArgument(cookie.Name, cookie.Value)) |
|
|
|
|
} |
|
|
|
|
// cookie
|
|
|
|
|
for _, cookie := range ht.Request().Cookies() { |
|
|
|
|
req.AddArguments(model.BuildCookieArgument(cookie.Name, cookie.Value)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// url query
|
|
|
|
|
for key, values := range ht.Request().URL.Query() { |
|
|
|
|
req.AddArguments(model.BuildQueryArgument(key, strings.Join(values, ","))) |
|
|
|
|
} |
|
|
|
|
// url query
|
|
|
|
|
for key, values := range ht.Request().URL.Query() { |
|
|
|
|
req.AddArguments(model.BuildQueryArgument(key, strings.Join(values, ","))) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
n := make(map[string]selector.Node, len(nodes)) |
|
|
|
|
n := make(map[string]selector.Node, len(nodes)) |
|
|
|
|
|
|
|
|
|
for _, node := range nodes { |
|
|
|
|
n[node.Address()] = node |
|
|
|
|
} |
|
|
|
|
for _, node := range nodes { |
|
|
|
|
n[node.Address()] = node |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
m, err := p.router.ProcessRouters(req) |
|
|
|
|
if err != nil { |
|
|
|
|
log.Errorf("polaris process routers failed, err=%v", err) |
|
|
|
|
return nodes |
|
|
|
|
} |
|
|
|
|
m, err := p.router.ProcessRouters(req) |
|
|
|
|
if err != nil { |
|
|
|
|
log.Errorf("polaris process routers failed, err=%v", err) |
|
|
|
|
return nodes |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
newNode := make([]selector.Node, 0, len(m.Instances)) |
|
|
|
|
for _, ins := range m.GetInstances() { |
|
|
|
|
if v, ok := n[fmt.Sprintf("%s:%d", ins.GetHost(), ins.GetPort())]; ok { |
|
|
|
|
newNode = append(newNode, v) |
|
|
|
|
} |
|
|
|
|
newNode := make([]selector.Node, 0, len(m.Instances)) |
|
|
|
|
for _, ins := range m.GetInstances() { |
|
|
|
|
if v, ok := n[fmt.Sprintf("%s:%d", ins.GetHost(), ins.GetPort())]; ok { |
|
|
|
|
newNode = append(newNode, v) |
|
|
|
|
} |
|
|
|
|
return newNode |
|
|
|
|
} |
|
|
|
|
return nodes |
|
|
|
|
if len(newNode) == 0 { |
|
|
|
|
return nodes |
|
|
|
|
} |
|
|
|
|
return newNode |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|