fix load time when cache is not ready with openbgpd
This commit is contained in:
parent
4b180a7b34
commit
cac7d44f87
@ -24,7 +24,10 @@ func (s *Server) apiNeighborsList(
|
||||
var neighborsResponse *api.NeighborsResponse
|
||||
|
||||
// Try to fetch neighbors from store, only fall back
|
||||
// to RS query if store is not ready yet
|
||||
// to RS query if store is not ready yet.
|
||||
// The stored neighbors response includes details like
|
||||
// the number of filtered routes which might be lacking
|
||||
// from the summary.
|
||||
if s.neighborsStore.IsInitialized(rsID) {
|
||||
status, err := s.neighborsStore.GetStatus(rsID)
|
||||
neighbors, err := s.neighborsStore.GetNeighborsAt(ctx, rsID)
|
||||
@ -51,7 +54,7 @@ func (s *Server) apiNeighborsList(
|
||||
if source == nil {
|
||||
return nil, ErrSourceNotFound
|
||||
}
|
||||
neighborsResponse, err = source.Neighbors()
|
||||
neighborsResponse, err = source.NeighborsSummary()
|
||||
if err != nil {
|
||||
s.logSourceError("neighbors", rsID, err)
|
||||
return nil, err
|
||||
|
@ -395,6 +395,11 @@ func (src *MultiTableBirdwatcher) Neighbors() (*api.NeighborsResponse, error) {
|
||||
return response, nil // dereference for now
|
||||
}
|
||||
|
||||
// NeighborsSummary is for now using Neighbors
|
||||
func (src *MultiTableBirdwatcher) NeighborsSummary() (*api.NeighborsResponse, error) {
|
||||
return src.Neighbors()
|
||||
}
|
||||
|
||||
// Routes gets filtered and exported route
|
||||
// from the birdwatcher backend.
|
||||
func (src *MultiTableBirdwatcher) Routes(
|
||||
|
@ -182,10 +182,14 @@ func (src *SingleTableBirdwatcher) Neighbors() (*api.NeighborsResponse, error) {
|
||||
|
||||
// Cache result
|
||||
src.neighborsCache.Set(response)
|
||||
|
||||
return response, nil // dereference for now
|
||||
}
|
||||
|
||||
// NeighborsSummary is for now an alias of Neighbors
|
||||
func (src *SingleTableBirdwatcher) NeighborsSummary() (*api.NeighborsResponse, error) {
|
||||
return src.Neighbors()
|
||||
}
|
||||
|
||||
// Routes gets filtered and exported routes
|
||||
func (src *SingleTableBirdwatcher) Routes(
|
||||
neighborID string,
|
||||
|
@ -202,6 +202,11 @@ func (gobgp *GoBGP) Neighbors() (*api.NeighborsResponse, error) {
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
// NeighborsSummary is an alias of Neighbors for now
|
||||
func (gobgp *GoBGP) NeighborsSummary() (*api.NeighborsResponse, error) {
|
||||
return gobgp.Neighbors()
|
||||
}
|
||||
|
||||
// Routes retrieves filtered and exported routes
|
||||
func (gobgp *GoBGP) Routes(neighborID string) (*api.RoutesResponse, error) {
|
||||
neigh, err := gobgp.lookupNeighbor(neighborID)
|
||||
|
@ -23,7 +23,8 @@ type BgplgdSource struct {
|
||||
cfg *Config
|
||||
|
||||
// Store the neighbor responses from the server here
|
||||
neighborsCache *caches.NeighborsCache
|
||||
neighborsCache *caches.NeighborsCache
|
||||
neighborsSummaryCache *caches.NeighborsCache
|
||||
|
||||
// Store the routes responses from the server
|
||||
// here identified by neighborID
|
||||
@ -38,16 +39,18 @@ func NewBgplgdSource(cfg *Config) *BgplgdSource {
|
||||
|
||||
// Initialize caches
|
||||
nc := caches.NewNeighborsCache(cacheDisabled)
|
||||
nsc := caches.NewNeighborsCache(cacheDisabled)
|
||||
rc := caches.NewRoutesCache(cacheDisabled, cfg.RoutesCacheSize)
|
||||
rrc := caches.NewRoutesCache(cacheDisabled, cfg.RoutesCacheSize)
|
||||
rfc := caches.NewRoutesCache(cacheDisabled, cfg.RoutesCacheSize)
|
||||
|
||||
return &BgplgdSource{
|
||||
cfg: cfg,
|
||||
neighborsCache: nc,
|
||||
routesCache: rc,
|
||||
routesReceivedCache: rrc,
|
||||
routesFilteredCache: rfc,
|
||||
cfg: cfg,
|
||||
neighborsCache: nc,
|
||||
neighborsSummaryCache: nsc,
|
||||
routesCache: rc,
|
||||
routesReceivedCache: rrc,
|
||||
routesFilteredCache: rfc,
|
||||
}
|
||||
}
|
||||
|
||||
@ -172,6 +175,51 @@ func (src *BgplgdSource) Neighbors() (*api.NeighborsResponse, error) {
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// NeighborsSummary retrievs list of neighbors, which
|
||||
// might lack details like with number of rejected routes.
|
||||
// It is much faster though.
|
||||
func (src *BgplgdSource) NeighborsSummary() (*api.NeighborsResponse, error) {
|
||||
// Query cache and see if we have a hit
|
||||
response := src.neighborsSummaryCache.Get()
|
||||
if response != nil {
|
||||
response.Meta.ResultFromCache = true
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// Make API request and read response
|
||||
req, err := src.ShowNeighborsRequest(context.Background())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
body, err := decoders.ReadJSONResponse(res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nb, err := decodeNeighbors(body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Set route server id (sourceID) for all neighbors and
|
||||
// calculate the filtered routes.
|
||||
for _, n := range nb {
|
||||
n.RouteServerID = src.cfg.ID
|
||||
|
||||
}
|
||||
response = &api.NeighborsResponse{
|
||||
Response: api.Response{
|
||||
Meta: src.makeResponseMeta(),
|
||||
},
|
||||
Neighbors: nb,
|
||||
}
|
||||
src.neighborsSummaryCache.Set(response)
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// NeighborsStatus retrives the status summary
|
||||
// for all neightbors
|
||||
func (src *BgplgdSource) NeighborsStatus() (*api.NeighborsStatusResponse, error) {
|
||||
|
@ -28,7 +28,8 @@ type StateServerSource struct {
|
||||
cfg *Config
|
||||
|
||||
// Store the neighbor responses from the server here
|
||||
neighborsCache *caches.NeighborsCache
|
||||
neighborsCache *caches.NeighborsCache
|
||||
neighborsSummaryCache *caches.NeighborsCache
|
||||
|
||||
// Store the routes responses from the server
|
||||
// here identified by neighborID
|
||||
@ -44,16 +45,18 @@ func NewStateServerSource(cfg *Config) *StateServerSource {
|
||||
|
||||
// Initialize caches
|
||||
nc := caches.NewNeighborsCache(cacheDisabled)
|
||||
nsc := caches.NewNeighborsCache(cacheDisabled)
|
||||
rc := caches.NewRoutesCache(cacheDisabled, cfg.RoutesCacheSize)
|
||||
rrc := caches.NewRoutesCache(cacheDisabled, cfg.RoutesCacheSize)
|
||||
rfc := caches.NewRoutesCache(cacheDisabled, cfg.RoutesCacheSize)
|
||||
|
||||
return &StateServerSource{
|
||||
cfg: cfg,
|
||||
neighborsCache: nc,
|
||||
routesCache: rc,
|
||||
routesReceivedCache: rrc,
|
||||
routesFilteredCache: rfc,
|
||||
cfg: cfg,
|
||||
neighborsCache: nc,
|
||||
neighborsSummaryCache: nsc,
|
||||
routesCache: rc,
|
||||
routesReceivedCache: rrc,
|
||||
routesFilteredCache: rfc,
|
||||
}
|
||||
}
|
||||
|
||||
@ -195,6 +198,49 @@ func (src *StateServerSource) Neighbors() (*api.NeighborsResponse, error) {
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// NeighborsSummary retrieves the neighbors without additional
|
||||
// information but as quickly as possible. The result will lack
|
||||
// a reject count.
|
||||
func (src *StateServerSource) NeighborsSummary() (*api.NeighborsResponse, error) {
|
||||
response := src.neighborsSummaryCache.Get()
|
||||
if response != nil {
|
||||
response.Meta.ResultFromCache = true
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// Make API request and read response
|
||||
req, err := src.ShowNeighborsRequest(context.Background())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
body, err := decoders.ReadJSONResponse(res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nb, err := decodeNeighbors(body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Set route server id (sourceID) for all neighbors
|
||||
for _, n := range nb {
|
||||
n.RouteServerID = src.cfg.ID
|
||||
}
|
||||
|
||||
response = &api.NeighborsResponse{
|
||||
Response: api.Response{
|
||||
Meta: src.makeResponseMeta(),
|
||||
},
|
||||
Neighbors: nb,
|
||||
}
|
||||
src.neighborsSummaryCache.Set(response)
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// NeighborsStatus retrives the status summary
|
||||
// for all neightbors
|
||||
func (src *StateServerSource) NeighborsStatus() (*api.NeighborsStatusResponse, error) {
|
||||
|
@ -25,6 +25,7 @@ type Source interface {
|
||||
ExpireCaches() int
|
||||
Status() (*api.StatusResponse, error)
|
||||
Neighbors() (*api.NeighborsResponse, error)
|
||||
NeighborsSummary() (*api.NeighborsResponse, error)
|
||||
NeighborsStatus() (*api.NeighborsStatusResponse, error)
|
||||
Routes(neighborID string) (*api.RoutesResponse, error)
|
||||
RoutesReceived(neighborID string) (*api.RoutesResponse, error)
|
||||
|
@ -2,6 +2,7 @@ package memory
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"sync"
|
||||
|
||||
"github.com/alice-lg/alice-lg/pkg/api"
|
||||
@ -97,6 +98,9 @@ func (b *NeighborsBackend) CountNeighborsAt(
|
||||
) (int, error) {
|
||||
neighbors, err := b.GetNeighborsAt(ctx, sourceID)
|
||||
if err != nil {
|
||||
if errors.Is(err, sources.ErrSourceNotFound) {
|
||||
return 0, nil
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
return len(neighbors), nil
|
||||
|
@ -141,14 +141,23 @@ func (s *SourcesStore) ShouldRefresh(
|
||||
log.Println("get status error:", err)
|
||||
return false
|
||||
}
|
||||
|
||||
nextRefresh := status.LastRefresh.Add(s.refreshInterval)
|
||||
|
||||
if status.State == StateBusy {
|
||||
return false // Source is busy
|
||||
}
|
||||
nextRefresh := status.LastRefresh.Add(
|
||||
s.refreshInterval)
|
||||
if status.State == StateError {
|
||||
// The refresh interval in the config is ok if the
|
||||
// success case. When an error occures it is desireable
|
||||
// to retry sooner, without spamming the server.
|
||||
nextRefresh = status.LastRefresh.Add(10 * time.Second)
|
||||
}
|
||||
|
||||
if time.Now().UTC().Before(nextRefresh) {
|
||||
return false // Too soon
|
||||
}
|
||||
|
||||
return true // Go for it
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user