gubernator

package module
v0.4.1 Latest Latest
Warning

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

Go to latest
Published: Oct 29, 2019 License: Apache-2.0 Imports: 36 Imported by: 1

README

Gubernator

Gubernator is a distributed, high performance, cloud native and stateless rate limiting service.

Features of Gubernator
  • Gubernator evenly distributes rate limit requests across the entire cluster, which means you can scale the system by simply adding more nodes.
  • Gubernator doesn’t rely on external caches like memcache or redis, as such there is no deployment synchronization with a dependant service. This makes dynamically growing or shrinking the cluster in an orchestration system like kubernetes or nomad trivial.
  • Gubernator holds no state on disk, It’s configuration is passed to it by the client on a per-request basis.
  • Gubernator provides both GRPC and HTTP access to it’s API.
  • Can be run as a sidecar to services that need rate limiting or as a separate service.
  • Can be used as a library to implement a domain specific rate limiting service.
  • Supports optional eventually consistent rate limit distribution for extremely high throughput environments. (See GLOBAL behavior architecture.md)
  • Gubernator is the english pronunciation of governor in Russian, also it sounds cool.
Stateless configuration

Gubernator is stateless in that it doesn’t require disk space to operate. No configuration or cache data is ever synced to disk. This is because every request to gubernator includes the config for the rate limit. At first you might think this an unnecessary overhead to each request. However, In reality a rate limit config is made up of only 4, 64bit integers.

An example rate limit request sent via GRPC might look like the following

rate_limits:
    # Scopes the request to a specific rate limit
  - name: requests_per_sec
    # A unique_key that identifies this instance of a rate limit request
    unique_key: account_id=123|source_ip=172.0.0.1
    # The number of hits we are requesting
    hits: 1
    # The total number of requests allowed for this rate limit
    limit: 100
    # The duration of the rate limit in milliseconds
    duration: 1000
    # The algorithm used to calculate the rate limit  
    # 0 = Token Bucket
    # 1 = Leaky Bucket
    algorithm: 0
    # The behavior of the rate limit in gubernator.
    # 0 = BATCHING (Enables batching of requests to peers)
    # 1 = NO_BATCHING (Disables batching)
    # 2 = GLOBAL (Enable global caching for this rate limit)
    behavior: 0

An example response would be

rate_limits:
    # The status of the rate limit.  OK = 0, OVER_LIMIT = 1
  - status: 0,
    # The current configured limit
    limit: 10,
    # The number of requests remaining
    remaining: 7,
    # A unix timestamp in milliseconds of when the bucket will reset, or if 
    # OVER_LIMIT is set it is the time at which the rate limit will no 
    # longer return OVER_LIMIT.
    reset_time: 1551309219226,
    # Additional metadata about the request the client might find useful
    metadata:
      # This is the name of the coordinator that rate limited this request
      "owner": "api-n03.staging.us-east-1.mailgun.org:9041"
Rate limit Algorithm

Gubernator currently supports 2 rate limit algorithms.

  1. Token Bucket implementation starts with an empty bucket, then each Hit adds a token to the bucket until the bucket is full. Once the bucket is full, requests will return OVER_LIMIT until the reset_time is reached at which point the bucket is emptied and requests will return UNDER_LIMIT. This algorithm is useful for enforcing very bursty limits. (IE: Applications where a single request can add more than 1 hit to the bucket; or non network based queuing systems.) The downside to this implementation is that once you have hit the limit no more requests are allowed until the configured rate limit duration resets the bucket to zero.

  2. Leaky Bucket is implemented similarly to Token Bucket where OVER_LIMIT is returned when the bucket is full. However tokens leak from the bucket at a consistent rate which is calculated as duration / limit. This algorithm is useful for metering, as the bucket leaks allowing traffic to continue without the need to wait for the configured rate limit duration to reset the bucket to zero.

Performance

In our production environment, for every request to our API we send 2 rate limit requests to gubernator for rate limit evaluation, one to rate the HTTP request and the other is to rate the number of recipients a user can send an email too within the specific duration. Under this setup a single gubernator node fields over 2,000 requests a second with most batched responses returned in under 1 millisecond.

requests graph

Peer requests forwarded to owning nodes typically respond in under 30 microseconds.

peer requests graph

NOTE The above graphs only report the slowest request within the 1 second sample time. So you are seeing the slowest requests that gubernator fields to clients.

