reconnx

package module
v1.0.2 Latest Latest
Warning

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

Go to latest
Published: Sep 23, 2021 License: MIT Imports: 5 Imported by: 0

README

reconnx - Reconnect pooled HTTP connections when they get slow (httpx plugin)

Build Status Go Report Card PkgGoDev

Package reconnx is a Go-language plugin for the httpx robust HTTP framework. The reconnx plugin closes pooled HTTP connections when they experience degraded performance, resulting in fresh replacement connections which may have substantially better performance.

Use Case: Web services often use a DNS load balancing system, such as Amazon Route53 or Azure Traffic Manager, to keep their DNS pointing at healthy hosts. But the default GoLang HTTP client pools HTTP connections, so old connections to bad hosts stay alive. The reconnx plugin closes these old connections when they start to perform badly, allowing your service to re-query DNS and shift over to healthy hosts.


Getting Started

Install reconnx:

$ go get github.com/gogama/reconnx

Configure the reconnx plugin on an httpx.Client to begin reconnecting bad connections:

package main

import (
	"github.com/gogama/httpx"
	"github.com/gogama/reconnx"
)

func main() {
	client := &httpx.Client{}
	reconnx.OnClient(client, reconnx.Config{
		Latency: reconnx.MachineConfig{
			// If the average time taken by "recent" requests to a particular
			// hostname is more than 1000.0 milliseconds, start closing
			// connections to that hostname.
			AbsThreshold: 1000.0,
			// If the average time taken by "recent" requests to a particular
			// hostname is more than 20.0% slower than the longer-term average
			// for that hostname, start closing connections to that hostname.
			PctThreshold: 20.0,
			// Stop closing connections for a specific hostname once 3 in a row
			// have been closed, or once 5 have been closed in total, whichever
			// happens first.
			ClosingStreak: 3,
			ClosingCount:  5,
		},
	})

	// Use the httpx HTTP client.
	// ...
	// ...
}

License

This project is licensed under the terms of the MIT License.

Acknowledgements

Developer happiness on this project was boosted by JetBrains' generous donation of an open source license for their lovely GoLand IDE. ❤

Documentation

Overview

Package reconnx dynamically closes connections to slow hosts, improving HTTP performance for the httpx library's robust HTTP client. See https://github.com/gogama/httpx.

Use the OnClient function to install reconnx in any httpx.Client:

cl := &httpx.Client{}           // Create robust HTTP client
cfg := reconnx.Config{
	Latency: reconnx.MachineConfig{
		AbsThreshold:   1500.0, // Close conns to host if recent latency > 1500ms
		PctThreshold:   200.0,  // Close conns to host if recent latency > 200% of historical
		ClosingStreak:  5,      // Stop closing conns to host once 5 in a row were closed...
		ClosingCount:   20,     // ...OR... Stop closing conns to host once 20 in total were closed
	},
}
reconnx.OnClient(cl, cfg)       // Install reconnx plugin

If you need to install reconnx directly onto an httpx.HandlerGroup, use the OnHandlers function.

Index

Constants

View Source
const (
	// DefaultHistoricalSamples is the default value used for number of
	// historical samples if the HistoricalSamples field of a
	// MachineConfig is zero.
	DefaultHistoricalSamples = 10

	// DefaultRecentSamples is the default value used for number of
	// recent samples if the RecentSamples field of a MachineConfig is
	// zero.
	DefaultRecentSamples = 3
)

Variables

This section is empty.

Functions

func OnClient

func OnClient(client *httpx.Client, config Config) *httpx.Client

OnClient installs the reconnx plugin onto an httpx.Client.

If client's current handler group is nil, OnClient creates a new handler group, sets it as client's current handler group, and proceeds to install X-Ray support into the handler group. If the handler group is not nil, OnClient adds the reconnx plugin into the existing handler group. (Be aware of this behavior if you are sharing a handler group among multiple clients.)

func OnHandlers

func OnHandlers(handlers *httpx.HandlerGroup, config Config) *httpx.HandlerGroup

OnHandlers installs the reconnx plugin onto an httpx.HandlerGroup.

The handler group may not be nil - if it is, a panic will ensue.

Types

type Config

type Config struct {
	// Logger is the logger where the plugin reports errors and
	// interesting events. If nil, the NopLogger is used.
	Logger Logger

	// Latency specifies when to close connections to a host due to
	// latency experienced in sending requests to that host.
	//
	// The unit Latency is milliseconds, so the AbsThreshold field must
	// be specified in milliseconds.
	//
	// Note that the zero value will result in connections never being
	// closed. At a minimum, the AbsThreshold, ClosingStreak, and
	// ClosingCount members should be set to positive values.
	Latency MachineConfig
}

Config describes how to configure the reconnx plugin.

type Logger

type Logger interface {
	// Printf prints a message to the Logger. Arguments are handled in
	// the manner of fmt.Printf.
	Printf(format string, v ...interface{})
}

Logger allows the reconnx plugin to log state changes and other information about plugin operation. The interface is compatible with the Go standard log.Logger.

Implementations of Logger must be safe for concurrent use by multiple goroutines.

type Machine

