I want to achieve L7 load balancing of grpc traffic using HAProxy 1.8 . Since HAProxy only supports L4 routing for grpc traffic, can we read the grpc request as http2 request (as grpc runs overs http2) in HAproxy and route the request based on some custom header of the request.
Or is there any alternate way to achieve L7 load balancing for grpc traffic. I am aware of the envoyby lyft, but don't plan on using it.
Just a quick update on this, HAProxy supports L7 with H2 on both sides since version 1.9, and gRPC works since 1.9.2 (trailers support was required).
For HAProxy to work as a L7 balancer, HAProxy needs speak http/2 to backends. Last time when I asked about this, I was told that http/2 support isn't on the immediate road-map for HAProxy (but incoming http/2 support is)
Related
I'm running a kubernetes application on GKE, which serves HTTP requests on port 80 and websocket on port 8080.
Now, HTTP part needs to know client's IP address, so I have to use HTTP load balancer as ingress service. Websocket part then has to use TCP load balancer, as it's clearly stated in docs that HTTP LB doesn't support it.
I got them both working, but on different IPs, and I need to have them on one.
I would expect that there is something like iptables on GCE, so I could forward traffic from port 80 to HTTP LB, and from 8080 to TCP LB, but I can't find anything like that. Anything including forwarding allows only one them.
I guess I could have one instance with nginx/HAproxy doing only this, but that seems like an overkill
Appreciate any help!
There's not a great answer to this right now. Ingress objects are really HTTP only right now, and we don't really support multiple grades of ingress in a single cluster (though we want to).
GCE's HTTP LB doesn't do websockets yet.
Services have a flaw in that they lose the client IP (we are working on that). Even once we solve this, you won't be able to use GCE's L7 balancer because of the extra port you need.
The best workaround I can think of, and has been used by a number of users until we preserve source IP, is this:
Run your own haproxy or nginx or even your own app as a Daemonset on some or all nodes (label controlled) with HostPorts.
Run a GCE Network LB (outside of Kubernetes) pointing at the nodes with HostPorts.
Once we can properly preserve external IPs, you can turn this back into a plain Service.
When having a bunch of systems that act as WebSocket drones and a Load Balancer in front of those drones. When a WebSocket request comes into the LB it chooses a WebSocket drone, and the WebSocket is established. (I use AWS ELB tcp SSL-terminated at ELB)
Question:
Now does the created WebSocket go through the LB, or does the LB forward the WebSocket request to a WebSocket drone and thus there is a direct link between client and a WebSocket drone?
If the WebSocket connection goes through the LB, this would make the LB a huge bottleneck.
Removing the LB and handing clients a direct IP of a WebSocket drone could circumvent this bottleneck but requires creating this logic myself, which I'm planning to do (depending on this questions' answers).
So are my thoughts on how this works correct?
AWS ELB as LB
After looking at the possible duplicate suggested by Pavel K I conclude that the WebSocket connection will go through the AWS ELB, as in:
Browser <--WebSocket--> LB <--WebSocket--> WebSocketServer
This makes the ELB a bottleneck, what I would have wanted is:
Browser <--WebSocket--> WebSocketServer
Where the ELB is only used to give the client a hostname/IP of an available WebSocketServer.
DNS as LB
The above problem could be circumvented by balancing on DNS-level, as explained in the possible duplicate. Since that way DNS will give an IP of an available WebSocketServer when ws.myapp.com is requested.
Downside is that this would require constantly updating DNS with up/down WebSocketServer changes (if your app is elastic this becomes even more of a problem).
Custom LB
Another option could be to create a custom LB which constantly monitors WebSocketServers and gives back the IP of an available WebSocketServer when the client requests so.
Downside is that the client needs to perform a separate (AJAX) request to get the IP of an available WebSocketServer, whereas with AWS ELB the Load Balancing happens implicitly.
Conclusion
Choosing the better evil..
I'm reading up on SockJS node server. Documentation says:
Often WebSockets don't play nicely with proxies and load balancers. Deploying a SockJS server behind Nginx or Apache could be painful. Fortunately recent versions of an excellent load balancer HAProxy are able to proxy WebSocket connections. We propose to put HAProxy as a front line load balancer and use it to split SockJS traffic from normal HTTP data.
I'm curious if anyone can expand on the problem that is being solved by HAProxy in this case? Specifically:
Why websockets don't play nice with proxies and load balancers?
Why deploying Sockjs sever behind Apache is painful?
1. Why websockets don't play nice with proxies and load balancers?
I'd recommend you read this article on How HTML5 Web Sockets Interact With Proxy Servers by Peter Lubbers. It should cover everything you need to know about WebSocket and proxies - and thus, load balancers.
2. Why deploying Sockjs sever behind Apache is painful?
There is a module for handling WebSocket connections but at present Apache doesn't natively support WebSocket, nor does it look like it will any time soon based on this bug filed on apache - HTML5 Websocket implementation. The suggestion is that it actually fits the module pattern better.
So, it's "painful" simply because it's not easy - there's no official support and therefore it doesn't have the community use that it otherwise may have.
There may also be other pains in the SockJS has HTTP-based fallback transports. So you need to proxy both the WebSocket connections (using the apache-websocket module) and also HTTP requests when fallback is used.
Related to this: Nginx v1.3 was released in February with WebSocket support.
i would like to replace my node-http-proxy module with nginx proxy_pass module. Is it possible with new released nginx version, as i have read, that it supports HTTP/1.1 out of the box. I saw some threads struggeling with that problem, that websockets are not supported by nginx.
In my case im running several node projects in background and want to route my websocket connections from port 80 to 8000-8100, depending on domain. Is there a native way to do websocket proxy/reverse proxy without using the tcp_module addon?
I tried to setup an upstream in nginx.conf with proxy_passing to it, but if i try to connect to port 80 over websocket, i get an 502 Gateway error.
Anyone facing the same problem?
Does anyone have a working example for nginx + spcket.io, proxying over port 80?
No, this is not yet possible; nginx 1.2 incorporates stuff from the 1.1.x development branch which indeed includes HTTP/1.1 reverse proxying. Websocket connections are established using the HTTP/1.1 "Upgrade" header, but the fact that nginx now supports this kind of headers does not mean it supports websockets (websockets are a different protocol, not HTTP).
(I tried this myself using the 1.1.x branch (which I found to be stable enough for my purpose) and it doesn't work without the tcp_module)
Websockets will probably be supported in 1.3.x ( http://trac.nginx.org/nginx/roadmap ).
Your alternatives are:
keep using node-http-proxy
use nginx without tcp module; socket.io won't use websockets but something else (e.g. long polling)
nginx with tcp module: in this case I think you need an additional port for this module (never tried this myself)
put something else in front as a reverse proxy: I use HAProxy (which supports websockets) in front of nginx and node. Nginx now simply acts as a static fileserver, not a proxy. Varnish is another option, if you want additional caching.
In relation to NginX with TCP module there are few problems I have encountered.
But the most tricky one is trying to run your websockets with nginx on port 80 on EC2 instance.
I described whole configuration here
I have an event-machine websocket application (using the em-websocket gem) and it runs fine. The problem is that I need to deploy it using port 80 through nginx (can't compile it with tcp proxy module). Is it possible to use a simple nginx proxy_pass pointing to a thin server and have the thin server to pass the requests to my websocket server?
From what I understand you can't proxy websocket traffic with a proxy_pass.
Since web sockets are done over HTTP 1.1 connections (where the handshake and upgrade are completed), your backend needs to support HTTP 1.1, and from what I have researched, they break the HTTP 1.0 spec...
I've seen some people try to do the same thing with socket.io and HAProxy (see links). I would guess that you could try to swap out the socket.io with em-websockets and expect similar results.
1: http://www.letseehere.com/reverse-proxy-web-sockets
2: HAProxy + WebSocket Disconnection