tmagent

package
v8.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 21, 2024 License: Apache-2.0, BSD-2-Clause, BSD-3-Clause, + 1 more Imports: 27 Imported by: 0

Documentation

Index

Constants

View Source
const (
	TrafficCtl     = "traffic_ctl"
	ParentsFile    = "parent.config"
	StrategiesFile = "strategies.yaml"
)
View Source
const HealthSafetyRatio = 0.3 // TODO make configurable?

HealthSafetyRatio is the ratio of unhealthy parents after which no parents will be marked down.

This is a safety mechanism: if for any reason most or all parents are marked down, something is seriously wrong, possibly with the health code itself, and therefore don't mark any parents down,

View Source
const ParentHealthPollTypeInvalid = ParentHealthPollType("")
View Source
const ParentHealthPollTypeL4 = ParentHealthPollType("l4")
View Source
const ParentHealthPollTypeL7 = ParentHealthPollType("l7")
View Source
const ParentHealthVersion = "1.0"

Variables

View Source
var ParentServicePollTimeoutService = 2 * time.Second

ParentServicePollTimeoutService is the timeout for PollParent. TODO make configurable.

Functions

func NewParentHealthPtr

func NewParentHealthPtr() *util.AtomicPtr[ParentHealth]

NewParentHealthPtr is a convenience func for NewAtomicPtr(NewParentHealth()).

func NewParentServiceHealthPtr

func NewParentServiceHealthPtr() *util.AtomicPtr[ParentServiceHealth]

NewParentServiceHealthPtr is a convenience func for NewAtomicPtr(NewParentServiceHealth()).

func StartParentHealthPoller

func StartParentHealthPoller(pi *ParentInfo, numWorkers int, pollInterval time.Duration, pollType ParentHealthPollType, updateHealthSignal func()) (chan<- struct{}, error)

StartParentHealthPoller polls parents for health every pollInterval. Returns a done channel, which will terminate the polling loop when written to.

func StartParentServiceHealthPoller

func StartParentServiceHealthPoller(pi *ParentInfo, numWorkers int, pollInterval time.Duration, updateHealthSignal func()) chan<- struct{}

StartParentServiceHealthPoller polls parents for health every pollInterval. Note only parents which are caches are polled. Returns a done channel, which will terminate the polling loop when written to.

func StartTrafficMonitorHealthPoller

func StartTrafficMonitorHealthPoller(pi *ParentInfo, updateHealthSignal func()) chan<- struct{}

StartTrafficMonitorHealthPoller The main polling function that keeps the parents list current if with any changes to the trafficserver 'parent.config' or 'strategies.yaml'. Also, it keeps parent status current with the the trafficserver HostStatus subsystem. Finally, on each poll cycle a trafficmonitor is queried to check that all parents used by this trafficserver are available for use based upon the trafficmonitors idea from it's health protocol. Parents are marked up or down in the trafficserver subsystem based upon that hosts current status and the status that trafficmonitor health protocol has determined for a parent.

Types

type FailOver

type FailOver struct {
	MaxSimpleRetries      int      `yaml:"max_simple_retries,omitempty"`
	MaxUnavailableRetries int      `yaml:"max_unavailable_retries,omitempty"`
	RingMode              string   `yaml:"ring_mode,omitempty"`
	ResponseCodes         []int    `yaml:"response_codes,omitempty"`
	MarkDownCodes         []int    `yaml:"markdown_codes,omitempty"`
	HealthCheck           []string `yaml:"health_check,omitempty"`
}

when reading the 'strategies.yaml', these fields are used to help parse out fail_over objects.

type Host

type Host struct {
	HostName  string     `yaml:"host"`
	Protocols []Protocol `yaml:"protocol"`
}

the fields used from 'strategies.yaml' that describe a parent.

type MarkdownServer

type MarkdownServer struct {
	// Shutdown signals the MarkdownService to stop its goroutines and release all resources.
	//
	// It is not buffered. Writes will block until the markdown service is done with any
	// ongoing markdown operation. Once a write returns, the MarkdownService will begin
	// shutdown.
	// TODO: add signal to callers when shutdown has finished.
	Shutdown chan<- struct{}

	// UpdateHealth signals to the markdown service that health status has changed, and it should process markdowns again.
	UpdateHealth func()
}

MarkdownServer contains symbols for manipulating a running MarkdownService started by StartMarkdownService.

func StartMarkdownService

func StartMarkdownService(pi *ParentInfo, pollInterval time.Duration) *MarkdownServer

type ParentHealth