Gubernator allows users to choose non-batching behavior which would further reduce latency for client rate limit requests. However because of throughput requirements our production environment uses Behaviour=BATCHING with the default 500 microsecond window. In production we have observed batch sizes of 1,000 during peak API usage. Other users who don’t have the same high traffic demands could disable batching and would see lower latencies but at the cost of throughput.

API

All methods are accessed via GRPC but are also exposed via HTTP using the GRPC Gateway

Health Check

Health check returns unhealthy in the event a peer is reported by etcd or kubernetes as up but the server instance is unable to contact that peer via it's advertised address.

GRPC
rpc HealthCheck (HealthCheckReq) returns (HealthCheckResp)
HTTP
GET /v1/HealthCheck

Example response:

{
  "status": "healthy",
  "peer_count": 3
}
Get Rate Limit

Rate limits can be applied or retrieved using this interface. If the client makes a request to the server with hits: 0 then current state of the rate limit is retrieved but not incremented.

GRPC
rpc GetRateLimits (GetRateLimitsReq) returns (GetRateLimitsResp)
HTTP
POST /v1/GetRateLimits

Example Payload

{
    "requests":[
        {
            "name": "requests_per_sec",
            "unique_key": "account.id=1234",
            "hits": 1,
            "duration": 60000,
            "limit": 10
        }
    ]
}

Example response:

{
  "responses":[
    {
      "status": 0,
      "limit": "10",
      "remaining": "7",
      "reset_time": "1551309219226",
    }
  ]
}
Deployment

NOTE: Gubernator uses etcd or kubernetes to discover peers and establish a cluster. If you don't have either, the docker-compose method is the simplest way to try gubernator out.

Docker with existing etcd cluster
$ docker run -p 8081:81 -p 8080:80 -e GUBER_ETCD_ENDPOINTS=etcd1:2379,etcd2:2379 \
   thrawn01/gubernator:latest 
   
# Hit the API at localhost:8080 (GRPC is at 8081)
$ curl http://localhost:8080/v1/HealthCheck
Docker compose

The docker compose file includes a local etcd server and 2 gubernator instances

# Download the docker-compose file
$ curl -O https://raw.githubusercontent.com/mailgun/gubernator/master/docker-compose.yaml

# Edit the compose file to change the environment config variables
$ vi docker-compose.yaml

# Run the docker container
$ docker-compose up -d

# Hit the API at localhost:8080 (GRPC is at 8081)
$ curl http://localhost:8080/v1/HealthCheck
Kubernetes
# Download the kubernetes deployment spec
$ curl -O https://raw.githubusercontent.com/mailgun/gubernator/master/k8s-deployment.yaml

# Edit the deployment file to change the environment config variables
$ vi k8s-deployment.yaml

# Create the deployment (includes headless service spec)
$ kubectl create -f k8s-deployment.yaml
Configuration

Gubernator is configured via environment variables with an optional --config flag which takes a file of key/values and places them into the local environment before startup.

See the example.conf for all available config options and their descriptions.

Architecture

See architecture.md for a full description of the architecture and the inner workings of gubernator.

Documentation

Overview

Package gubernator is a generated protocol buffer package.

It is generated from these files:

gubernator.proto
peers.proto

It has these top-level messages:

GetRateLimitsReq
GetRateLimitsResp
RateLimitReq
RateLimitResp
HealthCheckReq
HealthCheckResp
GetPeerRateLimitsReq
GetPeerRateLimitsResp
UpdatePeerGlobalsReq
UpdatePeerGlobal
UpdatePeerGlobalsResp

Package gubernator is a reverse proxy.

It translates gRPC into RESTful JSON APIs.

Index

Constants

View Source
const (
	Millisecond = 1
	Second      = 1000 * Millisecond
	Minute      = 60 * Second
)
View Source
const (
	Healthy   = "healthy"
	UnHealthy = "unhealthy"
)

Variables

View Source
var Algorithm_name = map[int32]string{
	0: "TOKEN_BUCKET",
	1: "LEAKY_BUCKET",
}
View Source
var Algorithm_value = map[string]int32{
	"TOKEN_BUCKET": 0,
	"LEAKY_BUCKET": 1,
}
View Source
var Behavior_name = map[int32]string{
	0: "BATCHING",
	1: "NO_BATCHING",
	2: "GLOBAL",
}
View Source
var Behavior_value = map[string]int32{
	"BATCHING":    0,
	"NO_BATCHING": 1,
	"GLOBAL":      2,
}
View Source
var Status_name = map[int32]string{
	0: "UNDER_LIMIT",
	1: "OVER_LIMIT",
}
View Source
var Status_value = map[string]int32{
	"UNDER_LIMIT": 0,
	"OVER_LIMIT":  1,
}

