• Stars
    star
    1,910
  • Rank 24,271 (Top 0.5 %)
  • Language
    Go
  • License
    Apache License 2.0
  • Created almost 9 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Doorman: Global Distributed Client Side Rate Limiting.

Doorman

Build Status

Doorman is a solution for Global Distributed Client Side Rate Limiting. Clients that talk to a shared resource (such as a database, a gRPC service, a RESTful API, or whatever) can use Doorman to voluntarily limit their use (usually in requests per second) of the resource. Doorman is written in Go and uses gRPC as its communication protocol. For some high-availability features it needs a distributed lock manager. We currently support etcd, but it should be relatively simple to make it use Zookeeper instead.

Getting started

The purpose of Doorman is to apportion and distribute capacity to clients based on some definition of fairness. The capacity a client gets for a resource depends on four things:

  • The configured maximum capacity for the resource (world-wide).
  • The capacity need (wants) of this client.
  • The capacity needs (wants) of all other clients on the planet.
  • The exact algorithm used (as defined by the configuration) to apportion the capacity among all the clients.

The Doorman master server remembers all clients that currently have capacity and whenever a client asks for capacity it inserts the clients request into its memory and runs the algorithm to figure out what this client should get.

Lease length and refresh interval

Doorman only gives out capacity for a limited amount of time, in the form of leases. Each capacity grant comes with a lease length: The client is guaranteed that amount of capacity for the duration of the lease. A typical lease length is five minutes. On top of the lease length the Doorman server also returns a refresh interval. This is the interval after which the client is expected to check back in to get a new lease. A typical refresh interval is five seconds.

Note: The Doorman system is cooperative. The clients are expected to honour the capacity grant, the lease length, and the refresh interval. The system provides no protection against misbehaving clients.

In the normal operation of the system the clients all check in regularly with the server to refresh their capacity. The server knows of all clients and their resource needs, and on every request makes the best possible apportionment of the capacity. For optimization purposes (reduce qps on the Doorman server) the client code does bulk refreshes for all resources whenever it sends out a request to the Doorman server. This means that under specific circumstances (for instance when registering a new resource) a resource might get its capacity refreshed a bit sooner than expected.

The Doorman configuration specifies which algorithm should be used to distribute capacity among all clients. The page on algorithms explains which algorithms currently are available and how they apportion capacity to each client.

The two parameters lease_length and refresh_interval optimize a number of different behaviors of the system:

  • The load on the Doorman server.
  • The speed with which the system converges as resource needs change and clients appear and disappear.
  • How the system deals with the Doorman server being unreachable or slow.

When the Doorman server goes unreachable and comes back

When a client cannot reach the Doorman server the following happens:

  • The client misses one or more refresh intervals. This does not matter much for the client other than that the capacity the client has is not adjusted for potentially changed resource needs.
  • When the Doorman server is unavailable for a longer period of time leases expire and the resources revert to their configured safe capacity. This can be either:
    • -1, meaning an unbounded (infinite) rate limit, or
    • 0, meaning that all access to the resource is blocked, or a positive number
  • As soon as the Doorman server becomes reachable again the clients will resume requesting capacity.

Note: Doorman uses multiple servers in different clusters and a master election procedure to determine the current master.

Doorman does not share or store its internal database. That means that when a Doorman server becomes the master it starts with an empty repository of clients and outstanding leases. However this is not as problematic as it seems, because once the server is available all clients will start calling it to refresh their leases. Since the Doorman server knows that it does not have enough information to run its algorithms it will simply return the currently assigned capacity, or zero if it is a request from a client which currently does not have capacity for the resource. The server knows the currently assigned capacity because clients helpfully include it in every GetCapacity RPC. This phase of the server is known as learning mode.

During the learning mode of a resource every request will be answered with a new lease for the same capacity the client currently has. Practically speaking after a couple of refresh intervals the server can be reasonably sure that it has been contacted by every existing client out there. However for reasons of safety the default learning mode duration is the same as the lease length. This decision ensures that when the learning mode duration expires we can be sure that there are no leases out there that we don't know about (because these would have expired by then). If you want the system to converge faster after a Doorman master election you can explicitly configure a learning_mode_duration in the resource template (see the page on the Configuration of the system for more information).

Who wants what?

