Golimit is Uber ringpop based distributed and decentralized rate limiter

Golimit A Distributed Rate limiter

Golimit is Uber ringpop based distributed and decentralized rate limiter. It is horizontally scalable and is based on shared nothing architecture. Every node in system is capable of handling read and writes of counters. It is designed to offer sub milliseconds latency to caller application. Recommended deployment topology is sidecar model. Every golimit node keeps local and global counter for api counter and local value is synchronized with other nodes on configurable periodic interval or at defined threshold.

Architecture

Http server provides http interface to increment counter against any arbitrary Key string. It also exposes admin api to manage global configurations.

Store encapsulates the data structure and functions to store, manage and replicate counters. Counter synchronisation is done in asynchronous way so the caller application is never blocked for cluster sync. Synchronizer module keeps aggregating counters in memory and broadcast to other nodes on periodic intervals or when the counter has crossed threshold. the interval and threshold are configurable.

StatsD Emitter pushes metrics to configured statsd server.

Block Diagram

Deployment

Suggested deployment model is to have golimit installed as sidecar. This will ensure application latency to sub milliseconds level. For Go applications golimit can be directly integrated as a module, the way of using golimit as module is explained later in document. Using as module takes away the pain of deployment and maintenance.

Block Diagram

Installation

  1. Build

    $ GOOS=linux GOARCH=amd64 go build  //Linux
    
    $ GOOS=darwin GOARCH=amd64 go build //OSX 
    
    $ GOOS=windows GOARCH=amd64 go build //Windows
    
  2. Configure

    Yml config

        clustername:  MyGolimitCluster # Cluster Name
        tchannelport: 2345 # Ringpop T Channel Port
        seed: "127.0.0.1:2345" # Seed node of cluster
        unsyncedctrlimit: 5  # Unsynced counter limit
        unsyncedtimelimit: 60000 # unsynced timeout in ms
        httpport: 8080  # Http server port
        statsdenabled: true # Enable statsd 
        statsdhostport: "metrics.xyz.com:80"  # statsd host port
        statsdsamplerate: 1 # Statsd sampling rate
        apisecret: alpha # secret key to use admin apis
        hostname: "127.0.0.1"
        unixsocketenable: true #enables unix socket,
                               #gives nearly 2x better performance in response time 
                               #when enabled tcp port config will be ignored and disabled 
        unixsocket: /tmp/golimit.sock #unix socket file location
        

    Note: Ensure the seed node is always reachable.

  3. Run

    $ ./golimitV3 --config=./golimitconfig.yml
    
  4. Use from Http Apis

    Param Description
    K Key a string, against this the counters are calculated
    C Count in number, numbers to increment in one api call, defaults to 1
    W Window in seconds, time window for which provided threshold is applicable
    T Threshold in number
    P PeakAveraged 0 or 1, if P=1 the provided rate limit is transposed to per second limit and then applied
    • INCR Request

      Application passes Key threshold and window and reply is block or not. This rate limiting is application driven as application has to pass all rate configuration in every call In following example second curl within 10 seconds gives back blocked =true

      $  curl -X POST "http://localhost:8080/incr?K=abc&T=1&W=10" 
      
      {"Block":false}
      
      $  curl -X POST "http://localhost:8080/incr?K=abc&T=1&W=10" 
          
      {"Block":true}
      
    • Create/Update global rate configuration, this is for rate limiting which is golimit cluster driven

      $ curl -X PUT  "http://localhost:8080/rate" -d '{"Window":60,"Limit":5,"Key":"a","PeakAveraged":false}' -H "apisecret: alpha" 
         
      {"Success":true}
      
      $ curl -X POST  "http://localhost:8080/ratelimit?K=a" 
      
      {"Block":false}
      
      # after 5 times
      # {"Block":true}
      
      
    • Ratelimit Request

       $ curl -X POST  "http://localhost:8080/ratelimit?K=a" 
       
       {"Block":false}
       
      
    • Get All defined Rate Config

      $ curl  "http://localhost:8080/rateall" 
      
      {"a":{"Window":60,"Limit":5,"PeakAveraged":false}}
      
      
    • Get a specific Rate Config

      $ curl  "http://localhost:8080/rate?K=a" 
      
      {"Window":60,"Limit":5,"PeakAveraged":false}%
      
      
    • Get Cluster Info

      $ curl  "http://localhost:8080/clusterinfo" 
      
      {"Whoami":"127.0.0.1:2345","Ready":true,"Uptime":9223372036854775807,"Members":["127.0.0.1:2345"]}   
      
      
  5. Use as Go module

    If application is in golang, golimit can be used as module directly instead of deploying as separate process.

    To install library:

    go get github.com/myntra/golimit

    package main
    import ("github.com/myntra/golimit/store")
    
    func main() {
    
        //Instantiate Store object, Use single store instance in one application
        store := store.NewStore()
    
        blocked := store.Incr("key", 1, 1000, 60, true) // Increment api
    
        if (blocked) {
            //Blocked
        }
    
        //Ensure Store is closed on program exit
        store.Close()
    }