Functions

func ContextWithStats

func ContextWithStats(ctx context.Context, stats *GRPCStats) context.Context

Returns a new `context.Context` that holds a reference to `GRPCStats`.

func FromTimeStamp

func FromTimeStamp(ts int64) time.Duration

Convert a unix millisecond timestamp to a time.Duration

func FromUnixMilliseconds

func FromUnixMilliseconds(ts int64) time.Time

func NewCache

func NewCache(maxSize int) *cache.LRUCache

New creates a new Cache with a maximum size

func RandomPeer

func RandomPeer(peers []string) string

Given a list of peers, return a random peer

func RandomString

func RandomString(n int) string

Return a random alpha string of 'n' length

func RegisterPeersV1Server

func RegisterPeersV1Server(s *grpc.Server, srv PeersV1Server)

func RegisterV1Handler

func RegisterV1Handler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error

RegisterV1Handler registers the http handlers for service V1 to "mux". The handlers forward requests to the grpc endpoint over "conn".

func RegisterV1HandlerClient

func RegisterV1HandlerClient(ctx context.Context, mux *runtime.ServeMux, client V1Client) error

RegisterV1HandlerClient registers the http handlers for service V1 to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "V1Client". Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "V1Client" doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in "V1Client" to call the correct interceptors.

func RegisterV1HandlerFromEndpoint

func RegisterV1HandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error)

RegisterV1HandlerFromEndpoint is same as RegisterV1Handler but automatically dials to "endpoint" and closes the connection when "ctx" gets done.

func RegisterV1Server

func RegisterV1Server(s *grpc.Server, srv V1Server)

func ToTimeStamp

func ToTimeStamp(duration time.Duration) int64

Convert a time.Duration to a unix millisecond timestamp

Types

type Algorithm

type Algorithm int32
const (
	// Token bucket algorithm https://en.wikipedia.org/wiki/Token_bucket
	Algorithm_TOKEN_BUCKET Algorithm = 0
	// Leaky bucket algorithm https://en.wikipedia.org/wiki/Leaky_bucket
	Algorithm_LEAKY_BUCKET Algorithm = 1
)

func (Algorithm) EnumDescriptor

func (Algorithm) EnumDescriptor() ([]byte, []int)

func (Algorithm) String

func (x Algorithm) String() string

type Behavior

type Behavior int32
const (
	// BATCHING is the default behavior. This enables batching requests which protects the
	// service from thundering herd. IE: When a service experiences spikes of unexpected high
	// volume requests.
	//
	// Using this option introduces a small amount of latency depending on
	// the `batchWait` setting. Defaults to around 500 Microseconds of additional
	// latency in low throughput situations. For high volume loads, batching can reduce
	// the overall load on the system substantially.
	Behavior_BATCHING Behavior = 0
	// Disables batching. Use this for super low latency rate limit requests when
	// thundering herd is not a concern but latency of requests is of paramount importance.
	Behavior_NO_BATCHING Behavior = 1
	// Enables Global caching of the rate limit. Use this if the rate limit applies globally to
	// all ingress requests. (IE: Throttle hundreds of thousands of requests to an entire
	// datacenter or cluster of http servers)
	//
	// Using this option gubernator will continue to use a single peer as the rate limit coordinator
	// to increment and manage the state of the rate limit, however the result of the rate limit is
	// distributed to each peer and cached locally. A rate limit request received from any peer in the
	// cluster will first check the local cache for a rate limit answer, if it exists the peer will
	// immediately return the answer to the client and asynchronously forward the aggregate hits to
	// the peer coordinator. Because of GLOBALS async nature we lose some accuracy in rate limit
	// reporting, which may result in allowing some requests beyond the chosen rate limit. However we
	// gain massive performance as every request coming into the system does not have to wait for a
	// single peer to decide if the rate limit has been reached.
	Behavior_GLOBAL Behavior = 2
)

func (Behavior) EnumDescriptor

func (Behavior) EnumDescriptor() ([]byte, []int)

func (Behavior) String

func (x Behavior) String() string

type BehaviorConfig