type ParentHealth struct {
	// Version is the direct version of this parent health, which applies to
	// direct RecursiveParentHealth which are ParentHealth.
	//
	// This does not apply to RecursiveParentHealth which are ParentServiceHealth;
	// rather, their own Version applies.
	//
	// Note this is the version of the service sending the result, not the service doing the polling.
	Version string `json:"version"`

	// Since is the RFC3339Nano-formatted time that this health result was polled.
	// Note this is the time of the service doing the polling, not the service sending the result.
	Since string `json:"since"`

	ParentHealthPollResults map[string]ParentHealthPollResult `json:"parent_health_poll_results"`
}

func DeserializeParentHealth

func DeserializeParentHealth(bts []byte) (*ParentHealth, error)

DeserializeParentHealth deserializes the ParentHealth from network or disk output, as previously serialized with Serialize.

func NewParentHealth

func NewParentHealth() *ParentHealth

func (*ParentHealth) Serialize

func (ph *ParentHealth) Serialize(prettyPrint bool) ([]byte, error)

Serialize serializes the ParentHealth for network or disk output.

type ParentHealthPollResult

type ParentHealthPollResult struct {
	Healthy bool `json:"healthy"`
	// UnhealthyReason is a human-readable string as to why the parent was unhealthy.
	// This will be empty if Healthy is true.
	UnhealthyReason string `json:"unhealthy_reason,omitempty"` // TODO rename to HealthChangeReason?

}

ParentHealthPollResult is the health data from polling a parent. This is currently just a boolean, but may include other data in the future.

type ParentHealthPollResultAndFQDN

type ParentHealthPollResultAndFQDN struct {
	ParentHealthPollResult
	ParentFQDN string
}

type ParentHealthPollType

type ParentHealthPollType string

func ParentHealthPollTypeFromStr

func ParentHealthPollTypeFromStr(st string) ParentHealthPollType

func (ParentHealthPollType) String

func (pt ParentHealthPollType) String() string

type ParentHealthServer

type ParentHealthServer struct {
	// contains filtered or unexported fields
}

func NewParentHealthServer

func NewParentHealthServer(pi *ParentInfo, addr string, readTimeout time.Duration) *ParentHealthServer

func StartParentHealthService

func StartParentHealthService(pi *ParentInfo, port int, readTimeout time.Duration) *ParentHealthServer

StartParentHealthService is a helper function that calls NewParentHealthServer, runs ListenAndServe in a goroutine, and returns the ParentHealthServer. If ListenAndServe returns an error, it's logged to the error log.

func (*ParentHealthServer) ListenAndServe

func (sv *ParentHealthServer) ListenAndServe() error

func (*ParentHealthServer) ListenAndServeTLS

func (sv *ParentHealthServer) ListenAndServeTLS(certFile, keyFile string) error

func (*ParentHealthServer) ServeHTTP

func (sv *ParentHealthServer) ServeHTTP(w http.ResponseWriter, req *http.Request)

func (*ParentHealthServer) Shutdown

func (sv *ParentHealthServer) Shutdown(ctx context.Context) error

type ParentInfo

type ParentInfo struct {
	ParentDotConfig        util.ConfigFile
	StrategiesDotYaml      util.ConfigFile
	TrafficServerBinDir    string
	TrafficServerConfigDir string

	Cfg    *util.AtomicPtr[config.Cfg]
	TOData *util.AtomicPtr[TOData]

	TrafficMonitorHealth *util.AtomicPtr[TrafficMonitorHealth]
	ParentHealthL4       *util.AtomicPtr[ParentHealth]
	ParentHealthL7       *util.AtomicPtr[ParentHealth]
	ParentServiceHealth  *util.AtomicPtr[ParentServiceHealth]
	ParentHealthLog      io.WriteCloser

	MarkdownMethods map[config.HealthMethod]struct{}
	HealthMethods   map[config.HealthMethod]struct{}

	// ParentHostFQDNs maps hostnames to fqdns, of parents.
	// This is necessary because Traffic Monitor's CRStates API only maps hostnames to health,
	// which is mostly okay for CDN caches; but we can't key on hostname anywhere else, because hostnames for non-cache parents aren't unique or meaningful.
	// So, we key on FQDN everywhere, and this mapping is used to map TM hostnames to their FQDNs.
	//
	// Don't use this for anything that includes non-cache (origin) servers.
	// Hostnames for any servers but caches are not unique and cannot be used as keys.
	ParentHostFQDNs util.SyncMap[string, string]
	// contains filtered or unexported fields
}

ParentInfo contains the necessary data required to keep track of trafficserver config files, lists of parents a trafficserver instance uses, and directory locations used for configuration and trafficserver executables.

All AtomicPtr members MUST NOT be modified. All AtomicPtr members are accessed concurrently by multiple goroutines, and their objects must be atomically replaced by a single writer, and never modified.

func NewParentInfo

