Version: v0.8.9 Latest Latest

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

Go to latest
Published: May 27, 2019 License: MIT



uds-proxy provides a UNIX domain socket and forwards traffic to HTTP(S) remotes through a customizable connection pool (i.e. using persistent connections).

what for? why? how?

Interacting with microservices often involves communication overhead: Every contact with another service may involve DNS lookups and establishment of a TCP connection plus, most likely, a HTTPS handshake.

This overhead can be costly and especially hard to circumvent for legacy applications -- thus uds-proxy.

uds-proxy creates a UNIX domain socket and forwards communication to one or more remote web servers. In a way, uds-proxy aims a bit at reducing application/API complexity by providing a generic and simple solution for connection pooling.

uds-proxy is implemented in Go, so it runs as native application on any OS supporting Go and UNIX domain sockets (i.e. not on Windows). Critical performance metrics of uds-proxy (request latencies, response codes...) and Go process statistics are exposed through Prometheus client library.

building / installing uds-proxy

Building requires a local Go 1.11+ installation:

go get -v github.com/schnoddelbotz/uds-proxy/cmd/uds-proxy

... or just grab a uds-proxy binary release.

See usage-example-for-an-https-endpoint for Docker usage.

To start uds-proxy at system boot, create e.g. a systemd unit. Don't try to run uds-proxy as root. It won't start.


Usage of ./uds-proxy:
  -client-timeout int
      http client connection timeout [ms] for proxy requests (default 5000)
  -idle-timeout int
      connection timeout [ms] for idle backend connections (default 90000)
  -max-conns-per-host int
      maximum number of connections per backend host (default 20)
  -max-idle-conns int
      maximum number of idle HTTP(S) connections (default 100)
  -max-idle-conns-per-host int
      maximum number of idle conns per backend (default 25)
      disable timestamps in log messages
  -pid-file string
      pid file to use, none if empty
  -prometheus-port string
      Prometheus monitoring port, e.g. :18080
      remote uses https://
  -socket string
      path of socket to create
  -socket-read-timeout int
      read timeout [ms] for -socket (default 5000)
  -socket-write-timeout int
      write timeout [ms] for -socket (default 5000)
      print uds-proxy version

monitoring / testing / development

Clone this repository and check the Makefile targets.

Most relevant make targets:

  • make monitoring_test spins up Prometheus, grafana and uds-proxy using Docker and starts another uds-proxy instance locally (outside Docker, on Mac only). The uds-proxy instances will be scraped by dockerized Prometheus and Grafana will provide dashboards. See monitoring/README.md for details.
  • make run_proxy starts a local uds-proxy instance for testing purposes. TEST_SOCKET environment variable controls socket location, defaults to uds-proxy-test.socket.
  • make test runs unit and functional tests from proxy_test directory.
  • make coverage generates code test coverage statistics.
  • make test_integration starts a local uds-proxy and runs some proxied-vs-non-proxied perf tests.
  • make realclean removes leftovers from tests or builds.
usage example for an HTTPS endpoint

Start the proxy:

uds-proxy -socket /tmp/proxied-svc.sock -prometheus-port :28080 -remote-https

Docker users:

mkdir -p /tmp/mysock_dir
docker run --rm -it -p28080:28080 -v/tmp/mysock_dir:/tmp schnoddelbotz/uds-proxy

For both cases, metrics should be available at http://localhost:28080/metrics while uds-proxy is running.

using bash / curl
# without uds-proxy, you would...
time curl -I https://www.google.com/

# with uds-proxy, always ...
# a) talk through socket and
# b) use http:// and let `-remote-https` ensure https is used to connect to remote hosts
time curl -I --unix-socket /tmp/proxied-svc.sock http://www.google.com/
# ... or using socket provided by dockerized uds-proxy:
time curl -I --unix-socket /tmp/mysock_dir/uds-proxy-docker.sock http://www.google.com/
using php / curl
// without uds-proxy
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://www.google.com/");

// with uds-proxy
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://www.google.com/");
curl_setopt($ch, CURLOPT_UNIX_SOCKET_PATH, "/tmp/proxied-svc.sock");
further socket testing

Mac's (i.e. BSD's) netcat allows to talk to unix domain sockets. It can be used to e.g. ensure correct behaviour of uds-proxy's -socket-(read|write)-timeout options. Simply use nc -U /path/to/uds-proxy.sock.

todo ...

  • fix heatmap
  • fix/drop sudo nobody for dockerized tests
  • fixme: add option -dont-follow-redirects
  • add a circuit breaker and or exponential backoff?
  • cleanup: wrap handleProxyRequest into logging handler
  • travis-ci + github release push
  • level-based stdout/err logging https://awesome-go.com/#logging
  • example systemd unit
  • log request sizes?
  • use/fix 'make test' in Dockerfile
  • sock umask / cli opt
  • support magic uds request headers...?
    • X-udsproxy-timeout: 250ms
    • X-udsproxy-debug: true


  • for Python and Redis, use a redis.py connection pool
  • for Python and HTTP, requests library will just do it
  • for Redis and PHP, phpredis supports experimental persistent connections
  • a potentially more sophisticated solution can be found in this TCP vs UDS speed comparison stackoverflow thread: Speedus intercepts relevant system calls, which avoids need for any code changes. However, if I understood correctly, Speedus only helps if services actually sit on the same host system.




Path Synopsis

Jump to

Keyboard shortcuts

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