type BehaviorConfig struct {
	// How long we should wait for a batched response from a peer
	BatchTimeout time.Duration
	// How long we should wait before sending a batched request
	BatchWait time.Duration
	// The max number of requests we can batch into a single peer request
	BatchLimit int

	// How long a non-owning peer should wait before syncing hits to the owning peer
	GlobalSyncWait time.Duration
	// How long we should wait for a global sync responses from peers
	GlobalTimeout time.Duration
	// The max number of global updates we can batch into a single peer request
	GlobalBatchLimit int
}

type Collector

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

Implements the Prometheus collector interface. Such that when the /metrics handler is called this collector pulls all the stats from

func NewGRPCStatsHandler

func NewGRPCStatsHandler() *Collector

func (*Collector) Close

func (c *Collector) Close()

func (*Collector) HandleConn

func (c *Collector) HandleConn(ctx context.Context, s stats.ConnStats)

func (*Collector) HandleRPC

func (c *Collector) HandleRPC(ctx context.Context, s stats.RPCStats)

func (*Collector) TagConn

func (*Collector) TagRPC

func (c *Collector) TagRPC(ctx context.Context, tagInfo *stats.RPCTagInfo) context.Context

type Config

type Config struct {
	// Required
	GRPCServer *grpc.Server

	// (Optional) Adjust how gubernator behaviors are configured
	Behaviors BehaviorConfig

	// (Optional) The cache implementation
	Cache cache.Cache

	// (Optional) This is the peer picker algorithm the server will use decide which peer in the cluster
	// will coordinate a rate limit
	Picker PeerPicker
}

config for a gubernator instance

func (*Config) SetDefaults

func (c *Config) SetDefaults() error

type ConsistantHash

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

Implements PeerPicker

func NewConsistantHash

func NewConsistantHash(fn HashFunc) *ConsistantHash

func (*ConsistantHash) Add

func (ch *ConsistantHash) Add(peer *PeerClient)

Adds a peer to the hash

func (*ConsistantHash) Get

func (ch *ConsistantHash) Get(key string) (*PeerClient, error)

Given a key, return the peer that key is assigned too

func (*ConsistantHash) GetPeerByHost

func (ch *ConsistantHash) GetPeerByHost(host string) *PeerClient

Returns the peer by hostname

func (*ConsistantHash) New

func (ch *ConsistantHash) New() PeerPicker

func (*ConsistantHash) Peers

func (ch *ConsistantHash) Peers() []*PeerClient

func (*ConsistantHash) Size

func (ch *ConsistantHash) Size() int

Returns number of peers in the picker

type EtcdPool

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

func NewEtcdPool

func NewEtcdPool(conf EtcdPoolConfig) (*EtcdPool, error)

func (*EtcdPool) Close

func (e *EtcdPool) Close()

type EtcdPoolConfig

type EtcdPoolConfig struct {
	AdvertiseAddress string
	BaseKey          string
	Client           *etcd.Client
	OnUpdate         UpdateFunc
}

type GRPCStats

type GRPCStats struct {
	Duration time.Duration
	Method   string
	Failed   int64
	Success  int64
}

func StatsFromContext

func StatsFromContext(ctx context.Context) *GRPCStats

Returns the `GRPCStats` previously associated with `ctx`.

type GetPeerRateLimitsReq

type GetPeerRateLimitsReq struct {
	// Must specify at least one RateLimit. The peer that recives this request MUST be authoritative for
	// each rate_limit[x].unique_key provided, as the peer will not forward the request to any other peers
	Requests []*RateLimitReq `protobuf:"bytes,1,rep,name=requests" json:"requests,omitempty"`
}

func (*GetPeerRateLimitsReq) Descriptor

func (*GetPeerRateLimitsReq) Descriptor() ([]byte, []int)

func (*GetPeerRateLimitsReq) GetRequests

func (m *GetPeerRateLimitsReq) GetRequests() []*RateLimitReq

func (*GetPeerRateLimitsReq) ProtoMessage

func (*GetPeerRateLimitsReq) ProtoMessage()

func (*GetPeerRateLimitsReq) Reset

func (m *GetPeerRateLimitsReq) Reset()

func (*GetPeerRateLimitsReq) String

func (m *GetPeerRateLimitsReq) String() string

type GetPeerRateLimitsResp

type GetPeerRateLimitsResp struct {
	// Responses are in the same order as they appeared in the PeerRateLimitRequests
	RateLimits []*RateLimitResp `protobuf:"bytes,1,rep,name=rate_limits,json=rateLimits" json:"rate_limits,omitempty"`
}

func (*GetPeerRateLimitsResp) Descriptor

