README
¶
httptp
httptp is an http(s) proxy and load balancer that saves network bandwidth.
It is built on top of httpteleport.
It accepts incoming requests at -in address and forwards them to -out addresses.
Each request is forwarded to the least loaded healthy -out address.
Any highly loaded http-based API service and microservice may benefit from
httptp usage. Here are a few buzzwords related to such services:
Features
-
Easy to use and configure - just run a single
httptpbinary with required command-line options. -
Easy integration with the existing HTTP-based API services.
-
httptpis fast. It is based on fasthttp. Easily handles more than 100K qps. -
May reduce required network bandwidth between servers by up to 10x. I.e.:
- 10Gbit HTTP traffic may be sent over 1Gbit link.
- 1Gbit HTTP traffic may be sent over 100Mbit link.
- 100Mbit HTTP traffic may be sent over 10Mbit link.
This may have the following benefits:
- Save a lot of money for expensive inter-datacenter traffic.
- Free internal network bandwidth for other services.
-
Supports encrypted connections on both
-inand-outends. -
HTTP keep-alive connections are used by default on both
-inand-outends.httptpeasily handles more than 100K of incoming concurrent keep-alive connections. -
May substitute
nginxin reverse proxy mode, load balancer mode and TLS offloading mode. -
Automatically generates and renews TLS certificates via letsencrypt.org.
-
Automatically adjusts load to upstream servers:
- Faster servers receive more requests.
- Slower and unhealthy servers receive less requests.
-
May limit the maximum number of open connections per upstream host.
-
May accept and/or forward http requests from/to unix sockets.
-
Collects and exports various stats at /expvar and /prometheus pages.
-
Easy to extend and customize.
httptpis open source software written in Go - easy to read and hack language. It is released under MIT license, so it may be easily customized and extended.
Usage
go get -u github.com/valyala/httpteleport/cmd/httptp
httptp -help
Examples
Reducing network bandwidth between datacenters
Suppose you have an RTB partner sending you 50K requests per second. Each RTB request contains ~2Kb JSON body according to RTB spec. 50K * 2Kb * 8bits = 0.8Gbps network bandwidth is required between the partner and you. In reality the required network bandwidth exceeds 1Gbps due to network protocols overhead. This may be quite expensive if your servers and partner servers are located in distinct datacenters. This also may be limiting factor for growth.
Let's decrease the required network bandwidth and the corresponding expenses
by 10x with httptp!
Suppose you have three worker servers hidden behind nginx running
on the ip 69.69.69.69:
upstream rtb {
rtb-server1:80;
rtb-server2:80;
rtb-server3:80;
keepalive 100000;
}
server {
listen 69.69.69.69:80;
location / {
proxy_pass http://rtb;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
Then start httptp on port 9876 on the same machine:
httptp -inType=teleport -in=69.69.69.69:9876 -outType=http -out=rtb-server1:80,rtb-server2:80,rtb-server3:80
Ask your partner starting httptp in his local network for proxying
RTB traffic to you:
# let's assume httptp is started at the server with local ip 10.10.10.10
httptp -inType=http -in=10.10.10.10:6789 -outType=teleport -out=69.69.69.69:9876
Then the partner may send rtb traffic to 10.10.10.10:6789 in his local network.
This traffic will be compressed and proxied to httptp listening
69.69.69.69:9876 in your network. The httptp will spread the traffic across
your worker servers set in the -out parameter: rtb-server1:80,rtb-server2:80,rtb-server3:80.
The result: network traffic between you and the partner is decreased by 10x. So the partner may send 10x more RTB requests to you. This may allow you and your partner earning more money :)
Reducing network bandwidth in local networks
The previous example decreased inter-datacenter network traffic.
But the amount of local traffic between httptp and worker servers didn't
change. httptp may solve the issue - just start httptp
on each worker server:
httptp -inType=teleport -in=:8345 -outType=http -out=127.0.0.1:80
Then restart httptp on proxy server, so it would route traffic to just started
httptp instances on each worker server:
httptp -inType=teleport -in=69.69.69.69:9876 -outType=teleport -out=rtb-server1:8345,rtb-server2:8345,rtb-server3:8345
Great! What about the partner? It still requires a lot of internal network
bandwidth between his servers and httptp running at 10.10.10.10:6789
in his local network.
This issue is easily solved - just run httptp on each of the server,
so it bypasses the local httptp at 10.10.10.10:6789 and routes
the traffic directly to our httptp at 69.69.69.69:9876:
httptp -inType=http -in=127.0.0.1:5438 -outType=teleport -out=69.69.69.69:9876
Don't forget modifying destination address from 10.10.10.10:6789
to 127.0.0.1:5438 on each of the servers.
Optimizing local inter-process communications
httptp in the previous example routes traffic to a locally running RTB service
via 127.0.0.1. This isn't the fastest approach - unix sockets
are usually faster. Luckily httptp supports unix sockets out of the box.
Just run it on each of the worker server with the following options:
httptp -inType=teleport -in=:8345 -outType=unix -out=/path/to/rtb/unix.socket
RTB servers must be able to accept http traffic from local unix socket
/path/to/rtb/unix.socket.
The same optimization applies to partner side:
httptp -inType=unix -in=/path/to/httptp/unix.socket -outType=teleport -out=69.69.69.69:9876
RTB servers must route http traffic to local unix socket /path/to/httptp/unix.socket.
Traffic encryption
In the previous examples RTB traffic is passed unencrypted over public networks
when traveling between you and the partner. Luckily httptp supports
TLS encryption
out of the box - just use teleports traffic type instead of teleport.
Run httptp with the following options on your proxy server:
httptp -inType=teleports -inTLSCert=/path/to/tls.cert -inTLSKey=/path/to/tls.key \
-in=69.69.69.69:4443 -outType=teleport -out=rtb-server1:8345,rtb-server2:8345,rtb-server3:8345
Note that you must have valid TLS certificate and key files for valid domain
name pointing to ip 69.69.69.69. Path to TLS ceritificate file is passed
via -inTLSCert, path to TLS key file is passed via -inTLSKey.
And ask your partner restarting httptp on each server with the following options:
httptp -inType=unix -in=/path/to/httptp/unix.socket -outType=teleports -out=domain-name-for.ip.69.69.69.69:4443
Where domain-name-for.ip.69.69.69.69 is a domain name from your certificate.
Batching
By default httptp forwards requests and responses immediately. This means that
each request or response results in at least one network packet.
Each network packet isn't free:
- It consumes additional CPU time.
- It consumes additional network resources.
- It contains a header overhead, which may be quite big comparing to the request / response size.
- It may hurt compression - multiple requests / responses are usually compressed better than a single request / response.
httptp allows sending multiple requests / responses in a single packet.
This is called batching. Just set non-zero -inDelay and/or -outDelay
when starting httptp.
Beware of the following batching issues:
- Batching may introduce delays.
- Batching may be useful only for high load, i.e. at least thousands of requests per second. Otherwise it is useless.
Compression
By default httptp compresses both requests and responses. While compression
saves network bandwidth, it isn't free - it consumes an additional CPU time.
httptp supports the following compression levels independently for requests
and responses via -inCompress and -outCompress options:
Restricting access to httptp
httptp running on your proxy node 69.69.69.69 in examples above accepts
incoming connections from any IP address. I.e. anybody across the internet
may send requests to it. httptp supports restricting access only
to the given IP list - just pass allowed IPs to -inAllowIP option:
httptp -inType=teleport -in=69.69.69.69:9876 -inAllowIP=partner-ip1,partner-ip2 \
-outType=teleport -out=rtb-server1:8345,rtb-server2:8345,rtb-server3:8345
HTTP load balancing
The following command starts httptp accepting http requests at port 80
and forwarding them to three worker nodes listed in the -out option:
httptp -inType=http -in=:80 -outType=http -out=node1:8080,node2:8080,node3:8080
TLS offloading
The following command starts httptp accepting https requests at port 443
and forwarding them unencrypted to the given -out worker nodes:
httptp -inType=https -in=:443 -outType=http -out=node1:8080,node2:8080,node3:8080
httptp automatically generates and renews TLS certificates for the requested
hosts matching -autocertHostRegexp and caches them at the -autocertCacheDir.
The certificates are generated using letsencrypt.org.
It is possible using already existing TLS certificates - just pass comma-separated
list of certificate paths to -inTLSCert and the corresponding comma-separated
list of key paths to -inTLSKey.
Advanced usage
httptp features may be integrated directly into your services.
Just use httpteleport package
in your clients and/or applications.
This will eliminate httptp hops from the path
client <-> httptp <-> network <-> httptp <-> your application,
thus saving network and CPU resources.
httptp contains other configuration options for advanced usage.
See httptp -help for more details:
$ httptp -help
Usage of ./httptp:
-autocertCacheDir string
Path to directory where automatically generated TLS certificates are cached for -inType=https.
The certificates are generated using https://letsencrypt.org/ (default "autocert-cache")
-autocertHostRegexp string
TLS certificates are automatically generated only for hostnames matching the given regexp (default "^.*$")
-clientIPHeader string
HTTP request header for sending the original client ip.
For instance, -clientIPHeader=X-Forwarded-For. Empty -clientIPHeader disables sending client ip in request headers
-concurrency int
The maximum number of concurrent requests httptp may process.
This also limits the maximum number of open connections per -out address if -outType=http or https (default 100000)
-expvarAddr string
TCP address for exporting httptp metrics. They are exported at the following pages:
http://expvarAddr/expvar - in expvar format
http://expvarAddr/prometheus - in prometheus format
(default "localhost:8040")
-in string
-inType address to listen to for incoming requests (default "127.0.0.1:8080")
-inAllowIP string
Comma-separated list of IP addresses allowed for establishing connections to -in.
All IP addresses are allowed if empty
-inCompress string
Which compression to use for responses if -inType=teleport.
Supported values:
none - responses aren't compressed. Low CPU usage at the cost of high network bandwidth
flate - responses are compressed using flate algorithm. Low network bandwidth at the cost of high CPU usage
snappy - responses are compressed using snappy algorithm. Balance between network bandwidth and CPU usage (default "flate")
-inDelay duration
How long to wait before sending batched responses back if -inType=teleport
-inGetOnly
Accept only GET -in requests if set to true
-inMaxBodySize int
Maximum body size for -in requests (default 4194304)
-inMaxHeaderSize int
Maximum header size for -in requests (default 4096)
-inTLSCert string
Comma-separated list of paths to TLS certificate files if -inType=https or teleports.
Certificates for -inType=https are automatically generated using https://letsencrypt.org/ and cached at -autocertCacheDir if empty (default "")
-inTLSKey string
Comma-separated list of paths to TLS key files if -inType=https or teleports.
Keys for -inType=https are automatically generated using https://letsencrypt.org/ and cached at -autocertCacheDir if empty (default "")
-inTLSSessionTicketKey string
TLS sesssion ticket key if -inType=https or teleports. Automatically generated if empty.
See https://blog.cloudflare.com/tls-session-resumption-full-speed-and-secure/ for details
-inType string
Type of -in address. Supported values:
http - accept http requests over TCP, e.g. -in=127.0.0.1:8080
https - accept https requests over TCP, e.g. -in=127.0.0.1:443
unix - accept http requests over unix socket, e.g. -in=/var/httptp/sock.unix
teleport - accept httpteleport connections over TCP, e.g. -in=127.0.0.1:8043
teleports - accept httpteleport connections over encrypted TCP, e.g. -in=127.0.0.1:8443 (default "http")
-logAllErrors
Log all the error while serving clients. This option may be useful for debugging
-out string
Comma-separated list of -outType addresses to forward requests to.
Each request is forwarded to the least loaded address (default "127.0.0.1:8043")
-outCompress string
Which compression to use for requests if -outType=teleport.
Supported values:
none - requests aren't compressed. Low CPU usage at the cost of high network bandwidth
flate - requests are compressed using flate algorithm. Low network bandwidth at the cost of high CPU usage
snappy - requests are compressed using snappy algorithm. Balance between network bandwidth and CPU usage (default "flate")
-outConnsPerAddr int
How many connections must be established per each -out server if -outType=teleport.
Usually a single connection is enough. Increase this value if the compression
on the connection occupies 100% of a single CPU core.
Alternatively, -inCompress and/or -outCompress may be set to snappy or none in order to reduce CPU load (default 1)
-outDelay duration
How long to wait before forwarding incoming requests to -out if -outType=teleport
-outMaxHeaderSize int
Maximum header size for -out responses (default 4096)
-outTimeout duration
The maximum duration for waiting responses from -out server (default 3s)
-outType string
Type of -out address. Supported values:
http - forward requests to http servers on TCP, e.g. -out=127.0.0.1:80
https - forward requests to https servers on TCP, e.g -out=127.0.0.1:443
unix - forward requests to http servers on unix socket, e.g. -out=/var/nginx/sock.unix
teleport - forward requests to httpteleport servers over TCP, e.g. -out=127.0.0.1:8043
tepelorts - forward requests to httpteleport servers over encrypted TCP, e.g. -out=127.0.0.1:8043. The server must properly set -inTLS* flags in order to accept encrypted TCP connections (default "teleport")
-reusePort
Whether to enable SO_REUSEPORT on -in if -inType is http or teleport
Documentation
¶
There is no documentation for this package.