Merge pull request #835 from milosgajdos83/router-strategy

Router strategy
This commit is contained in:
Asim Aslam 2019-10-09 19:18:59 +01:00 committed by GitHub
commit 5a6e73d4a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 85 additions and 20 deletions

View File

@ -319,23 +319,13 @@ func (r *router) advertiseTable() error {
for {
select {
case <-ticker.C:
// list routing table routes to announce
routes, err := r.table.List()
// do full table flush
events, err := r.flushRouteEvents(Update)
if err != nil {
return fmt.Errorf("failed listing routes: %s", err)
}
// collect all the added routes before we attempt to add default gateway
events := make([]*Event, len(routes))
for i, route := range routes {
event := &Event{
Type: Update,
Timestamp: time.Now(),
Route: route,
}
events[i] = event
return fmt.Errorf("failed flushing routes: %s", err)
}
// advertise all routes as Update events to subscribers
// advertise routes to subscribers
if len(events) > 0 {
log.Debugf("Router flushing table with %d events: %s", len(events), r.options.Id)
r.advertWg.Add(1)
@ -692,15 +682,58 @@ func (r *router) flushRouteEvents(evType EventType) ([]*Event, error) {
return nil, fmt.Errorf("failed listing routes: %s", err)
}
if r.options.Advertise == AdvertiseAll {
// build a list of events to advertise
events := make([]*Event, len(routes))
for i, route := range routes {
event := &Event{
Type: evType,
Timestamp: time.Now(),
Route: route,
}
events[i] = event
}
return events, nil
}
// routeMap stores optimal routes per service
bestRoutes := make(map[string]Route)
// go through all routes found in the routing table and collapse them to optimal routes
for _, route := range routes {
routeKey := route.Service + "@" + route.Network
optimal, ok := bestRoutes[routeKey]
if !ok {
bestRoutes[routeKey] = route
continue
}
// if the current optimal route metric is higher than routing table route, replace it
if optimal.Metric > route.Metric {
bestRoutes[routeKey] = route
continue
}
// if the metrics are the same, prefer advertising your own route
if optimal.Metric == route.Metric {
if route.Router == r.options.Id {
bestRoutes[routeKey] = route
continue
}
}
}
log.Debugf("Router advertising %d best routes out of %d", len(bestRoutes), len(routes))
// build a list of events to advertise
events := make([]*Event, len(routes))
for i, route := range routes {
events := make([]*Event, len(bestRoutes))
i := 0
for _, route := range bestRoutes {
event := &Event{
Type: evType,
Timestamp: time.Now(),
Route: route,
}
events[i] = event
i++
}
return events, nil

View File

@ -18,6 +18,8 @@ type Options struct {
Network string
// Registry is the local registry
Registry registry.Registry
// Advertise is the advertising strategy
Advertise Strategy
// Client for calling router
Client client.Client
}
@ -64,12 +66,20 @@ func Registry(r registry.Registry) Option {
}
}
// Strategy sets route advertising strategy
func Advertise(a Strategy) Option {
return func(o *Options) {
o.Advertise = a
}
}
// DefaultOptions returns router default options
func DefaultOptions() Options {
return Options{
Id: uuid.New().String(),
Address: DefaultAddress,
Network: DefaultNetwork,
Registry: registry.DefaultRegistry,
Id: uuid.New().String(),
Address: DefaultAddress,
Network: DefaultNetwork,
Registry: registry.DefaultRegistry,
Advertise: AdvertiseBest,
}
}

View File

@ -139,6 +139,28 @@ type Advert struct {
Events []*Event
}
// Strategy is route advertisement strategy
type Strategy int
const (
// AdvertiseAll advertises all routes to the network
AdvertiseAll Strategy = iota
// AdvertiseBest advertises optimal routes to the network
AdvertiseBest
)
// String returns human readable Strategy
func (s Strategy) String() string {
switch s {
case AdvertiseAll:
return "all"
case AdvertiseBest:
return "best"
default:
return "unknown"
}
}
// NewRouter creates new Router and returns it
func NewRouter(opts ...Option) Router {
return newRouter(opts...)