func (*GetPeerRateLimitsResp) Descriptor() ([]byte, []int)

func (*GetPeerRateLimitsResp) GetRateLimits

func (m *GetPeerRateLimitsResp) GetRateLimits() []*RateLimitResp

func (*GetPeerRateLimitsResp) ProtoMessage

func (*GetPeerRateLimitsResp) ProtoMessage()

func (*GetPeerRateLimitsResp) Reset

func (m *GetPeerRateLimitsResp) Reset()

func (*GetPeerRateLimitsResp) String

func (m *GetPeerRateLimitsResp) String() string

type GetRateLimitsReq

type GetRateLimitsReq struct {
	Requests []*RateLimitReq `protobuf:"bytes,1,rep,name=requests" json:"requests,omitempty"`
}

Must specify at least one Request

func (*GetRateLimitsReq) Descriptor

func (*GetRateLimitsReq) Descriptor() ([]byte, []int)

func (*GetRateLimitsReq) GetRequests

func (m *GetRateLimitsReq) GetRequests() []*RateLimitReq

func (*GetRateLimitsReq) ProtoMessage

func (*GetRateLimitsReq) ProtoMessage()

func (*GetRateLimitsReq) Reset

func (m *GetRateLimitsReq) Reset()

func (*GetRateLimitsReq) String

func (m *GetRateLimitsReq) String() string

type GetRateLimitsResp

type GetRateLimitsResp struct {
	Responses []*RateLimitResp `protobuf:"bytes,1,rep,name=responses" json:"responses,omitempty"`
}

RateLimits returned are in the same order as the Requests

func (*GetRateLimitsResp) Descriptor

func (*GetRateLimitsResp) Descriptor() ([]byte, []int)

func (*GetRateLimitsResp) GetResponses

func (m *GetRateLimitsResp) GetResponses() []*RateLimitResp

func (*GetRateLimitsResp) ProtoMessage

func (*GetRateLimitsResp) ProtoMessage()

func (*GetRateLimitsResp) Reset

func (m *GetRateLimitsResp) Reset()

func (*GetRateLimitsResp) String

func (m *GetRateLimitsResp) String() string

type HashFunc

type HashFunc func(data []byte) uint32

type HealthCheckReq

type HealthCheckReq struct {
}

func (*HealthCheckReq) Descriptor

func (*HealthCheckReq) Descriptor() ([]byte, []int)

func (*HealthCheckReq) ProtoMessage

func (*HealthCheckReq) ProtoMessage()

func (*HealthCheckReq) Reset

func (m *HealthCheckReq) Reset()

func (*HealthCheckReq) String

func (m *HealthCheckReq) String() string

type HealthCheckResp

type HealthCheckResp struct {
	// Valid entries are 'healthy' or 'unhealthy'
	Status string `protobuf:"bytes,1,opt,name=status" json:"status,omitempty"`
	// If 'unhealthy', message indicates the problem
	Message string `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"`
	// The number of peers we know about
	PeerCount int32 `protobuf:"varint,3,opt,name=peer_count,json=peerCount" json:"peer_count,omitempty"`
}

func (*HealthCheckResp) Descriptor

func (*HealthCheckResp) Descriptor() ([]byte, []int)

func (*HealthCheckResp) GetMessage

func (m *HealthCheckResp) GetMessage() string

func (*HealthCheckResp) GetPeerCount

func (m *HealthCheckResp) GetPeerCount() int32

func (*HealthCheckResp) GetStatus

func (m *HealthCheckResp) GetStatus() string

func (*HealthCheckResp) ProtoMessage

func (*HealthCheckResp) ProtoMessage()

func (*HealthCheckResp) Reset

func (m *HealthCheckResp) Reset()

func (*HealthCheckResp) String

func (m *HealthCheckResp) String() string

type Instance

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

func New

func New(conf Config) (*Instance, error)

func (*Instance) Collect

func (s *Instance) Collect(ch chan<- prometheus.Metric)

Collect fetches metrics from the server for use by prometheus

func (*Instance) Describe

func (s *Instance) Describe(ch chan<- *prometheus.Desc)

Describe fetches prometheus metrics to be registered

func (*Instance) GetPeer

func (s *Instance) GetPeer(key string) (*PeerClient, error)

GetPeers returns a peer client for the hash key provided

func (*Instance) GetPeerList

func (s *Instance) GetPeerList() []*PeerClient

func (*Instance) GetPeerRateLimits

