mucp Proxy no longer uses RPC interface of router.Router directly
This commit is contained in:
parent
388ac34b7c
commit
b55adc0c30
@ -4,12 +4,10 @@ package mucp
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/micro/go-micro/client"
|
"github.com/micro/go-micro/client"
|
||||||
"github.com/micro/go-micro/client/selector"
|
|
||||||
"github.com/micro/go-micro/codec"
|
"github.com/micro/go-micro/codec"
|
||||||
"github.com/micro/go-micro/codec/bytes"
|
"github.com/micro/go-micro/codec/bytes"
|
||||||
"github.com/micro/go-micro/config/options"
|
"github.com/micro/go-micro/config/options"
|
||||||
@ -17,7 +15,6 @@ import (
|
|||||||
"github.com/micro/go-micro/network/router"
|
"github.com/micro/go-micro/network/router"
|
||||||
"github.com/micro/go-micro/server"
|
"github.com/micro/go-micro/server"
|
||||||
|
|
||||||
pb "github.com/micro/go-micro/network/router/proto"
|
|
||||||
"github.com/micro/go-micro/network/router/table"
|
"github.com/micro/go-micro/network/router/table"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -27,7 +24,7 @@ type Proxy struct {
|
|||||||
// embed options
|
// embed options
|
||||||
options.Options
|
options.Options
|
||||||
|
|
||||||
// Endpoint specified the fixed service endpoint to call.
|
// Endpoint specifies the fixed service endpoint to call.
|
||||||
Endpoint string
|
Endpoint string
|
||||||
|
|
||||||
// The client to use for outbound requests
|
// The client to use for outbound requests
|
||||||
@ -36,12 +33,9 @@ type Proxy struct {
|
|||||||
// The router for routes
|
// The router for routes
|
||||||
Router router.Router
|
Router router.Router
|
||||||
|
|
||||||
// The router service client
|
|
||||||
RouterService pb.RouterService
|
|
||||||
|
|
||||||
// A fib of routes service:address
|
// A fib of routes service:address
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
Routes map[string][]table.Route
|
Routes map[string]map[uint64]table.Route
|
||||||
}
|
}
|
||||||
|
|
||||||
// read client request and write to server
|
// read client request and write to server
|
||||||
@ -79,155 +73,54 @@ func readLoop(r server.Request, s client.Stream) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// toNodes returns a list of node addresses from given routes
|
||||||
|
func toNodes(routes map[uint64]table.Route) []string {
|
||||||
|
var nodes []string
|
||||||
|
for _, node := range routes {
|
||||||
|
address := node.Address
|
||||||
|
if len(node.Gateway) > 0 {
|
||||||
|
address = node.Gateway
|
||||||
|
}
|
||||||
|
nodes = append(nodes, address)
|
||||||
|
}
|
||||||
|
return nodes
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Proxy) getRoute(service string) ([]string, error) {
|
func (p *Proxy) getRoute(service string) ([]string, error) {
|
||||||
// converts routes to just addresses
|
|
||||||
toNodes := func(routes []table.Route) []string {
|
|
||||||
var nodes []string
|
|
||||||
for _, node := range routes {
|
|
||||||
address := node.Address
|
|
||||||
if len(node.Gateway) > 0 {
|
|
||||||
address = node.Gateway
|
|
||||||
}
|
|
||||||
nodes = append(nodes, address)
|
|
||||||
}
|
|
||||||
return nodes
|
|
||||||
}
|
|
||||||
|
|
||||||
// lookup the route cache first
|
// lookup the route cache first
|
||||||
p.RLock()
|
p.Lock()
|
||||||
routes, ok := p.Routes[service]
|
routes, ok := p.Routes[service]
|
||||||
// got it!
|
|
||||||
if ok {
|
if ok {
|
||||||
p.RUnlock()
|
|
||||||
return toNodes(routes), nil
|
|
||||||
}
|
|
||||||
p.RUnlock()
|
|
||||||
|
|
||||||
// route cache miss, now lookup the router
|
|
||||||
// if it does not exist, don't error out
|
|
||||||
// the proxy will just hand off to the client
|
|
||||||
// and try the registry
|
|
||||||
// in future we might set a default gateway
|
|
||||||
if p.Router != nil {
|
|
||||||
// lookup the router
|
|
||||||
routes, err := p.Router.Lookup(
|
|
||||||
table.NewQuery(table.QueryService(service)),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
p.Lock()
|
|
||||||
if p.Routes == nil {
|
|
||||||
p.Routes = make(map[string][]table.Route)
|
|
||||||
}
|
|
||||||
p.Routes[service] = routes
|
|
||||||
p.Unlock()
|
p.Unlock()
|
||||||
|
|
||||||
return toNodes(routes), nil
|
return toNodes(routes), nil
|
||||||
}
|
}
|
||||||
|
p.Routes[service] = make(map[uint64]table.Route)
|
||||||
|
p.Unlock()
|
||||||
|
|
||||||
// we've tried getting cached routes
|
// if the router is broken return error
|
||||||
// we've tried using the router
|
if status := p.Router.Status(); status.Code == router.Error {
|
||||||
addr := os.Getenv("MICRO_ROUTER_ADDRESS")
|
return nil, status.Error
|
||||||
name := os.Getenv("MICRO_ROUTER")
|
|
||||||
|
|
||||||
// no router is specified we're going to set the default
|
|
||||||
if len(name) == 0 && len(addr) == 0 {
|
|
||||||
p.Router = router.DefaultRouter
|
|
||||||
go p.Router.Advertise()
|
|
||||||
|
|
||||||
// recursively execute getRoute
|
|
||||||
return p.getRoute(service)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(name) == 0 {
|
// lookup the routes in the router
|
||||||
name = "go.micro.router"
|
results, err := p.Router.Lookup(table.NewQuery(table.QueryService(service)))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// lookup the remote router
|
// update the proxy cache
|
||||||
|
p.Lock()
|
||||||
var addrs []string
|
for _, route := range results {
|
||||||
|
p.Routes[service][route.Hash()] = route
|
||||||
// set the remote address if specified
|
|
||||||
if len(addr) > 0 {
|
|
||||||
addrs = append(addrs, addr)
|
|
||||||
} else {
|
|
||||||
// we have a name so we need to check the registry
|
|
||||||
services, err := p.Client.Options().Registry.GetService(name)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, service := range services {
|
|
||||||
for _, node := range service.Nodes {
|
|
||||||
addrs = append(addrs, node.Address)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// no router addresses available
|
|
||||||
if len(addrs) == 0 {
|
|
||||||
return nil, selector.ErrNoneAvailable
|
|
||||||
}
|
|
||||||
|
|
||||||
var pbRoutes *pb.LookupResponse
|
|
||||||
var gerr error
|
|
||||||
|
|
||||||
// set default client
|
|
||||||
if p.RouterService == nil {
|
|
||||||
p.RouterService = pb.NewRouterService(name, p.Client)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: implement backoff and retries
|
|
||||||
for _, addr := range addrs {
|
|
||||||
// call the router
|
|
||||||
proutes, err := p.RouterService.Lookup(context.Background(), &pb.LookupRequest{
|
|
||||||
Query: &pb.Query{
|
|
||||||
Service: service,
|
|
||||||
},
|
|
||||||
}, client.WithAddress(addr))
|
|
||||||
if err != nil {
|
|
||||||
gerr = err
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// set routes
|
|
||||||
pbRoutes = proutes
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// errored out
|
|
||||||
if gerr != nil {
|
|
||||||
return nil, gerr
|
|
||||||
}
|
|
||||||
|
|
||||||
// no routes
|
|
||||||
if pbRoutes == nil {
|
|
||||||
return nil, selector.ErrNoneAvailable
|
|
||||||
}
|
|
||||||
|
|
||||||
// convert from pb to []*router.Route
|
|
||||||
for _, r := range pbRoutes.Routes {
|
|
||||||
routes = append(routes, table.Route{
|
|
||||||
Service: r.Service,
|
|
||||||
Address: r.Address,
|
|
||||||
Gateway: r.Gateway,
|
|
||||||
Network: r.Network,
|
|
||||||
Link: r.Link,
|
|
||||||
Metric: int(r.Metric),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
routes = p.Routes[service]
|
||||||
|
p.Unlock()
|
||||||
|
|
||||||
return toNodes(routes), nil
|
return toNodes(routes), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServeRequest honours the server.Router interface
|
// ServeRequest honours the server.Router interface
|
||||||
func (p *Proxy) ServeRequest(ctx context.Context, req server.Request, rsp server.Response) error {
|
func (p *Proxy) ServeRequest(ctx context.Context, req server.Request, rsp server.Response) error {
|
||||||
// set default client
|
|
||||||
if p.Client == nil {
|
|
||||||
p.Client = client.DefaultClient
|
|
||||||
}
|
|
||||||
|
|
||||||
// service name
|
// service name
|
||||||
service := req.Service()
|
service := req.Service()
|
||||||
endpoint := req.Endpoint()
|
endpoint := req.Endpoint()
|
||||||
@ -342,13 +235,24 @@ func NewProxy(opts ...options.Option) proxy.Proxy {
|
|||||||
p.Client = c.(client.Client)
|
p.Client = c.(client.Client)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set the default client
|
||||||
|
if p.Client == nil {
|
||||||
|
p.Client = client.DefaultClient
|
||||||
|
}
|
||||||
|
|
||||||
// get router
|
// get router
|
||||||
r, ok := p.Options.Values().Get("proxy.router")
|
r, ok := p.Options.Values().Get("proxy.router")
|
||||||
if ok {
|
if ok {
|
||||||
p.Router = r.(router.Router)
|
p.Router = r.(router.Router)
|
||||||
// TODO: should we advertise?
|
|
||||||
go p.Router.Advertise()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create default router and start it
|
||||||
|
if p.Router == nil {
|
||||||
|
p.Router = router.DefaultRouter
|
||||||
|
}
|
||||||
|
|
||||||
|
// routes cache
|
||||||
|
p.Routes = make(map[string]map[uint64]table.Route)
|
||||||
|
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user