This post is for a new rust project that I have been working on lately. I haven’t really touched rust much for nearly a year, but sometimes projects come up that necessitate a statically typed language. The program is a rust network proxy designed for use in HA redis deployments.

You can view the repo for the proxy here. The basic function of the app is to listen on a user-specified socket, and query a user-specified redis sentinel for redis master’s current location. The proxy then forwards any connections on the listening address over to the current master’s location.

Installation

Once rust has been installed, simply run the following command to install the proxy:

cargo install --git https://github.com/findelabs/rust-redis-proxy.git


Usage

The proxy accepts a number of arguments for operation:

  • listen (required): Specify the listening socket
  • master (required): Specify the redis master name
  • sentinel (sentinel): Specify the redis sentinel socket
  • debug (optional): Enabled debugging mode

The debug flag simply shows a little more info, such as incoming connections.


Overview

The good chunk of code that handles the proxy function was pulled straight from tokio-core, found here.

I added in a bunch of extra code, though, to handle getopts, as well as the health check and sentinel query threads. Eventually I would like to port this over to using true async/await features in current rust, but I don’t believe that my rust coding skills are there yet.

If you would like to test the performance, simply start up a redis server and sentinel, and start the proxy with something like:

./rust-redis-proxy --master mymaster --listen 127.0.0.1:8081 --sentinel 127.0.0.1:26379

You should see some startup messages, like below:

2019-12-07T16:17:54.089435375+00:00 - Startup Message: Listening on: 127.0.0.1:8081
2019-12-07T16:17:54.089539770+00:00 - Startup Message: Sentinel at: 127.0.0.1:26379
2019-12-07T16:17:54.089596458+00:00 - Startup Message: Current master socket: 127.0.0.1:6379
...

The proxy queries the sentinel every second, and the healthcheck against the master cache is ran every ten seconds. If the master cache healthcheck fails, it will decrease the healthcheck interval to one second, and log an error. I’ve found this has been helpful for debugging.

Enabling debugging with --debug enables logging incoming connections to the proxy itself. In the future, I plan to write a standalone app to export simple networking and process statistics for ingestion with prometheus, so stay tuned for more.

This proxy has performed well enough in testing, it obviously cannot keep up with the raw speed of a redis cache, but in my testing, I have been unable to get this proxy to die. In testing, I have successfully hammered the proxy with nearly 10K clients, with pipelining enabled. While the proxy was slowed by the numerous connections, it failed to die.




Has been tested with rust 1.39