func (s *Instance) GetPeerRateLimits(ctx context.Context, r *GetPeerRateLimitsReq) (*GetPeerRateLimitsResp, error)

GetPeerRateLimits is called by other peers to get the rate limits owned by this peer.

func (*Instance) GetRateLimits

func (s *Instance) GetRateLimits(ctx context.Context, r *GetRateLimitsReq) (*GetRateLimitsResp, error)

GetRateLimits is the public interface used by clients to request rate limits from the system. If the rate limit `Name` and `UniqueKey` is not owned by this instance then we forward the request to the peer that does.

func (*Instance) HealthCheck

func (s *Instance) HealthCheck(ctx context.Context, r *HealthCheckReq) (*HealthCheckResp, error)

HealthCheck Returns the health of our instance.

func (*Instance) SetPeers

func (s *Instance) SetPeers(peers []PeerInfo)

SetPeers is called when the pool of peers changes

func (*Instance) UpdatePeerGlobals

func (s *Instance) UpdatePeerGlobals(ctx context.Context, r *UpdatePeerGlobalsReq) (*UpdatePeerGlobalsResp, error)

UpdatePeerGlobals updates the local cache with a list of global rate limits. This method should only be called by a peer who is the owner of a global rate limit.

type Interval

type Interval struct {
	C chan struct{}
	// contains filtered or unexported fields
}

func NewInterval

func NewInterval(d time.Duration) *Interval

NewInterval creates a new ticker like object, however the `C` channel does not return the current time and `C` channel will only get a tick after `Next()` has been called.

func (*Interval) Next

func (i *Interval) Next()

Next queues the next interval to run, If multiple calls to Next() are made before previous intervals have completed they are ignored.

func (*Interval) Stop

func (i *Interval) Stop()

type K8sPool

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

func NewK8sPool

func NewK8sPool(conf K8sPoolConfig) (*K8sPool, error)

func (*K8sPool) Close

func (e *K8sPool) Close()

type K8sPoolConfig

type K8sPoolConfig struct {
	OnUpdate  UpdateFunc
	Namespace string
	Selector  string
	PodIP     string
	PodPort   string
	Enabled   bool
}

type PeerClient

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

func NewPeerClient

func NewPeerClient(conf BehaviorConfig, host string) (*PeerClient, error)

func (*PeerClient) GetPeerRateLimit

func (c *PeerClient) GetPeerRateLimit(ctx context.Context, r *RateLimitReq) (*RateLimitResp, error)

GetPeerRateLimit forwards a rate limit request to a peer. If the rate limit has `behavior == BATCHING` configured this method will attempt to batch the rate limits

func (*PeerClient) GetPeerRateLimits

func (c *PeerClient) GetPeerRateLimits(ctx context.Context, r *GetPeerRateLimitsReq) (*GetPeerRateLimitsResp, error)

GetPeerRateLimits requests a list of rate limit statuses from a peer

func (*PeerClient) UpdatePeerGlobals

func (c *PeerClient) UpdatePeerGlobals(ctx context.Context, r *UpdatePeerGlobalsReq) (*UpdatePeerGlobalsResp, error)

UpdatePeerGlobals sends global rate limit status updates to a peer

type PeerInfo

type PeerInfo struct {
	Address string
	IsOwner bool
}

type PeerPicker

type PeerPicker interface {
	GetPeerByHost(host string) *PeerClient
	Peers() []*PeerClient
	Get(string) (*PeerClient, error)
	New() PeerPicker
	Add(*PeerClient)
	Size() int
}

type PeersV1Client

type PeersV1Client interface {
	// Used by peers to relay batches of requests to an authoritative peer
	GetPeerRateLimits(ctx context.Context, in *GetPeerRateLimitsReq, opts ...grpc.CallOption) (*GetPeerRateLimitsResp, error)
	// Used by peers send global rate limit updates to other peers
	UpdatePeerGlobals(ctx context.Context, in *UpdatePeerGlobalsReq, opts ...grpc.CallOption) (*UpdatePeerGlobalsResp, error)
}

func NewPeersV1Client

func NewPeersV1Client(cc *grpc.ClientConn) PeersV1Client

type PeersV1Server

type PeersV1Server interface {
	// Used by peers to relay batches of requests to an authoritative peer
	GetPeerRateLimits(context.Context, *GetPeerRateLimitsReq) (*GetPeerRateLimitsResp, error)
	// Used by peers send global rate limit updates to other peers
	UpdatePeerGlobals(context.Context, *UpdatePeerGlobalsReq) (*UpdatePeerGlobalsResp, error)
}

