Move the network resolver out (#1944)

This commit is contained in:
Asim Aslam
2020-08-18 21:38:29 +01:00
committed by GitHub
parent 2eac8ed64f
commit 5d6b7b3d7d
9 changed files with 14 additions and 64 deletions

View File

@@ -7,7 +7,6 @@ import (
"io"
"math"
"math/rand"
"sort"
"sync"
"time"
@@ -17,9 +16,9 @@ import (
"github.com/micro/go-micro/v3/logger"
"github.com/micro/go-micro/v3/network"
pb "github.com/micro/go-micro/v3/network/mucp/proto"
"github.com/micro/go-micro/v3/network/resolver/dns"
"github.com/micro/go-micro/v3/proxy"
"github.com/micro/go-micro/v3/registry/noop"
"github.com/micro/go-micro/v3/resolver/dns"
"github.com/micro/go-micro/v3/router"
"github.com/micro/go-micro/v3/server"
smucp "github.com/micro/go-micro/v3/server/mucp"
@@ -35,8 +34,6 @@ var (
DefaultName = "go.micro"
// DefaultAddress is default network address
DefaultAddress = ":0"
// ResolveTime defines time interval to periodically resolve network nodes
ResolveTime = 1 * time.Minute
// AnnounceTime defines time interval to periodically announce node neighbours
AnnounceTime = 1 * time.Second
// KeepAliveTime is the time in which we want to have sent a message to a peer
@@ -424,43 +421,11 @@ func (n *mucpNetwork) initNodes(startup bool) {
// resolveNodes resolves network nodes to addresses
func (n *mucpNetwork) resolveNodes() ([]string, error) {
// resolve the network address to network nodes
records, err := n.options.Resolver.Resolve(n.options.Name)
if err != nil {
if logger.V(logger.DebugLevel, logger.DefaultLogger) {
logger.Debugf("Network failed to resolve nodes: %v", err)
}
}
// sort by lowest priority
if err == nil && len(records) > 0 {
sort.Slice(records, func(i, j int) bool { return records[i].Priority < records[j].Priority })
}
// keep processing
nodeMap := make(map[string]bool)
// collect network node addresses
//nolint:prealloc
var nodes []string
var i int
for _, record := range records {
if _, ok := nodeMap[record.Address]; ok {
continue
}
nodeMap[record.Address] = true
nodes = append(nodes, record.Address)
i++
// break once MaxConnection nodes has been reached
if i == MaxConnections {
break
}
}
// use the DNS resolver to expand peers
dns := &dns.Resolver{}
@@ -481,6 +446,7 @@ func (n *mucpNetwork) resolveNodes() ([]string, error) {
if _, ok := nodeMap[record.Address]; !ok {
nodes = append(nodes, record.Address)
}
nodeMap[record.Address] = true
}
}
@@ -1160,8 +1126,6 @@ func (n *mucpNetwork) manage() {
defer announce.Stop()
prune := time.NewTicker(PruneTime)
defer prune.Stop()
resolve := time.NewTicker(ResolveTime)
defer resolve.Stop()
netsync := time.NewTicker(SyncTime)
defer netsync.Stop()
@@ -1374,8 +1338,6 @@ func (n *mucpNetwork) manage() {
}
}
}()
case <-resolve.C:
n.initNodes(false)
}
}
}

View File

@@ -2,8 +2,6 @@ package network
import (
"github.com/google/uuid"
"github.com/micro/go-micro/v3/network/resolver"
"github.com/micro/go-micro/v3/network/resolver/noop"
"github.com/micro/go-micro/v3/proxy"
"github.com/micro/go-micro/v3/proxy/mucp"
"github.com/micro/go-micro/v3/router"
@@ -32,8 +30,6 @@ type Options struct {
Router router.Router
// Proxy is network proxy
Proxy proxy.Proxy
// Resolver is network resolver
Resolver resolver.Resolver
}
// Id sets the id of the network node
@@ -92,22 +88,14 @@ func Proxy(p proxy.Proxy) Option {
}
}
// Resolver is the network resolver
func Resolver(r resolver.Resolver) Option {
return func(o *Options) {
o.Resolver = r
}
}
// DefaultOptions returns network default options
func DefaultOptions() Options {
return Options{
Id: uuid.New().String(),
Name: "go.micro",
Address: ":0",
Tunnel: tmucp.NewTunnel(),
Router: regRouter.NewRouter(),
Proxy: mucp.NewProxy(),
Resolver: new(noop.Resolver),
Id: uuid.New().String(),
Name: "go.micro",
Address: ":0",
Tunnel: tmucp.NewTunnel(),
Router: regRouter.NewRouter(),
Proxy: mucp.NewProxy(),
}
}

View File

@@ -1,78 +0,0 @@
// Package dns resolves names to dns records
package dns
import (
"context"
"net"
"github.com/micro/go-micro/v3/network/resolver"
"github.com/miekg/dns"
)
// Resolver is a DNS network resolve
type Resolver struct {
// The resolver address to use
Address string
}
// Resolve assumes ID is a domain name e.g micro.mu
func (r *Resolver) Resolve(name string) ([]*resolver.Record, error) {
host, port, err := net.SplitHostPort(name)
if err != nil {
host = name
port = "8085"
}
if len(host) == 0 {
host = "localhost"
}
if len(r.Address) == 0 {
r.Address = "1.0.0.1:53"
}
//nolint:prealloc
var records []*resolver.Record
// parsed an actual ip
if v := net.ParseIP(host); v != nil {
records = append(records, &resolver.Record{
Address: net.JoinHostPort(host, port),
})
return records, nil
}
m := new(dns.Msg)
m.SetQuestion(dns.Fqdn(host), dns.TypeA)
rec, err := dns.ExchangeContext(context.Background(), m, r.Address)
if err != nil {
return nil, err
}
for _, answer := range rec.Answer {
h := answer.Header()
// check record type matches
if h.Rrtype != dns.TypeA {
continue
}
arec, _ := answer.(*dns.A)
addr := arec.A.String()
// join resolved record with port
address := net.JoinHostPort(addr, port)
// append to record set
records = append(records, &resolver.Record{
Address: address,
})
}
// no records returned so just best effort it
if len(records) == 0 {
records = append(records, &resolver.Record{
Address: net.JoinHostPort(host, port),
})
}
return records, nil
}

View File

@@ -1,31 +0,0 @@
// Package dns srv resolves names to dns srv records
package dnssrv
import (
"fmt"
"net"
"github.com/micro/go-micro/v3/network/resolver"
)
// Resolver is a DNS network resolve
type Resolver struct{}
// Resolve assumes ID is a domain name e.g micro.mu
func (r *Resolver) Resolve(name string) ([]*resolver.Record, error) {
_, addrs, err := net.LookupSRV("network", "udp", name)
if err != nil {
return nil, err
}
records := make([]*resolver.Record, 0, len(addrs))
for _, addr := range addrs {
address := addr.Target
if addr.Port > 0 {
address = fmt.Sprintf("%s:%d", addr.Target, addr.Port)
}
records = append(records, &resolver.Record{
Address: address,
})
}
return records, nil
}

View File

@@ -1,78 +0,0 @@
// Package http resolves names to network addresses using a http request
package http
import (
"encoding/json"
"errors"
"io/ioutil"
"net/http"
"net/url"
"github.com/micro/go-micro/v3/network/resolver"
)
// Resolver is a HTTP network resolver
type Resolver struct {
// If not set, defaults to http
Proto string
// Path sets the path to lookup. Defaults to /network
Path string
// Host url to use for the query
Host string
}
type Response struct {
Nodes []*resolver.Record `json:"nodes,omitempty"`
}
// Resolve assumes ID is a domain which can be converted to a http://name/network request
func (r *Resolver) Resolve(name string) ([]*resolver.Record, error) {
proto := "http"
host := "localhost:8080"
path := "/network/nodes"
if len(r.Proto) > 0 {
proto = r.Proto
}
if len(r.Path) > 0 {
path = r.Path
}
if len(r.Host) > 0 {
host = r.Host
}
uri := &url.URL{
Scheme: proto,
Path: path,
Host: host,
}
q := uri.Query()
q.Set("name", name)
uri.RawQuery = q.Encode()
rsp, err := http.Get(uri.String())
if err != nil {
return nil, err
}
defer rsp.Body.Close()
if rsp.StatusCode != 200 {
return nil, errors.New("non 200 response")
}
b, err := ioutil.ReadAll(rsp.Body)
if err != nil {
return nil, err
}
// encoding format is assumed to be json
var response *Response
if err := json.Unmarshal(b, &response); err != nil {
return nil, err
}
return response.Nodes, nil
}

View File

@@ -1,13 +0,0 @@
// Package noop is a noop resolver
package noop
import (
"github.com/micro/go-micro/v3/network/resolver"
)
type Resolver struct{}
// Resolve returns the list of nodes
func (r *Resolver) Resolve(name string) ([]*resolver.Record, error) {
return []*resolver.Record{}, nil
}

View File

@@ -1,39 +0,0 @@
// Package registry resolves names using the go-micro registry
package registry
import (
"github.com/micro/go-micro/v3/network/resolver"
"github.com/micro/go-micro/v3/registry"
"github.com/micro/go-micro/v3/registry/mdns"
)
// Resolver is a registry network resolver
type Resolver struct {
// Registry is the registry to use otherwise we use the defaul
Registry registry.Registry
}
// Resolve assumes ID is a domain name e.g micro.mu
func (r *Resolver) Resolve(name string) ([]*resolver.Record, error) {
reg := r.Registry
if reg == nil {
reg = mdns.NewRegistry()
}
services, err := reg.GetService(name)
if err != nil {
return nil, err
}
var records []*resolver.Record
for _, service := range services {
for _, node := range service.Nodes {
records = append(records, &resolver.Record{
Address: node.Address,
})
}
}
return records, nil
}

View File

@@ -1,16 +0,0 @@
// Package resolver resolves network names to addresses
package resolver
// Resolver is network resolver. It's used to find network nodes
// via the name to connect to. This is done based on Network.Name().
// Before we can be part of any network, we have to connect to it.
type Resolver interface {
// Resolve returns a list of addresses for a name
Resolve(name string) ([]*Record, error)
}
// A resolved record
type Record struct {
Address string `json:"address"`
Priority int64 `json:"priority"`
}

View File

@@ -1,33 +0,0 @@
// Package static is a static resolver
package static
import (
"github.com/micro/go-micro/v3/network/resolver"
)
// Resolver returns a static list of nodes. In the event the node list
// is not present it will return the name of the network passed in.
type Resolver struct {
// A static list of nodes
Nodes []string
}
// Resolve returns the list of nodes
func (r *Resolver) Resolve(name string) ([]*resolver.Record, error) {
// if there are no nodes just return the name
if len(r.Nodes) == 0 {
return []*resolver.Record{
{Address: name},
}, nil
}
records := make([]*resolver.Record, 0, len(r.Nodes))
for _, node := range r.Nodes {
records = append(records, &resolver.Record{
Address: node,
})
}
return records, nil
}