Skip to content

Commit

Permalink
Removed anycast functionality from traffic control (#7877)
Browse files Browse the repository at this point in the history
* Removed anycast functionality from traffic control (#62)

* removed anycast functionality from traffic control

* added changelog for pr

* corrected formatting in traffic_monitor/datareq/datareq.go

---------

Co-authored-by: serDrem <serega7@gmail.com>

* Updated changelog

---------

Co-authored-by: Dremin, Sergey (Principal SRE, CDN EngOps) <Sergey_Dremin@comcast.com>
Co-authored-by: serDrem <serega7@gmail.com>
  • Loading branch information
3 people authored Dec 4, 2023
1 parent fa231d7 commit 3710add
Show file tree
Hide file tree
Showing 18 changed files with 21 additions and 425 deletions.
1 change: 0 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
- [#7672](https://github.com/apache/trafficcontrol/pull/7672) *Traffic Control Health Client*: Added peer monitor flag while using `strategies.yaml`.
- [#7609](https://github.com/apache/trafficcontrol/pull/7609) *Traffic Portal*: Added Scope Query Param to SSO login.
- [#7450](https://github.com/apache/trafficcontrol/pull/7450) *Traffic Ops*: Removed hypnotoad section and added listen field to traffic_ops_golang section in order to simplify cdn config.
- [#7290](https://github.com/apache/trafficcontrol/pull/7302) *Traffic Monitor*: Update TM results with hostname from via header, syncronize health on caches with same service address.
- [#7291](https://github.com/apache/trafficcontrol/pull/7291) *Traffic Ops*: Extended Layered Profile feature to aggregate parameters for all server profiles.
- [#7314](https://github.com/apache/trafficcontrol/pull/7314) *Traffic Portal*: Added capability feature to Delivery Service Form (HTTP, DNS).
- [#7295](https://github.com/apache/trafficcontrol/pull/7295) *Traffic Portal*: Added description and priority order for Layered Profile on server form.
Expand Down
1 change: 0 additions & 1 deletion docs/source/admin/traffic_monitor.rst
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ traffic_monitor.cfg
- ``health.polling.interval``
- ``peers.polling.interval``
- ``heartbeat.polling.interval``
- ``tm.sameipservers.enabled`` - When set to true, performs an AND operation on the availability statuses of servers with same ip. Any unavailable server(s) with same ip as other server(s) will cause the other server(s) to be set to unavailable.

Upon receiving this configuration, Traffic Monitor begins polling :term:`cache server` s. Once every :term:`cache server` has been polled, :ref:`health-proto` state is available via RESTful JSON endpoints and a web browser UI.

Expand Down
5 changes: 0 additions & 5 deletions docs/source/glossary.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,6 @@ Glossary
- :term:`forward proxy`: Used by Traffic Control for Mid-tier :dfn:`cache servers`.
- transparent proxy: These are not used by Traffic Control. If you are interested you can learn more about transparent proxies on `wikipedia <http://en.wikipedia.org/wiki/Proxy_server#Transparent_proxy>`_.

anycast group
Anycast group
Anycast Group
A group of caching HTTP proxy servers that have the same service address that is equal cost multi path routed at the last hop

Cache Group
Cache Groups
A group of caching HTTP proxy servers that together create a combined larger cache using consistent hashing. Traffic Router treats all servers in a :dfn:`Cache Group` as though they are in the same geographic location, though they are in fact only in the same general area. A :dfn:`Cache Group` has one single set of geographical coordinates even if the :term:`cache servers` that make up the :dfn:`Cache Group` are actually in :term:`Physical Locations`. The :term:`cache servers` in a :dfn:`Cache Group` are not aware of the other :term:`cache servers` in the group - there is no clustering software or communications between :term:`cache servers` in a :dfn:`Cache Group`.
Expand Down
4 changes: 0 additions & 4 deletions docs/source/overview/traffic_monitor.rst
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,3 @@ The optimistic quorum prevents invalid state propagation caused by a Traffic Mon
Protocol Engagement
-------------------
Short polling intervals of both the :term:`cache servers` and Traffic Monitor peers help to reduce customer impact of outages. It is not uncommon for a :term:`cache server` to be marked unavailable by Traffic Monitor - in fact, it is business as usual for many CDNs. Should a widely requested video asset cause a single :term:`cache server` to get close to its interface capacity, the Health Protocol will "kick in," and Traffic Monitor marks the :term:`cache server` as unavailable. New clients want to see the same asset, and now :ref:`tr-overview` will send these customers to another :term:`cache server` in the same :term:`Cache Group`. The load is now shared between the two :term:`cache servers`. As clients finish watching the asset on the overloaded :term:`cache server`, it will drop below the threshold and gets marked available again, and new clients will begin to be directed to it once more. It is less common for a :term:`Delivery Service` to be marked unavailable by Traffic Monitor. The :term:`Delivery Service` thresholds are usually used for overflow situations at extreme peaks to protect other :term:`Delivery Services` in the CDN from being impacted.

Handling Cache Servers with Same Service IP
-------------------------------------------
Traffic Monitor is able to direct Traffic Router to route traffic to groups of :term:`cache servers` with the same service IP address, but not to an individual :term:`cache server` within that group. To monitor :term:`cache servers` within that group, HTTP :mailheader:`Keep-Alive` header is omitted with the ``health.polling.keepalive`` and ``stat.polling.keepalive`` Traffic Monitor :term:`profile` :term:`parameters` so that the Traffic Monitor source port changes for those connections and the Traffic Monitor can get to all the :term:`cache servers` within that group via `ECMP <https://en.wikipedia.org/wiki/Equal-cost_multi-path_routing>`(Equal Cost Multi Path). ECMP rules govern routing to destinations with equal cost. Changing the source port ensures all the routes to :term:`cache servers` within an ECMP group are taken. Then Traffic Monitor updates the responses using the :mailheader:`Via` header. In the event of :dfn:`Health Protocol` determining the overall health of one of the :term:`cache servers` in an anycast group by evaluating network throughput and load against values configured in :ref:`to-overview` to exceed their limit, it declares the whole groups as unhealthy.
1 change: 0 additions & 1 deletion lib/go-rfc/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ const (
Age = "Age" // RFC7234§5.1
Location = "Location" // RFC7231§7.1.2
Authorization = "Authorization" // RFC7235§4.2
Via = "Via" // RFC3261§8.1.1.7
Cookie = "Cookie" // RFC7873
)

Expand Down
1 change: 0 additions & 1 deletion lib/go-tc/crstates.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ type IsAvailable struct {
DirectlyPolled bool `json:"-"`
Status string `json:"status"`
LastPoll time.Time `json:"lastPoll"`
LastPollV6 time.Time `json:"lastPollV6"`
}

// NewCRStates creates a new CR states object, initializing pointer members.
Expand Down
18 changes: 0 additions & 18 deletions traffic_monitor/cache/astats.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,17 @@ import (
"errors"
"fmt"
"io"
"regexp"
"strings"

"github.com/apache/trafficcontrol/v8/lib/go-log"
"github.com/apache/trafficcontrol/v8/lib/go-rfc"
"github.com/apache/trafficcontrol/v8/traffic_monitor/dsdata"
"github.com/apache/trafficcontrol/v8/traffic_monitor/poller"
"github.com/apache/trafficcontrol/v8/traffic_monitor/todata"

jsoniter "github.com/json-iterator/go"
)

func init() {
registerDecoder("astats", astatsParse, astatsPrecompute)
hostnameRegex = regexp.MustCompile(`(?:http|https)/\d+\.\d+ ([A-Za-z0-9\-]{0,61})`)
}

// AstatsSystem represents fixed system stats returned from the
Expand Down Expand Up @@ -120,22 +116,8 @@ func astatsParse(cacheName string, rdr io.Reader, pollCTX interface{}) (Statisti
astats.Ats["system.proc.loadavg"] = astats.System.ProcLoadavg
astats.Ats["system.proc.net.dev"] = astats.System.ProcNetDev

via := ctx.HTTPHeader.Get(rfc.Via)
if via != "" {
viaRegexSubmatch := hostnameRegex.FindStringSubmatch(via)
if len(viaRegexSubmatch) > 0 {
astats.Ats[rfc.Via] = viaRegexSubmatch[1]
}
}
return stats, astats.Ats, nil
} else if ctype == "text/csv" {
via := ctx.HTTPHeader.Get(rfc.Via)
if via != "" {
viaRegexSubmatch := hostnameRegex.FindStringSubmatch(via)
if len(viaRegexSubmatch) > 0 {
cacheName = viaRegexSubmatch[1]
}
}
return astatsCsvParseCsv(cacheName, rdr)
} else {
return stats, nil, fmt.Errorf("stats Content-Type (%s) can not be parsed by astats", ctype)
Expand Down
3 changes: 0 additions & 3 deletions traffic_monitor/cache/astats_csv.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import (
"strings"

"github.com/apache/trafficcontrol/v8/lib/go-log"
"github.com/apache/trafficcontrol/v8/lib/go-rfc"
)

type astatsDataCsv struct {
Expand Down Expand Up @@ -129,7 +128,5 @@ func astatsCsvParseCsv(cacheName string, data io.Reader) (Statistics, map[string
return stats, nil, fmt.Errorf("cache '%s' had no interfaces", cacheName)
}

statMap[rfc.Via] = cacheName

return stats, statMap, nil
}
8 changes: 0 additions & 8 deletions traffic_monitor/cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,10 @@ package cache
*/

import (
"fmt"
"io"
"regexp"
"time"

"github.com/apache/trafficcontrol/v8/lib/go-log"
"github.com/apache/trafficcontrol/v8/lib/go-rfc"
"github.com/apache/trafficcontrol/v8/lib/go-tc"
"github.com/apache/trafficcontrol/v8/traffic_monitor/todata"
)
Expand All @@ -37,8 +34,6 @@ type Handler struct {
ToData *todata.TODataThreadsafe
}

var hostnameRegex *regexp.Regexp

func (h Handler) ResultChan() <-chan Result {
return h.resultChan
}
Expand Down Expand Up @@ -316,9 +311,6 @@ func (handler Handler) Handle(id string, rdr io.Reader, format string, reqTime t
}
result.Time = time.UnixMilli(int64(valInt))
}
if value, ok := miscStats[rfc.Via]; ok {
result.ID = fmt.Sprintf("%v", value)
}

result.Statistics = stats
result.Miscellaneous = miscStats
Expand Down
4 changes: 0 additions & 4 deletions traffic_monitor/cache/data.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,6 @@ type AvailableStatus struct {
UnavailableStat string
// Poller is the name of the poller which set this availability status.
Poller string
// Time of last poll
LastPoll time.Time
// Time of v6 last poll
LastPollV6 time.Time
}

// CacheAvailableStatuses is the available status of each cache.
Expand Down
13 changes: 0 additions & 13 deletions traffic_monitor/cache/stats_over_http.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,10 @@ import (
"fmt"
"io"
"math"
"regexp"
"strconv"
"strings"

"github.com/apache/trafficcontrol/v8/lib/go-log"
"github.com/apache/trafficcontrol/v8/lib/go-rfc"
"github.com/apache/trafficcontrol/v8/traffic_monitor/poller"
"github.com/apache/trafficcontrol/v8/traffic_monitor/todata"

Expand All @@ -55,7 +53,6 @@ const LOADAVG_SHIFT = 65536

func init() {
registerDecoder("stats_over_http", statsOverHTTPParse, statsOverHTTPPrecompute)
hostnameRegex = regexp.MustCompile(`(?:http|https)/\d+\.\d+ ([A-Za-z0-9\-]{0,61})`)
}

type stats_over_httpData struct {
Expand All @@ -74,14 +71,6 @@ func statsOverHTTPParse(cacheName string, data io.Reader, pollCTX interface{}) (

ctx := pollCTX.(*poller.HTTPPollCtx)

via := ctx.HTTPHeader.Get(rfc.Via)
if via != "" {
viaRegexSubmatch := hostnameRegex.FindStringSubmatch(via)
if len(viaRegexSubmatch) > 0 {
cacheName = viaRegexSubmatch[1]
}
}

ctype := ctx.HTTPHeader.Get("Content-Type")

if ctype == "text/json" || ctype == "text/javascript" || ctype == "application/json" || ctype == "" {
Expand All @@ -105,8 +94,6 @@ func statsOverHTTPParse(cacheName string, data io.Reader, pollCTX interface{}) (

statMap := sohData.Global

statMap[rfc.Via] = cacheName

if stats.Loadavg, err = parseLoadAvg(statMap); err != nil {
return stats, nil, fmt.Errorf("Error parsing loadavg for cache '%s': %v", cacheName, err)
}
Expand Down
77 changes: 13 additions & 64 deletions traffic_monitor/datareq/crstate.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,10 @@ import (
"fmt"
"net/http"
"net/url"
"strings"

"github.com/apache/trafficcontrol/v8/lib/go-log"
"github.com/apache/trafficcontrol/v8/lib/go-tc"
"github.com/apache/trafficcontrol/v8/traffic_monitor/health"
"github.com/apache/trafficcontrol/v8/traffic_monitor/peer"
"github.com/apache/trafficcontrol/v8/traffic_monitor/threadsafe"
"github.com/apache/trafficcontrol/v8/traffic_monitor/todata"
)

func srvTRState(
Expand All @@ -39,13 +35,11 @@ func srvTRState(
combinedStates peer.CRStatesThreadsafe,
peerStates peer.CRStatesPeersThreadsafe,
distributedPollingEnabled bool,
toData todata.TODataThreadsafe,
monitorConfig threadsafe.TrafficMonitorConfigMap,
) ([]byte, int, error) {
_, raw := params["raw"] // peer polling case
_, local := params["local"] // distributed peer polling case
if raw {
data, err := srvTRStateData(localStates, distributedPollingEnabled, toData, monitorConfig)
data, err := srvTRStateSelf(localStates, distributedPollingEnabled)
return data, http.StatusOK, err
}

Expand All @@ -64,11 +58,19 @@ func srvTRState(
}
}

data, err := srvTRStateData(combinedStates, local && distributedPollingEnabled, toData, monitorConfig)
data, err := srvTRStateDerived(combinedStates, local && distributedPollingEnabled)

return data, http.StatusOK, err
}

func srvTRStateDerived(combinedStates peer.CRStatesThreadsafe, directlyPolledOnly bool) ([]byte, error) {
if !directlyPolledOnly {
return tc.CRStatesMarshall(combinedStates.Get())
}
unfiltered := combinedStates.Get()
return tc.CRStatesMarshall(filterDirectlyPolledCaches(unfiltered))
}

func filterDirectlyPolledCaches(crstates tc.CRStates) tc.CRStates {
filtered := tc.CRStates{
Caches: make(map[tc.CacheName]tc.IsAvailable),
Expand All @@ -82,63 +84,10 @@ func filterDirectlyPolledCaches(crstates tc.CRStates) tc.CRStates {
return filtered
}

func srvTRStateData(localStates peer.CRStatesThreadsafe, directlyPolledOnly bool, toData todata.TODataThreadsafe, monitorConfig threadsafe.TrafficMonitorConfigMap) ([]byte, error) {
if val, ok := monitorConfig.Get().Config["tm.sameipservers.enabled"]; ok && val.(string) == "true" {
localStatesC := updateStatusSameIpServers(localStates, toData)
if !directlyPolledOnly {
return tc.CRStatesMarshall(localStatesC)
}
return tc.CRStatesMarshall(filterDirectlyPolledCaches(localStatesC))
}
func srvTRStateSelf(localStates peer.CRStatesThreadsafe, directlyPolledOnly bool) ([]byte, error) {
if !directlyPolledOnly {
return tc.CRStatesMarshall(localStates.Get())
}
return tc.CRStatesMarshall(filterDirectlyPolledCaches(localStates.Get()))
}

func updateStatusSameIpServers(localStates peer.CRStatesThreadsafe, toData todata.TODataThreadsafe) tc.CRStates {
localStatesC := localStates.Get()
toDataC := toData.Get()

for cache, _ := range localStatesC.Caches {
if _, ok := toDataC.SameIpServers[cache]; ok {
// all servers with same ip must be available if they are in reported state
allAvailableV4 := true
allAvailableV6 := true
allIsAvailable := true
for partner, _ := range toDataC.SameIpServers[cache] {
if partnerState, ok := localStatesC.Caches[partner]; ok {
// a partner host is reported but is marked down for exceeding a threshold
// this host also needs to be marked down to divert all traffic for their
// common ip
if strings.Contains(partnerState.Status, string(tc.CacheStatusReported)) &&
strings.Contains(partnerState.Status, health.TooHigh.String()) {
if !partnerState.Ipv4Available {
allAvailableV4 = false
}
if !partnerState.Ipv6Available {
allAvailableV6 = false
}
if !partnerState.IsAvailable {
allIsAvailable = false
}
if !allAvailableV4 && !allAvailableV6 && !allIsAvailable {
break
}
}
}
}
newIsAvailable := tc.IsAvailable{}
newIsAvailable.DirectlyPolled = localStatesC.Caches[cache].DirectlyPolled
newIsAvailable.Status = localStatesC.Caches[cache].Status
newIsAvailable.LastPoll = localStatesC.Caches[cache].LastPoll
newIsAvailable.LastPollV6 = localStatesC.Caches[cache].LastPollV6
newIsAvailable.IsAvailable = localStatesC.Caches[cache].IsAvailable && allIsAvailable
newIsAvailable.Ipv4Available = localStatesC.Caches[cache].Ipv4Available && allAvailableV4
newIsAvailable.Ipv6Available = localStatesC.Caches[cache].Ipv6Available && allAvailableV6

localStatesC.Caches[cache] = newIsAvailable
}
}
return localStatesC
unfiltered := localStates.Get()
return tc.CRStatesMarshall(filterDirectlyPolledCaches(unfiltered))
}
Loading

0 comments on commit 3710add

Please sign in to comment.