type PoolInterface

type PoolInterface interface {
	Close()
}

type RateLimitReq

type RateLimitReq struct {
	// The name of the rate limit IE: 'requests_per_second', 'gets_per_minute`
	Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
	// Uniquely identifies this rate limit IE: 'ip:10.2.10.7' or 'account:123445'
	UniqueKey string `protobuf:"bytes,2,opt,name=unique_key,json=uniqueKey" json:"unique_key,omitempty"`
	// Rate limit requests optionally specify the number of hits a request adds to the matched limit. If Hit
	// is zero, the request returns the current limit, but does not increment the hit count.
	Hits int64 `protobuf:"varint,3,opt,name=hits" json:"hits,omitempty"`
	// The number of requests that can occur for the duration of the rate limit
	Limit int64 `protobuf:"varint,4,opt,name=limit" json:"limit,omitempty"`
	// The duration of the rate limit in milliseconds
	// Second = 1000 Milliseconds
	// Minute = 60000 Milliseconds
	// Hour = 3600000 Milliseconds
	Duration int64 `protobuf:"varint,5,opt,name=duration" json:"duration,omitempty"`
	// The algorithm used to calculate the rate limit. The algorithm may change on
	// subsequent requests, when this occurs any previous rate limit hit counts are reset.
	Algorithm Algorithm `protobuf:"varint,6,opt,name=algorithm,enum=pb.gubernator.Algorithm" json:"algorithm,omitempty"`
	// The behavior of the rate limit in gubernator.
	Behavior Behavior `protobuf:"varint,7,opt,name=behavior,enum=pb.gubernator.Behavior" json:"behavior,omitempty"`
}

func (*RateLimitReq) Descriptor

func (*RateLimitReq) Descriptor() ([]byte, []int)

func (*RateLimitReq) GetAlgorithm

func (m *RateLimitReq) GetAlgorithm() Algorithm

func (*RateLimitReq) GetBehavior

func (m *RateLimitReq) GetBehavior() Behavior

func (*RateLimitReq) GetDuration

func (m *RateLimitReq) GetDuration() int64

func (*RateLimitReq) GetHits

func (m *RateLimitReq) GetHits() int64

func (*RateLimitReq) GetLimit

func (m *RateLimitReq) GetLimit() int64

func (*RateLimitReq) GetName

func (m *RateLimitReq) GetName() string

func (*RateLimitReq) GetUniqueKey

func (m *RateLimitReq) GetUniqueKey() string

func (*RateLimitReq) HashKey

func (m *RateLimitReq) HashKey() string

func (*RateLimitReq) ProtoMessage

func (*RateLimitReq) ProtoMessage()

func (*RateLimitReq) Reset

func (m *RateLimitReq) Reset()

func (*RateLimitReq) String

func (m *RateLimitReq) String() string

type RateLimitResp

type RateLimitResp struct {
	// The status of the rate limit.
	Status Status `protobuf:"varint,1,opt,name=status,enum=pb.gubernator.Status" json:"status,omitempty"`
	// The currently configured request limit (Identical to RateLimitRequest.rate_limit_config.limit).
	Limit int64 `protobuf:"varint,2,opt,name=limit" json:"limit,omitempty"`
	// This is the number of requests remaining before the limit is hit.
	Remaining int64 `protobuf:"varint,3,opt,name=remaining" json:"remaining,omitempty"`
	// This is the time when the rate limit span will be reset, provided as a unix timestamp in milliseconds.
	ResetTime int64 `protobuf:"varint,4,opt,name=reset_time,json=resetTime" json:"reset_time,omitempty"`
	// Contains the error; If set all other values should be ignored
	Error string `protobuf:"bytes,5,opt,name=error" json:"error,omitempty"`
	// This is additional metadata that a client might find useful. (IE: Additional headers, corrdinator ownership, etc..)
	Metadata map[string]string `` /* 136-byte string literal not displayed */
}

func (*RateLimitResp) Descriptor

func (*RateLimitResp) Descriptor() ([]byte, []int)

func (*RateLimitResp) GetError

func (m *RateLimitResp) GetError() string

func (*RateLimitResp) GetLimit

func (m *RateLimitResp) GetLimit() int64

func (*RateLimitResp) GetMetadata

func (m *RateLimitResp) GetMetadata() map[string]string

func (*RateLimitResp) GetRemaining