type Machine interface {
	// State reports the current state of the state machine.
	State() State

	// Next receives a new data point into the state machine and returns
	// the next and previous states.
	//
	// The new data point consists of a value and a closed flag. The
	// value is averaged with other recent values and checked against
	// the MachineConfig's absolute and percent thresholds. The closed
	// flag indicates whether the HTTP connection that generated the
	// value was closed.
	//
	// If the new data point did cause not a state transition, the next
	// state is equal to the previous state.
	Next(value float64, closed bool) (next State, prev State)
}

A Machine is a simple generic state machine for deciding whether to close connections.

The state machine can be used independently of the plugin itself and thus both the Machine interface and the NewMachine function are exported.

func NewMachine

func NewMachine(config MachineConfig) Machine

NewMachine constructs a new Machine with the given configuration.

type MachineConfig

type MachineConfig struct {
	// HistoricalSamples is the number of samples to include in the
	// historical average. If zero, DefaultHistoricalSamples is used.
	HistoricalSamples uint

	// RecentSamples is the number of samples to include in the recent
	// average. If zero, DefaultRecentSamples is used.
	RecentSamples uint

	// AbsThreshold specifies the absolute value threshold for closing
	// connections. If the recent average is greater than AbsThreshold,
	// the Machine will transition to the Closing state.
	//
	// If AbsThreshold is zero or negative, there is no absolute
	// threshold and the absolute value of the recent average will not
	// cause the Machine to transition to the Closing state.
	//
	// Note that if AbsThreshold is positive, the Machine's Next method
	// clamps to AbsThreshold (AbsThreshold is the maximum possible
	// value) before including them in the recent or historical average.
	// This prevents a single outlier value from skewing the recent or
	// historical averages. This clamping behavior also affects the
	// percentage calculation if both AbsThreshold and PctThreshold are
	// positive, but does not affect it if AbsThreshold is zero or
	// negative.
	AbsThreshold float64

	// PctThreshold specifies the percentage threshold for closing
	// connections. If the recent average is at least PctThreshold %
	// greater than the historical average, the Machine will transition
	// to the Closing state.
	//
	// If PctThreshold is zero or negative, there is no percentage
	// threshold and a percentage increase of the recent average over
	// the historical average will not cause the Machine to transition
	// to the Closing state.
	//
	// The Units for PctThreshold are "percentage points". Therefore the
	// value 1.0 represents a 1% increase, 20.0 represents a 20%
	// increase, and 120.0 represents a 120% increase.
	//
	// The percentage calculation can be affected by the AbsThreshold
	// value in the following way. If AbsThreshold is positive, then
	// all new values are clamped to AbsThreshold before being included
	// in the average. This prevents outliers from skewing the averages,
	// as this can cause legitimate anomalies to be missed.
	PctThreshold float64

	// ClosingStreak specifies the number of consecutive HTTP connections
	// that must be closed in order to transition out of the Closing
	// state.
	//
	// If this value is zero, the Machine will never enter the Closing
	// state.
	//
	// Even if the closing streak is not reached, the Machine will
	// transition out of the Closing state if the total closed
	// connection count (ClosingCount) is reached first.
	ClosingStreak uint

	// ClosingCount specifies the number of total (not necessarily
	// consecutive) HTTP connections that must be closed in order to
	// transition out of the Closing state.
	//
	// If this value is zero, the Machine will never enter the Closing
	// state.
	//
	// The Machine may transition out of the Closing state before the
	// closed connection count reaches ClosingCount if the closed
	// connection streak (ClosingStreak) is reached first.
	ClosingCount uint

	// RestingCount specifies the number of data points for which the
	// machine should "rest" in the Resting state after transitioning
	// out of the Closing state, and before transitioning back to either
	// Watching or Closing.
	//
	// If this value is zero, the Machine will never enter the Resting
	// state.
	//
	// The purpose of this value is to help prevent "infinite loop"
	// cases where persistent bad performance results in every
	// connection being closed all the time. Since HTTP connection setup
	// isn't free, and the TLS handshake required for HTTPS connections
	// is CPU-intensive both for the client and the server, the Resting
	// state exists as a circuit breaker to help prevent brownout
	// scenarios when a remote host is having a bad day.
	RestingCount uint
}

A MachineConfig specifies how to configure a new Machine.

type NopLogger

type NopLogger struct{}

NopLogger implements the Logger interface but ignores all messages sent to it. Use NopLogger if you are not interested in receiving updates about plugin operation.

func (NopLogger) Printf

func (NopLogger) Printf(string, ...interface{})

type State

type State int

A State represents the current state of a Machine.

const (
	// Watching indicates that a Machine is actively watching new data,
	// evaluating whether it should transition to the Closing state.
	Watching State = iota

	// Closing indicates that a Machine is actively closing connections,
	// and may transition to the Resting or Watching states.
	Closing

	// Resting indicates that a Machine is in a resting period where it
	// passively accumulates new data but does not change states. Once
	// the resting period is over, the machine will transition either to
	// the Watching state, if the data are good, or the Closing state,
	// if the data indicate connections should be closed.
	Resting
)

func (State) String

func (s State) String() string

Jump to

Keyboard shortcuts

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