H2-Proxy is a light way proxy yet useful for proxying http2 and gRPC traffic
h2-proxy supports http2 and gRPC servers/clients for proxying the request/responses, so far without support for SSL (in TODO list).
The proxy is able to balance the requests against the target defined (if there are multiple IP associated with the same domain) according to the load balancing algorithm defined. Before returning any connection the balancer makes sure the connection selected is active, otherwise, a maximum of 10 retries is done before returning an error.
- none (default): No balancer means that h2-proxy grabs from the connection pool the first available connection, always in the same order the connections were stored.
- random: grabs in a random way any of the available connections.
- round_robin: based in the round-robin algorithm pick an available connection from the pool.
The domain refresh helps the proxy to have the latest status of the domain, is useful to keep the load balancer up to date when instances are created, rotated, or deleted.
The domain refresh is enabled by configuration but also depends if the target is a domain in case of IP it is disabled automatically, also there is a configuration for the refresh rate where the default value is 60 seconds.
h2-proxy can be set up in two ways via yaml file or environment variables
If yaml configuration wants to be used then the file needs to be placed inside /etc/h2-proxy/config.yaml
or set the env var H2_PROXY_CFG_LOCATION
for a new location.
proxy_address: '0.0.0.0:50060'
proxy_name: 'h2-proxy'
target_host: 'my-target-domain'
target_port: '50051'
idle_timeout: 300
print_logs: true
compact_logs: true
dns_config:
refresh_rate: 45
need_refresh: true
balancer_alg: round_robin
proxy_address:
proxy address is the interface and the port the proxy will be listening on, for docker the ports exposed by the container are 8080 8090 50060 50061, default value is0.0.0.0:50060
proxy_name
: is the proxy name, default value ish2-proxy
this name will be sent in theX-Proxied-By
headertarget_host:
is the server host you want to redirect the call to, this value is mandatorytarget_port:
is the target server port, this value is mandatoryidle_timeout:
is the time in seconds the proxy will keep the connection alive if does not receive any request, default value is 300 (5 minutes)print_logs:
indicates if want basic logs to be printed, so far a very basic functionality is enabled and the logs arenprinted in stdout, default value isfalse
compact_logs:
indicates if some values are shortened when the log is printed to help to reduce the log size
logs with compact logs disabled:
2020/01/01 10:10:55 {"rq_id": "c1824516-48e9-4540-9ca3-8720754e145e", "rq_path": "/user.UserService/CreateUser", "rq_proto": "HTTP/2.0", "elapsed_time_ms": 2, "rq_length": 58, "rs_length": 256}
logs with compact logs enabled:
2020/01/01 10:10:14 id:4ef01a36-2ba6-4922-9519-cf63567d68f1 | p: /user.UserService/CreateUser | pr: HTTP/2.0 | ms: 2 | rq_ln: 58 | rs_ln: 256
dns_config.refresh_rate:
value in seconds that indicates how often the resolver needs to check the domain in order to update the set of IPs associated with one domain, default value 60 secondsdns_config.need_refresh:
useful to disable the domain refresh feature, default value is true but in case the target is an IP then this value is set as falsedns_config.balancer_alg:
indicates the load balancing algorithm, the default value is none, possible values are: none, random and round_robin.
In the case the default values in the YAML suits all the needs then a configuration by environment variables can be done.
If YAML file is not provided the next environment variables are required:
H2_PROXY_TARGET_HOST
- host where the proxy needs to redirect the callsH2_PROXY_TARGET_PORT
- target portH2_PROXY_PRINT_LOGS
- optional value that indiates if want logs to be printedH2_PROXY_COMPACT_LOGS
- an optional value that indicates if some keys can be shortened in the logs
After defining the configuration strategy is time to start up the project:
pull the docker image docker pull cperez08/h2-proxy
then docker run -d --name h2-proxy -p 50060:50060 -e H2_PROXY_TARGET_HOST=127.0.0.1 -e H2_PROXY_TARGET_PORT=8080 -e H2_PROXY_PRINT_LOGS=true cperez08/h2-proxy
change the values for the real ones
FROM cperez08/h2-proxy
COPY config.yaml /etc/h2-proxy/config.yaml
docker build -t my-h2-proxy .
docker run -d --name h2-proxy -p 50060:50060 my-h2-proxy
download the binary via go get, for this option make sure you have your $GOPATH/bin
set up in your PATH otherwise copy and paste from that location the binary into the desired destination.
- downlaod
go get -u github.com/cperez08/h2-proxy
- run
h2-proxy
(in case the$GOPATH/bin
is set up in PATH - cp
$GOPATH/bin/h2-proxy
my-location/ &&./my-location/h2-proxy
remember either load the environment variables and/or place the config file in an appropriate location.
In order to proxy gRPC services properly inside a Kubernetes cluster follow these steps:
- Set up the gRPC server, then deploy and create a headless service.
- Set up the proxy to create the deployment and service.
- Set up the client gRPC pointing to the proxy, also you need to set up the client in a way this can balance the requests to the different proxy instances, for this support you can follow this guideline which explains how to set up properly the client gRPC based in a custom resolver (the one used in this project)
- Test and start testing with requests
note: the most important part of this set up is the headless service that needs to be done for the server and for the proxy (in the aforementioned example), with this configuration Kubernetes keeps up to date all the pod's IP related to the service, so the resolver keeps in sync all the IPs where the calls need to be redirected.
- Add support for SSL
- Add circuit break
- Add support for multiple IPs
- Add more load balancing alghoritms
- Improve logging