-
Notifications
You must be signed in to change notification settings - Fork 89
Components
This page describes the main components of rend and how they fit together. This is a fairly high level overview, though, so see the child pages for more detail about any one component. The following description will be referencing this image:
For any given server, there can be more than one socket accepting connections at a time. The server component, when it is started, actually just starts a relatively simple accept()
loop that just accepts connections and spins off another goroutine that acts as a server
The server is also conceptually basic; it's a loop that forever repeats:
- parse a new request
- handle request
- record timing metrics
In the picture it shows a separate box for the protocol implementation. This is because the server, when it starts on a new connection, doesn't actually know what protocol is being used by the client. In theory this could be any protocol parser that implements the proper interface, but in Rend it really just chooses between the text and binary memcached protocols.
The Orchestrator is the component (also pluggable) that has most of the smarts of Rend. It is the piece that will determine how best to complete the request given the L1 and L2 it has. Built in are Orchestrators that use an L1 cache only, and L1 and L2 in a hot / cold configuration, and then one that is optimized for batch job interaction and background communication that uses L1 opportunistically but generally only modifies L2.
The Handlers as the bottom are the pieces that translate the internal Memcached-like commands and calls into real, on the wire or on disk calls to handle data. These pieces are where the rubber meets the road. These are, of course, pluggable as well (notice a pattern?). Anything implementing the interface can be used as a Handler. Within Netflix, there are are a few already that have been developed, with varying levels of production readiness:
- The standard handler - this is mostly a pass-through translation from commands to Memcached calls
- The chunked handler - this needs some explanation, so see the detail page.
- A batching / connection pool handler - uses a connection pool and batching to reduce syscalls
- rend-http handler - translates a subset of calls into REST calls on the EVCache API
- rend-lmdb handler - uses LMDB as a local on-disk storage solution
- Mnemonic - an in-house sharded RocksDB-backed disk storage solution
The great thing about the design of Rend is that any of the components can be replaced fairly easily if need be. The server listener function actually take a constructor function for the server itself, the orchestrator, and both handlers. All of these constructor functions are typed such that you can return anything you want that conforms to the interfaces.
func ListenAndServe(l ListenArgs, s ServerConst, o orcas.OrcaConst, h1, h2 handlers.HandlerConst)
For examples on this composition, see memproxy.go.