func (m *RateLimitResp) GetRemaining() int64

func (*RateLimitResp) GetResetTime

func (m *RateLimitResp) GetResetTime() int64

func (*RateLimitResp) GetStatus

func (m *RateLimitResp) GetStatus() Status

func (*RateLimitResp) ProtoMessage

func (*RateLimitResp) ProtoMessage()

func (*RateLimitResp) Reset

func (m *RateLimitResp) Reset()

func (*RateLimitResp) String

func (m *RateLimitResp) String() string

type Status

type Status int32
const (
	Status_UNDER_LIMIT Status = 0
	Status_OVER_LIMIT  Status = 1
)

func (Status) EnumDescriptor

func (Status) EnumDescriptor() ([]byte, []int)

func (Status) String

func (x Status) String() string

type UpdateFunc

type UpdateFunc func([]PeerInfo)

type UpdatePeerGlobal

type UpdatePeerGlobal struct {
	Key    string         `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"`
	Status *RateLimitResp `protobuf:"bytes,2,opt,name=status" json:"status,omitempty"`
}

func (*UpdatePeerGlobal) Descriptor

func (*UpdatePeerGlobal) Descriptor() ([]byte, []int)

func (*UpdatePeerGlobal) GetKey

func (m *UpdatePeerGlobal) GetKey() string

func (*UpdatePeerGlobal) GetStatus

func (m *UpdatePeerGlobal) GetStatus() *RateLimitResp

func (*UpdatePeerGlobal) ProtoMessage

func (*UpdatePeerGlobal) ProtoMessage()

func (*UpdatePeerGlobal) Reset

func (m *UpdatePeerGlobal) Reset()

func (*UpdatePeerGlobal) String

func (m *UpdatePeerGlobal) String() string

type UpdatePeerGlobalsReq

type UpdatePeerGlobalsReq struct {
	// Must specify at least one RateLimit
	Globals []*UpdatePeerGlobal `protobuf:"bytes,1,rep,name=globals" json:"globals,omitempty"`
}

func (*UpdatePeerGlobalsReq) Descriptor

func (*UpdatePeerGlobalsReq) Descriptor() ([]byte, []int)

func (*UpdatePeerGlobalsReq) GetGlobals

func (m *UpdatePeerGlobalsReq) GetGlobals() []*UpdatePeerGlobal

func (*UpdatePeerGlobalsReq) ProtoMessage

func (*UpdatePeerGlobalsReq) ProtoMessage()

func (*UpdatePeerGlobalsReq) Reset

func (m *UpdatePeerGlobalsReq) Reset()

func (*UpdatePeerGlobalsReq) String

func (m *UpdatePeerGlobalsReq) String() string

type UpdatePeerGlobalsResp

type UpdatePeerGlobalsResp struct {
}

func (*UpdatePeerGlobalsResp) Descriptor

func (*UpdatePeerGlobalsResp) Descriptor() ([]byte, []int)

func (*UpdatePeerGlobalsResp) ProtoMessage

func (*UpdatePeerGlobalsResp) ProtoMessage()

func (*UpdatePeerGlobalsResp) Reset

func (m *UpdatePeerGlobalsResp) Reset()

func (*UpdatePeerGlobalsResp) String

func (m *UpdatePeerGlobalsResp) String() string

type V1Client

type V1Client interface {
	// Given a list of rate limit requests, return the rate limits of each.
	GetRateLimits(ctx context.Context, in *GetRateLimitsReq, opts ...grpc.CallOption) (*GetRateLimitsResp, error)
	// This method is for round trip benchmarking and can be used by
	// the client to determine connectivity to the server
	HealthCheck(ctx context.Context, in *HealthCheckReq, opts ...grpc.CallOption) (*HealthCheckResp, error)
}

func DialV1Server

func DialV1Server(server string) (V1Client, error)

Create a new connection to the server

func NewV1Client

func NewV1Client(cc *grpc.ClientConn) V1Client

type V1Server

type V1Server interface {
	// Given a list of rate limit requests, return the rate limits of each.
	GetRateLimits(context.Context, *GetRateLimitsReq) (*GetRateLimitsResp, error)
	// This method is for round trip benchmarking and can be used by
	// the client to determine connectivity to the server
	HealthCheck(context.Context, *HealthCheckReq) (*HealthCheckResp, error)
}

Directories

Path Synopsis
cmd
gubernator command
gubernator-cli command

Jump to

Keyboard shortcuts

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