func NewParentInfo(cfgPtr *util.AtomicPtr[config.Cfg]) (*ParentInfo, error)

used at startup to load a trafficservers list of parents from it's 'parent.config', 'strategies.yaml' and current parent status from trafficservers HostStatus subsystem.

func (*ParentInfo) GetCacheParents

func (pi *ParentInfo) GetCacheParents() []string

GetCacheParents returns a list of parent FQDNs which are caches (as opposed to origins). See GetParents for concurrency and other details.

func (*ParentInfo) GetCacheStatuses

func (pi *ParentInfo) GetCacheStatuses() (tc.CRStates, error)

Queries a traffic monitor that is monitoring the trafficserver instance running on a host to obtain the availability, health, of a parent used by trafficserver.

func (*ParentInfo) GetParents

func (pi *ParentInfo) GetParents() []string

GetParents returns a list of parent FQDNs. The map of parents is not locked during execution, so if the map data is changed concurrently, whether or not changes are returned will be nondeterministic. It is safe for multiple goroutines.

func (*ParentInfo) GetTOData

func (pi *ParentInfo) GetTOData(cfg *config.Cfg) error

GetTOData fetches data needed from Traffic Ops and refreshes it in the ParentInfo object.

Note it takes a Config, even though ParentInfo has a AtomicPtr[Config], because callers typically need to atomically operate on a single Config. If a caller doesn't already have a Config, simply call pi.GetTOData(pi.Cfg.Get()).

func (*ParentInfo) LoadOrStoreParentStatus

func (pi *ParentInfo) LoadOrStoreParentStatus(fdqn string, status ParentStatus) (ParentStatus, bool)

LoadOrStoreParentStatus adds the given status if fqdn does not exist, and returns the existing value if it does exist. Returns true if the value was loaded, false if it was stored.

This behaves identical to sync.Map.LoadOrStore.

It is safe for multiple goroutines.

func (*ParentInfo) LoadParentStatus

func (pi *ParentInfo) LoadParentStatus(fqdn string) (ParentStatus, bool)

LoadParentStatus returns parent's status and whether the parent existed. It is safe for multiple goroutines.

func (*ParentInfo) StoreParentStatus

func (pi *ParentInfo) StoreParentStatus(fqdn string, st ParentStatus)

StoreParentStatus Sets a parent's status. It is safe for multiple goroutines.

func (*ParentInfo) UpdateParentInfo

func (pi *ParentInfo) UpdateParentInfo(cfg *config.Cfg) error

Used by the polling function to update the parents list from changes to 'parent.config' and 'strategies.yaml'. The parents availability is also updated to reflect the current state from the trafficserver HostStatus subsystem.

func (*ParentInfo) WritePollState

func (pi *ParentInfo) WritePollState() error

type ParentServiceHealth

type ParentServiceHealth struct {
	// Version is the direct version of this parent health, which applies to
	// direct RecursiveParentHealth which are ParentHealth.
	//
	// This does not apply to RecursiveParentHealth which are ParentServiceHealth;
	// rather, their own Version applies.
	Version string `json:"version"`

	ParentServiceHealthPollResults map[string]RecursiveParentHealth `json:"parent_service_health_poll_results"`

	// Since is the RFC3339Nano-formatted time that this health result was polled.
	// Note this is the time of the service doing the polling, not the service sending the result.
	Since time.Time `json:"since"`
}

ParentServiceHealth is the recursive parent health polled from other Parent Health Services.

Parents will be recursively polled. If a parent is a cache, its Parent Health Service will be polled and the result placed in its map key. If a parent is not a cache, its ordinary Parent Health will be placed in its map key. See StartParentHealthPoller.

func CombineParentHealth

func CombineParentHealth(parentHealthL4 *ParentHealth, parentHealthL7 *ParentHealth, parentServiceHealth *ParentServiceHealth) *ParentServiceHealth

CombineParentHealth takes a ParentHealth directly queried from the parent service (ATS or the Origin) and the ParentServiceHealth directly queried from the parent's HealthService, combines them, and returns a ParentServiceHealth with each direct parent's RecursiveParentHealth containing both the direct ParentHealth and the ParentServiceHealth.

