How to load balance users over an ejabberd cluster? - xmpp

I need to cater for 20,000 connected users in a 4-node ejabberd cluster. How would you distribute incoming connections over multiple ejabberd nodes?

To load balance XMPP TCP/IP traffic, you simply need to but a TCP/IP load balancer. From HAProxy, to Amazon LBS or BIGIP, choose your favorite one.

A way to load balancing without introducing SPOFs is to use multiple SRV records.
IF the clients you are providing the service to support it (i.e. they perform DNS queries to _xmpp-client._tcp.yourdomain), then you get load balancing (with "weights" inside the same priority group) and failover too (assigning a lower priority to a failover group).

Related

Kubernetes how to load balance EXTERNAL persistent tcp connections?

I'm having an issue with load balancing persistent tcp connections to my kubernetes replicas.
I have Unity3D clients outside of the kubernetes cluster.
My cluster is a baremetal cluster with metallb installed composed out of 3 nodes: 1 master and 2 workers.
As I have read there are two approaches:
1) client connects to all replicas and each time it needs to send a request it will do so on a random connection out of those that it has previously established. Periodically, it refreshes connections (in case autoscale happened or some of the persistent connections died).
The problem here is, I'm not sure how to access all replicas externally, headless services cannot be exposed externally.
2) service mesh ? I have vaguely read/understood that they might establish persistent tcp on your behalf. So something like this :
unity3d client <----persistent connection ---> controller <---persistent connection----> replicas
However, I'm not sure how to accomplish this and I'm not sure what will happen if the controller itself fails, will all the clients get their connections dropped ? As I see it, it will come down to the same issue as the one from 1), which is allowing a client to connect to multiple different replicas at the same time with a persistent TCP connection.
Part of question comes as a complement to this : https://learnk8s.io/kubernetes-long-lived-connections
In order to enable external traffic to your cluster you need an Ingress Gateway. Your ingress gateway could be the standard nginx Ingress, a gateway provided by a mesh like the Istio Gateway or a more specialized edge gateway like ambassador, traefik, kong, gloo, etc.
There are at least two ways you can perform load balancing in K8s:
Using a Service resource which is just a set of iptables rules managed by the kube-proxy process. This is L4 load balancing only. No L7 application protocols like HTTP2 or gRPC are supported. Depending on your case, this type of LB might not be ideal for long lived connections as connections will rarely be closed.
Using the L7 load balancing offered by any of the ingress controllers which will skip the iptables routing (using a headless Service) and allow for more advanced load balancing algorithms.
In order to benefit from the latter case you still need to ensure that connections are eventually terminated which is often done from the client to the proxy (while reusing connections from the proxy to the upstream). I'm not familiar with Unity3D connections but if terminating them is not an option you won't be able to do much load balancing after all.
When the controller fails, connections will be dropped and your client could either graciously re-attempt the connection or panic. It depends on how you code it.

load balancing postgres instances via aws network balancer possible?

We have an application that has multiple postgres databases (that are guaranteed to be in sync) installed on AWS EC2 instances in different availability zones. I would like to abstract them behind a single DNS so that, if one of the EC2 instances crashes, the clients can still access the db. I am wondering if I can use an AWS network load balancer to load balance my databases? Why or why not? If not, is there any other standard, easy-to-implement solution that I can use? (I am aware of http://www.pgpool.net/mediawiki/index.php/Main_Page for example. However, am leery of using something that I have to setup myself, especially since I would have to replicate pgpool instances as well...)
Having just tried it myself, it does seem you can set up a network load balancer to load balance your databases. My production setup uses patroni to manage failover, and patroni provides an HTTP API for health checks. The master returns a 200 response, while the replicas return a 503. This works fine for my use case, where the replicas are there just for failover, not for replicated reads. I'm assuming you could come up with some code that returns a successful response for health checks based on your needs.
I configured the load balancer to listen to port 5432 and the health checks to connect on port 8008. I modified the security group for the postgres instances to allow connections from my VPC's IP range, since the NLB doesn't have security groups. Connecting via psql to the NLB's DNS name worked as expected.
Though it works, I think I'll stick with my current setup, which has a PgBouncer running on each application instance (so no need to worry managing a pool of bouncer instances) with consul-template updating pgbouncer.ini and reloading PgBouncer when the leader key changes in consul.

Pgbouncer - Can I use pgbouncer for load balancing the request in postgres cluster?

Currently, I am using pgbouncer for connection pooling in the postgresql cluster. I just want to make sure, Whether it is possible to load balance request between the nodes in the postgresql cluster using pgbouncer.
Now there's pgbouncer-rr-patch(pgbouncer fork by AWS) that can do load balancing:
Routing: intelligently send queries to different database servers from one client connection; use it to partition or load balance across multiple servers/clusters.
From the PgBouncer FAQ
How to load-balance queries between several servers?
PgBouncer does not have internal multi-host configuration. It is possible via some external tools:
DNS round-robin. Use several IPs behind one DNS name. PgBouncer does not look up DNS each time new connection is launched. Instead it caches all IPs and does round-robin internally. Note: if there is more than 8 IPs behind one name, the DNS backend must support EDNS0 protocol. See README for details.
Use a TCP connection load-balancer. Either LVS or HAProxy seem to be good choices. On PgBouncer side it may be good idea to make server_lifetime smaller and also turn server_round_robin on - by default idle connections are reused by LIFO algorithm which may work not so well when load-balancing is needed

Prevent jboss application server from getting picked up by load balancer?

There are two mod cluster load balancers running in my network and I want to exclude one from picking up my jboss application server nodes.
I want the nodes to be served exclusively by one of the balancers. How do I achieve this?
I solved this problem by changing the multicast ip:port in the load balancer and jboss application servers.
The multicast was set to default for all instances and thus why both load balancers were picking up my nodes. By setting the multicast address to a specific ip:port combination in one of the load balancers and the application servers, I was able to restrict application servers to the one load balancer.

How does clustering of ejabberd nodes work?

Does it work like master-slave way, where xmpp clients connect to a master node, and master node uses the slave nodes to distribute the load?
If not, how load balancing can be done after clustering of ejabberd nodes?
All nodes are equal and there is no master. State is kept in mnesia or mysql (like roster table, session etc.). Configuration is replicated over all nodes.
Usually it means there is LB in front of the whole cluster. One cluster is represented by one domain. You can have more and federate them.