http_lb

package module
v0.0.0-...-d8c09a4 Latest Latest
Warning

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

Go to latest
Published: Feb 27, 2024 License: MIT Imports: 11 Imported by: 0

README

HTTP Load Balancer

A lightweight, extensible Go-based load balancer with extensibility, robust configurability, seamless scalability, and integrated health checks, ensuring optimal performance and reliability for high-demand applications.

Features

  • Configuration Flexibility: Easily configurable through YAML files, enabling fine-tuning of load balancing behavior to suit specific requirements.
  • Efficient Containerization: Fully containerized with Docker, ensuring seamless deployment and portability across diverse environments.
  • Simplified Execution: Streamlined execution with a user-friendly Makefile, facilitating straightforward setup and operation.
  • Versatile Load Balancing: Supports a wide array of static load balancing algorithms, providing flexibility to optimize traffic distribution.
  • Extensibility: Built with extensibility in mind, allowing for easy extension and customization of each component to adapt to evolving needs.
  • Robust Health Monitoring: Empowered with built-in health checks, ensuring continuous monitoring of backend server health for enhanced reliability.
  • Enhanced Monitoring Capabilities: Equipped with comprehensive logging features, making it well-suited for integration with monitoring tools to track performance metrics and diagnose issues effectively.

Usage

Requirements
  • Make
  • Docker
Steps:
  1. Copy the config.yaml and configure it.
  2. Run it using make run
    If you are on a development server, Be cautious and run it using make run_dev
  3. That's it :)

Configuration

Here is the sample configuration file in YAML (available at config.yaml):

algorithm: round-robin
log_level: debug

frontend:
  listen: 0.0.0.0:8000
  tls:
    cert: cert.ctr
    key: key.key

backend:
backend:
  servers:
    - http://127.0.0.1:5001
    - http://127.0.0.1:5002
  timeout: 1s # ms, s, min, h
  keep_alive:
    max_idle_connections: 100 # 0 means no limit
    idle_connection_timeout: 30s # maximum amount of time an idle connection will remain idle before closing itself. (0 means no limit)

health_check:
  endpoint: /health_check
  expected_status_code: 200 # HTTP Status codes like 200 or 304
  interval: 10s # ms, s, min, h
  timeout: 2s
  • algorithm: Determines the backend selection method for client connections. Available options include:
    • Round-robin (round-robin)
    • Sticky round-robin (sticky-round-robin)
    • URL Hash (url-hash)
    • IP Hash (ip-hash)
    • Random (random)
      If you want to know how they work, read this article HERE
  • log_level: Sets the logging level for monitoring purposes. Options range from info to debug.
  • frontend: It's responsible for accepting the incoming requests
    • listen: Specifies the IP and port for the HTTP server to listen on. \
    • OPTIONAL (Recommended) tls: If you want the front-end only accepts tls requests. Also, don't forget to uncomment the line to map the tls files to container using volumes in Makefile
      • cert: The path to the certificate file.
      • key: The path to the private key file.
  • backend: The most important field. You define your backends in an array.
    • servers: An array of URLs of the backend servers.
    • timeout: Timeout for requests to the backend.
    • keep_alive: Keeping the connections alive to avoid create connection for each request.
      • max_idle_connections: Maximum number of idle connections (0 for no limit).
      • idle_connection_timeout: The maximum amount of time an idle connection will remain idle before closing itself. (0 means no limit)
  • health_check: Monitors backend health and adjusts routing accordingly.
    • endpoint: Path for the health check to verify backend availability.
    • expected_status_code: Expected HTTP status code indicating backend health.
    • interval: Interval for checking backend health.
    • timeout: Timeout for health check requests.

Extensibility

HTTP-LB is designed with extensibility in mind, with every component built upon abstraction. This architecture enables seamless development and customization of each component for effortless integration and utilization.

  • Algorithms: Based on the LoadBalancingAlgorithm interface defined in definitions.go, allowing for easy implementation of custom load balancing algorithms to suit specific requirements.
  • Request Forwarder: This crucial component handles incoming requests from the frontend, invoking the selected algorithm and forwarding requests to the reverse proxy seamlessly.
  • Health Checker: Built upon the HealthChecker interface, ensuring continuous monitoring of backend server health for enhanced reliability.
    These components serve as the backbone of the load balancer, with additional components following similar abstraction principles for further extensibility. Explore definitions.go to discover more abstraction-based components ready for customization and expansion.

Contribution

Contributions to HTTP-LB are warmly welcomed. To contribute, please follow these steps:

  1. Fork the repository.
  2. Make your changes, ensuring clear and concise commit messages.
  3. Push your branch to your fork.
  4. Submit a pull request (PR) to the main repository, detailing the changes and any relevant information.
  5. Your PR will be reviewed, and upon approval, it will be merged into the main branch.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrServerExists             = errors.New("server already exists")
	ErrServerNotExists          = errors.New("server doesn't exist")
	ErrNoHealthyServerAvailable = errors.New("no healthy server is available")
)

Functions

func ContainsSlice

func ContainsSlice[T comparable](slice []T, target T) bool

func CopySlice

func CopySlice[T any](slice []T) []T

func Hash

func Hash(input string) uint

func RewriteURL

func RewriteURL(url *url.URL) func(*httputil.ProxyRequest)

func RewriteXForwarded

func RewriteXForwarded(p *httputil.ProxyRequest)

Types

type Forwarder

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

func NewForwarder

func NewForwarder(lbAlgo LoadBalancingAlgorithm, rpFactory ReverseProxyFactory, logger *zap.Logger) *Forwarder

func (*Forwarder) Forward

func (f *Forwarder) Forward(rw http.ResponseWriter, r *http.Request) error

type Frontend

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

func NewFrontend

func NewFrontend(listenAddr string, tls *TLSOptions, reqForwarder RequestForwarder, logger *zap.Logger) *Frontend

func (*Frontend) Handler

func (f *Frontend) Handler(rw http.ResponseWriter, r *http.Request)

func (*Frontend) Run

func (f *Frontend) Run() error

func (*Frontend) Shutdown

func (f *Frontend) Shutdown() error

type GracefulShutdown

type GracefulShutdown interface {
	Shutdown() error
}

type HashingAlgorithm

type HashingAlgorithm func(string) uint

type HealthCheck

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

func NewHealthCheck

func NewHealthCheck(endPoint string, interval time.Duration, serverPool ServerPool,
	expectedStatusCode int, client *http.Client, logger *zap.Logger) *HealthCheck

func (*HealthCheck) Run

func (h *HealthCheck) Run()

func (*HealthCheck) Shutdown

func (h *HealthCheck) Shutdown() error

type HealthChecker

type HealthChecker interface {
	Run()
}

type LoadBalancingAlgorithm

type LoadBalancingAlgorithm interface {
	SelectServer(Request) (string, error)
}

type RPFactory

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

func NewRPFactory

func NewRPFactory(transportFactory TransportFactory) *RPFactory

func (*RPFactory) Create

func (rp *RPFactory) Create(server string) (*httputil.ReverseProxy, error)

type Request

type Request struct {
	RemoteIP string
	URLPath  string
}

type RequestForwarder

type RequestForwarder interface {
	Forward(http.ResponseWriter, *http.Request) error
}

type ReverseProxyFactory

type ReverseProxyFactory interface {
	Create(string) (*httputil.ReverseProxy, error)
}

type Server

type Server struct {
	Address string
	Status  ServerStatus
}

type ServerPool

type ServerPool interface {
	RegisterServer(string) error
	UnregisterServer(string) error
	SetServerStatus(string, ServerStatus) error
	Servers() []Server
	HealthyServers() []string
	UnhealthyServers() []string
}

type ServerPoolImplementation

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

func NewServerPool

func NewServerPool(servers []string, logger *zap.Logger) *ServerPoolImplementation

func (*ServerPoolImplementation) HealthyServers

func (b *ServerPoolImplementation) HealthyServers() []string

func (*ServerPoolImplementation) RegisterServer

func (b *ServerPoolImplementation) RegisterServer(server string) error

func (*ServerPoolImplementation) Servers

func (b *ServerPoolImplementation) Servers() []Server

func (*ServerPoolImplementation) SetServerStatus

func (b *ServerPoolImplementation) SetServerStatus(server string, status ServerStatus) error

func (*ServerPoolImplementation) UnhealthyServers

func (b *ServerPoolImplementation) UnhealthyServers() []string

func (*ServerPoolImplementation) UnregisterServer

func (b *ServerPoolImplementation) UnregisterServer(server string) error

type ServerStatus

type ServerStatus int
const (
	Healthy ServerStatus = iota + 1
	Unhealthy
)

func (ServerStatus) String

func (s ServerStatus) String() string

type TLSOptions

type TLSOptions struct {
	CertFile string
	KeyFile  string
}

type TransFactory

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

func NewTransportFactory

func NewTransportFactory(timeout time.Duration, maxIdleConns int, idleConnsTimeout time.Duration) *TransFactory

func (*TransFactory) Create

func (t *TransFactory) Create() *http.Transport

type TransportFactory

type TransportFactory interface {
	Create() *http.Transport
}

Directories

Path Synopsis
cmd
cli

Jump to

Keyboard shortcuts

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