Normally, if we need to scale a Meteor app, we need to put it behind a load balancer like Nginx or HaProxy. We need to configure it properly for Meteor and manage it separately. If we need to add or remove instances, then we need to change the configuration again and restart the load balancer.
” What if we could load-balance Meteor apps by just installing a Meteor package? And if it could detect new or removed instances and route traffic accordingly, that’d be great. “
We are proud to say, we now have a solution that can do things mentioned above. It’s Cluster. Let’s see how we can use it.
Using cluster is pretty easy. First, install the following package into your Meteor app:
meteor add meteorhacks:cluster
Then, when you are running your app, export the following environment variables:
export CLUSTER_DISCOVERY_URL=mongodb://mongo-url export CLUSTER_SERVICE=web # define this as a web service export CLUSTER_ENDPOINT_URL=http://ipaddresss:port
Cluster uses MongoDB to communicate between all the Meteor instances of your app. To do this, you can use your app’s current
MONGO_URL. But if possible, use a separate replica set.
CLUSTER_ENDPOINT_URL is the direct URL for the Meteor app running on your server. It could be a private URL, but all the instances of your app should be able to access it.
Now, deploy as many as instances of your app as possible and send the traffic to an instance of your cluster. That’s all you’ve to do.
When you need to scale up, simply add more instances. There is no need to configure anything. Cluster will detect new instances and route the traffic to new servers. You can also remove running instances without affecting other instances or your app.
If you need more info on this, watch this live demo.
If you are using Meteor Up to deploy your app, you can use a configuration like this.
With this, you don’t need to configure
CLUSTER_ENDPOINT_URL. Meteor up set it automatically. (Make sure to update Meteor Up to the latest version.)
This looks great. But with this setup, traffic is proxied through a single instance. If we’ve a high-traffic Meteor app, this will be an issue. Normally to solve such an issue, we would add multiple load balancers with DNS load-balancing.
Let’s think in a different way.
” What if every instance of your app were a load balancer? Then we wouldn’t need to worry about this issue anymore. “
With cluster, every Meteor instance becomes a load balancer. So, if we can find a way to send traffic to these instances, we’ve the answer for our question. We can do this in two ways.
This is the simplest solution. Configure your domain’s DNS to resolve the DNS into multiple instances of your app. That’s all.
With this solution, if one balancer goes down, you need to remove that DNS record. For that you can use a DNS solution like Route53, which has health-checking support.
We’ve another way to do this. We can configure multiple instances in our cluster as balancers. A balancer is a special type of instance that can accept DDP traffic directly from the browser.
Once you mark some of your instances as balancers, the browser will send DDP traffic directly to these individual instances.
DDP is the Meteor’s real-time protocol. Currently, Meteor implements it using SockJS. So, DDP traffic is SockJS traffic. Which is normally WebSockets or long polling.
It’s very easy to configure an instance as a balancer. Just expose the following environment variable when starting your app:
This balancer URL needs to be a public URL, so you may need to create a DNS entry.
With this approach, we can add and remove balancers as we need and cluster will take care of the routing accordingly.
For production, we prefer to use both of the above approaches for load-balancing. The DNS-based approach makes our app highly available and the balancer-based approach allows us to add and remove instances very quickly.
It’s also very important to use a MongoDB Replica Set for the
CLUSTER_DISCOVERY_URL for high availability.
We are currently using cluster in production for both Kadira and BulletProof Meteor. We are satisfied with its performance and now we don’t need to monitor and manage a Nginx layer. We are planning a performance test and we’ll publish the results soon.
EDIT: We did a performance test. Here are the results.
Cluster is not just a load balancer, it’s a service discovery solution for Meteor. It is well suited for microservices. We’ll write a blog post about that soon. In the meantime, try to follow these resources.