Similar Resources

Go Open Source, Distributed, Simple and efficient Search Engine

Go Open Source, Distributed, Simple and efficient full text search engine.

Dec 31, 2022

Dapr is a portable, event-driven, runtime for building distributed applications across cloud and edge.

Dapr is a portable, event-driven, runtime for building distributed applications across cloud and edge.

Dapr is a portable, serverless, event-driven runtime that makes it easy for developers to build resilient, stateless and stateful microservices that run on the cloud and edge and embraces the diversity of languages and developer frameworks.

Jan 5, 2023

Asynq: simple, reliable, and efficient distributed task queue in Go

Asynq: simple, reliable, and efficient distributed task queue in Go

Asynq: simple, reliable, and efficient distributed task queue in Go

Dec 31, 2022

💡 A Distributed and High-Performance Monitoring System. The next generation of Open-Falcon

💡 A Distributed and High-Performance Monitoring System.  The next generation of Open-Falcon

夜莺简介 夜莺是一套分布式高可用的运维监控系统,最大的特点是混合云支持,既可以支持传统物理机虚拟机的场景,也可以支持K8S容器的场景。同时,夜莺也不只是监控,还有一部分CMDB的能力、自动化运维的能力,很多公司都基于夜莺开发自己公司的运维平台。开源的这部分功能模块也是商业版本的一部分,所以可靠性有保

Jan 5, 2023

Build share and run your distributed applications.

Build share and run your distributed applications.

sealer[ˈsiːlər] provides the way for distributed application package and delivery based on kubernetes.

Dec 30, 2022

short-url distributed and high-performance

durl 是一个分布式的高性能短链服务,逻辑简单,并提供了相关api接口,开发人员可以快速接入,也可以作为go初学者练手项目.

Jan 2, 2023

A distributed and coördination-free log management system

A distributed and coördination-free log management system

OK Log is archived I hoped to find the opportunity to continue developing OK Log after the spike of its creation. Unfortunately, despite effort, no su

Dec 26, 2022

JuiceFS is a distributed POSIX file system built on top of Redis and S3.

JuiceFS is a distributed POSIX file system built on top of Redis and S3.

JuiceFS is a high-performance POSIX file system released under GNU Affero General Public License v3.0. It is specially optimized for the cloud-native

Jan 4, 2023
Comments
  • fixed crash in updating rate configs

    fixed crash in updating rate configs

    Fix for crash due to concurrent read and write:

    Crash Log stacktrace:

    fatal error: concurrent map iteration and map write

    goroutine 10652 [running]: runtime.throw(0xe4b20f, 0x26) /var/lib/jenkins/tools/org.jenkinsci.plugins.golang.GolangInstallation/go1.10.1/src/runtime/panic.go:616 +0x81 fp=0xc42ab47640 sp=0xc42ab47620 pc=0x42c941 runtime.mapiternext(0xc42d66b740) /var/lib/jenkins/tools/org.jenkinsci.plugins.golang.GolangInstallation/go1.10.1/src/runtime/hashmap.go:747 +0x55c fp=0xc42ab476d0 sp=0xc42ab47640 pc=0x40a90c reflect.mapiternext(0xc42d66b740) /var/lib/jenkins/tools/org.jenkinsci.plugins.golang.GolangInstallation/go1.10.1/src/runtime/hashmap.go:1223 +0x2b fp=0xc42ab476e8 sp=0xc42ab476d0 pc=0x40ba2b reflect.Value.MapKeys(0xcf18e0, 0xc4201f1980, 0x15, 0x0, 0x4094f2, 0xc42ab47878) /var/lib/jenkins/tools/org.jenkinsci.plugins.golang.GolangInstallation/go1.10.1/src/reflect/value.go:1134 +0x13f fp=0xc42ab47790 sp=0xc42ab476e8 pc=0x4c3def encoding/json.(*mapEncoder).encode(0xc42a8864f8, 0xc42a7fc4d0, 0xcf18e0, 0xc4201f1980, 0x15, 0xcf0100) /var/lib/jenkins/tools/org.jenkinsci.plugins.golang.GolangInstallation/go1.10.1/src/encoding/json/encode.go:668 +0xad fp=0xc42ab478f0 sp=0xc42ab47790 pc=0x6b7d7d encoding/json.(*mapEncoder).(encoding/json.encode)-fm(0xc42a7fc4d0, 0xcf18e0, 0xc4201f1980, 0x15, 0xc4201f0100) /var/lib/jenkins/tools/org.jenkinsci.plugins.golang.GolangInstallation/go1.10.1/src/encoding/json/encode.go:700 +0x64 fp=0xc42ab47930 sp=0xc42ab478f0 pc=0x6c2604 encoding/json.(*encodeState).reflectValue(0xc42a7fc4d0, 0xcf18e0, 0xc4201f1980, 0x15, 0x100) /var/lib/jenkins/tools/org.jenkinsci.plugins.golang.GolangInstallation/go1.10.1/src/encoding/json/encode.go:325 +0x82 fp=0xc42ab47968 sp=0xc42ab47930 pc=0x6b57a2 encoding/json.(*encodeState).marshal(0xc42a7fc4d0, 0xcf18e0, 0xc4201f1980, 0x100, 0x0, 0x0) /var/lib/jenkins/tools/org.jenkinsci.plugins.golang.GolangInstallation/go1.10.1/src/encoding/json/encode.go:298 +0xa5 fp=0xc42ab479a0 sp=0xc42ab47968 pc=0x6b5495 encoding/json.Marshal(0xcf18e0, 0xc4201f1980, 0xc4200ceb01, 0x510000c42ab47a40, 0x0, 0x51d9c0b44f658c17, 0x412778) /var/lib/jenkins/tools/org.jenkinsci.plugins.golang.GolangInstallation/go1.10.1/src/encoding/json/encode.go:161 +0x5f fp=0xc42ab479e8 sp=0xc42ab479a0 pc=0x6b4e9f bitbucket.mynt.myntra.com/api/knuth/vendor/github.com/myntra/golimit/store.(*Store).SaveRateConfig(0xc4201e2900) /var/lib/jenkins/workspace/Sfknuth-may31knuth/src/bitbucket.mynt.myntra.com/api/knuth/vendor/github.com/myntra/golimit/store/store.go:471 +0x42 fp=0xc42ab47a50 sp=0xc42ab479e8 pc=0xa85932 bitbucket.mynt.myntra.com/api/knuth/vendor/github.com/myntra/golimit/store.(*Store).SyncRateConfig(0xc4201e2900, 0x7fc849183ce8, 0xc42cb6b640, 0xc42b3041a0, 0x1c, 0x3c00015f90, 0x9d0101, 0xf89bc0, 0xc42d6a3b60) /var/lib/jenkins/workspace/Sfknuth-may31knuth/src/bitbucket.mynt.myntra.com/api/knuth/vendor/github.com/myntra/golimit/store/cluster.go:217 +0x1fe fp=0xc42ab47ae8 sp=0xc42ab47a50 pc=0xa8361e bitbucket.mynt.myntra.com/api/knuth/vendor/github.com/myntra/golimit

    Behaviour and fix can be verified in the following code link: https://play.golang.org/p/sgHcsTI7WZY

  • codahale/hdrhistogram repo url has been transferred under the github HdrHstogram umbrella

    codahale/hdrhistogram repo url has been transferred under the github HdrHstogram umbrella

    Problem

    The codahale/hdrhistogram repo has been transferred under the github HdrHstogram umbrella with the help from the original author in Sept 2020 (new repo url https://github.com/HdrHistogram/hdrhistogram-go). The main reasons are to group all implementations under the same roof and to provide more active contribution from the community as the original repository was archived several years ago.

    The dependency URL should be modified to point to the new repository URL. The tag "v0.9.0" was applied at the point of transfer and will reflect the exact code that was frozen in the original repository.

    If you are using Go modules, you can update to the exact point of transfer using the @v0.9.0 tag in your go get command.

    go mod edit -replace github.com/codahale/hdrhistogram=github.com/HdrHistogram/[email protected]
    

    Performance Improvements

    From the point of transfer, up until now (mon 16 aug 2021), we've released 3 versions that aim support the standard HdrHistogram serialization/exposition formats, and deeply improve READ performance. We recommend to update to the latest version.

Parallel Digital Universe - A decentralized identity-based social network

Parallel Digital Universe Golang implementation of PDU. What is PDU? Usage Development Contributing PDU PDU is a decentralized identity-based social n

Nov 20, 2022
A Golang implementation of the Umee network, a decentralized universal capital facility in the Cosmos ecosystem.

Umee A Golang implementation of the Umee network, a decentralized universal capital facility in the Cosmos ecosystem. Umee is a Universal Capital Faci

Jan 3, 2023
Distributed lock manager. Warning: very hard to use it properly. Not because it's broken, but because distributed systems are hard. If in doubt, do not use this.

What Dlock is a distributed lock manager [1]. It is designed after flock utility but for multiple machines. When client disconnects, all his locks are

Dec 24, 2019
Distributed reliable key-value store for the most critical data of a distributed system

etcd Note: The main branch may be in an unstable or even broken state during development. For stable versions, see releases. etcd is a distributed rel

Dec 30, 2022
Distributed disk storage database based on Raft and Redis protocol.
Distributed disk storage database based on Raft and Redis protocol.

IceFireDB Distributed disk storage system based on Raft and RESP protocol. High performance Distributed consistency Reliable LSM disk storage Cold and

Dec 31, 2022
A distributed system for embedding-based retrieval
A distributed system for embedding-based retrieval

Overview Vearch is a scalable distributed system for efficient similarity search of deep learning vectors. Architecture Data Model space, documents, v

Dec 30, 2022
An implementation of a distributed access-control server that is based on Google Zanzibar

An implementation of a distributed access-control server that is based on Google Zanzibar - "Google's Consistent, Global Authorization System".

Dec 22, 2022
High performance, distributed and low latency publish-subscribe platform.
High performance, distributed and low latency publish-subscribe platform.

Emitter: Distributed Publish-Subscribe Platform Emitter is a distributed, scalable and fault-tolerant publish-subscribe platform built with MQTT proto

Jan 2, 2023
Fast, efficient, and scalable distributed map/reduce system, DAG execution, in memory or on disk, written in pure Go, runs standalone or distributedly.

Gleam Gleam is a high performance and efficient distributed execution system, and also simple, generic, flexible and easy to customize. Gleam is built

Jan 1, 2023