Doorman requires the clients to inform it of the desired capacity (the so-called wants). If you are using the low-level Doorman client you need to figure out your capacity need and call the appropriate methods to make sure that the client library requests that amount of capacity during its refresh cycle. However if you use the rate limiter objects provided by the Doorman clients the desired capacity is determined automatically by observing the behavior of the threads that want to access the resource. This automatic wants determination uses a moving average to smoothen out any spikes.

Next steps

Status and Plans

Doorman should be currently considered Alpha quality software. The server and Go client received a decent amount of testing at Google (both functional and load testing), so we are pretty confident they do what they are supposed to do. However, in the process of open-sourcing the code we switched from internal Google technologies to their Open Source equivalents – and this needs more testing. Finally, there's no proper versioning scheme at the moment.

Short term plans:

  • C++ client;
  • Python client;
  • Docker image;

Longer term plans:

  • Ruby client;
  • Proper semantic versioning.

Installation

First, you need to have Go installed. You can either follow the official installation instructions or, on OS X, just do

brew install go

As part of the initial setup, you have to set GOPATH, wihch is the location where Go keeps all its sources and binary artifacts.

export GOPATH=...

With this out of the way, Doorman is just one go get away:

go get github.com/youtube/doorman/go/cmd/doorman

If you are interested in a checkout of Doorman that you can modify, you can do:

mkdir -p $GOPATH/src/github.com/youtube
git clone [email protected]:youtube/doorman.git

Go version <= 1.5

If you are using a version of Go earlier than 1.6, you will need to set an environment variable to enable vendoring (see https://golang.org/s/go15vendor):

export GO15VENDOREXPERIMENT=1

Contributing

See CONTRIBUTING for details on submitting patches and the contribution workflow.

License

Doorman is under the Apache 2.0 license. See the LICENSE file for details.

Note

This is not an official Google product.

More Repositories

1

api-samples

Code samples for YouTube APIs, including the YouTube Data API, YouTube Analytics API, and YouTube Live Streaming API. The repo contains language-specific directories that contain the samples.
Java
5,477
star
2

spfjs

A lightweight JS framework for fast navigation and page updates from YouTube
JavaScript
2,230
star
3

youtube-ios-player-helper

Lightweight helper library that allows iOS developers to add inline playback of YouTube videos through a WebView
Objective-C
1,650
star
4

spitfire

A high-performance Python template language
Python
406
star
5

yt-watchme

Java
340
star
6

cobalt

Cobalt is a lightweight HTML5 application container
C++
296
star
7

yt-direct-lite-android

The code is a reference implementation for an Android OS application that captures video, uploads it to YouTube, and submits the video to a YouTube Direct Lite instance.
Java
276
star
8

yt-direct-lite-iOS

The code is a reference implementation for an iOS application that captures video, uploads it to YouTube, and submits the video to a YouTube Direct Lite instance.
Objective-C
202
star
9

geo-search-tool

A tool to perform YouTube API v3 searches for videos tagged with geo-coordinates.
JavaScript
138
star
10

yt-android-player

Java
130
star
11

js_mse_eme

js_mse_eme is an externally-published tool that is aimed to test the validity of a browser's HTML5 Media Source Extension and Encrypted Media Extension implementations
JavaScript
91
star
12

youtubechatbot

This is a sample YouTube chat bot that's designed to run on Google App Engine. It leverages Task Queues to simulate a long-running background process which polls the YouTube LiveChatMessages API for the specified video.
83
star
13

youtube-chat-for-minecraft

A plugin for Minecraft Forge that provides an API for YouTube live chat services
Java
60
star
14

h5vcc

This is a minimal build of WebKit and Chromium sufficient to render an HTML5 video container for game consoles.
C++
58
star
15

yt-direct-lite-javascript

JavaScript
32
star
16

cobalt_sandbox

Cobalt dev workflow sandbox - this repo exists only as a CI sandbox. Please see http://cobalt.dev and https://github.com/youtube/cobalt
C++
21
star
17

yt-auto-curate-ruby

Ruby
15
star
18

h5vcc_hh

C++
15
star
19

yt-analytics-dump-ruby

Ruby
10
star
20

yt-shuffle-playlist-ruby

Ruby
10
star
21

rcat

A proposal for detecting engagement abuse of embedded third-party web content without depending on cookies.
Java
7
star
22

yt_channel_section_targeter

HTML
6
star
23

vfl

5
star
24

.github

3
star
25

.allstar

1
star