If any parent exists in the direct ParentHealth but not ParentServiceHealth (which may be common, if cache parents aren't running the Health Service; and will always be true for origin parents), the direct parent will be inserted into the ParentServiceHealth.

If any parent exists in the ParentServiceHealth but not ParentHealth, that means the actual parent service (ATS or the Origin) was unreachable, even though the Parent Health Service was reachable. In which case, we don't want to ever consider that parent healthy, so it will not be included.

func DeserializeParentServiceHealth

func DeserializeParentServiceHealth(bts []byte) (*ParentServiceHealth, error)

DeserializeParentServiceHealth deserializes the ParentHealth from network or disk output, as previously serialized with Serialize.

func NewParentServiceHealth

func NewParentServiceHealth() *ParentServiceHealth

func (*ParentServiceHealth) Serialize

func (ph *ParentServiceHealth) Serialize(prettyPrint bool) ([]byte, error)

Serialize serializes the ParentServiceHealth for network or disk output.

type ParentServiceHealthErrFQDN

type ParentServiceHealthErrFQDN struct {
	Health RecursiveParentHealth
	Err    error
	FQDN   string
}

ParentServiceHealthErrFQDN contains the health, any error, and the parent fqdn. This is used to return on a result chan from a poll worker.

type ParentServiceHealthPollResult

type ParentServiceHealthPollResult struct {
	Healthy bool
	// UnhealthyReason is a human-readable string as to why the parent was unhealthy.
	// This will be empty if Healthy is true.
	UnhealthyReason string // TODO rename to HealthChangeReason?

}

ParentServiceHealthPollResult is the health data from polling a parent. This is currently just a boolean, but may include other data in the future. TODO delete

type ParentStatus

type ParentStatus struct {
	Fqdn                 string
	ActiveReason         bool
	LocalReason          bool
	ManualReason         bool
	LastTmPoll           int64
	UnavailablePollCount int
	MarkUpPollCount      int
}

ParentStatus contains the trafficserver 'HostStatus' fields that are necessary to interface with the trafficserver 'traffic_ctl' command.

func (ParentStatus) Status

func (p ParentStatus) Status() string

used to log that a parent's status is either UP or DOWN based upon the HostStatus reason codes. to be considered UP, all reason codes must be 'true'.

type Protocol

type Protocol struct {
	Scheme           string  `yaml:"scheme"`
	Port             int     `yaml:"port"`
	Health_check_url string  `yaml:"health_check_url,omitempty"`
	Weight           float64 `yaml:"weight,omitempty"`
}

the protocol object in 'strategies.yaml' that help to describe a parent.

type RecursiveParentHealth

type RecursiveParentHealth struct {
	ParentHealthL4      *ParentHealthPollResult `json:"parent_health_l4"`
	ParentHealthL7      *ParentHealthPollResult `json:"parent_health_l7"`
	ParentServiceHealth *ParentServiceHealth    `json:"parent_service_health"` // debug
}

RecursiveParentHealth is either a poll from a direct parent poll of a non-cache or a ParentServiceHealth from a parent service poll of a cache.

Either ParentHealth or ParentServiceHealth will not be nil, but never both.

This would be more elegant as an interface, but a struct with two pointers is easier to deserialize.

type StatusReason

type StatusReason int
const (
	ACTIVE StatusReason = iota
	LOCAL
	MANUAL
)

these are the HostStatus reason codes used within trafficserver.

func (StatusReason) String

func (s StatusReason) String() string

used for logging a parent's HostStatus reason code setting.

type Strategies

type Strategies struct {
	Strategy []Strategy    `yaml:"strategies"`
	Hosts    []Host        `yaml:"hosts"`
	Groups   []interface{} `yaml:"groups"`
}

the top level array defintions in a trafficserver 'strategies.yaml' configuration file.

type Strategy

type Strategy struct {
	Strategy        string   `yaml:"strategy"`
	Policy          string   `yaml:"policy"`
	HashKey         string   `yaml:"hash_key,omitempty"`
	GoDirect        bool     `yaml:"go_direct,omitempty"`
	ParentIsProxy   bool     `yaml:"parent_is_proxy,omitempty"`
	CachePeerResult bool     `yaml:"cache_peer_result,omitempty"`
	Scheme          string   `yaml:"scheme"`
	FailOvers       FailOver `yaml:"failover,omitempty"`
}

a trafficserver strategy object from 'strategies.yaml'.

type TOData

type TOData struct {
	UserAgent string
	TOClient  *toclient.Session
	Monitors  map[string]struct{} `json:"trafficmonitors,omitempty"` // set[fqdn]
	Caches    map[string]struct{} `json:"caches,omitempty"`          // set[fqdn]
}

TOData is the Traffic Ops data needed by various services.

func NewTOData

func NewTOData(userAgent string) *TOData

func (*TOData) Clone

func (td *TOData) Clone() *TOData

Clone copies the TOData into a new object. Note the TOClient, which is safe for use by multiple goroutines, is not copied.

type TrafficMonitorHealth

type TrafficMonitorHealth struct {
	// PollTime is the local time this TM health was obtained
	PollTime      time.Time
	CacheStatuses map[tc.CacheName]tc.IsAvailable
}

func NewTrafficMonitorHealth

func NewTrafficMonitorHealth() *TrafficMonitorHealth

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL