Server is dying due to traffic. What can I do?


#1

My app is experiencing a spike in visitors (~120 concurrent users) and now it takes minutes to fetch data from MongoDB. What can I do?

Description of problem:

  1. Go to https://remotebase.io
  2. The page loads fine, but the loading spinner shows indefinitely. Sometimes it works.

EDIT

hosted on digital ocean NYC:

  • 2GBMemory
  • 2 CoreProcessor
  • 40GBSSD Disk
  • 3TBTransfer

System load: 1.63 Processes: 103
Usage of /: 9.9% of 39.25GB Users logged in: 0
Memory usage: 31% IP address for eth0: xxx
Swap usage: 0% IP address for docker0: xxx


How I Migrated My App from Meteor
#2

haha sorry I made a post here about your post, looks like some others noticed too.

give us some background on what your deployment is.

galaxy? digital ocean? nodechef?
where is your db hosted? etc…


#3

@cstrat I just edited the post to provide more info on deployment. Feels good to showcase Meteor on HN. (It’s also on Product Hunt now)


#4

wow and only 30 concurrent users causing the db issues?
you’ve got pretty decent specs on that droplet.
i’ve had half that many concurrent on a $10 droplet without any issue.


#5

@cstrat If I moved to Galaxy, would it help? If so, how much downtime should I expect?


#6

You left out a key piece. Where is the db hosted? Do you have a mongo replica set? Did you enable the MONGO_OPLOG_URL setting for meteor?

You say the db seems slow, do you have indexes in place?


#7

Not sure if that would help, you must have much more than 30 concurrent users.
If you really only had 30 concurrent users, you might need to update your app with some optimisation… like Josh said, your DB might not be correctly indexed, you might have some costly functions on subscription. Have you got Kadira running with reporting? I checked and it doesnt look like you have Kadira installed. Its very useful for checking to see if something funny is happening.

Galaxy works great, but you would need to migrate your database to a 3rd party host as Galaxy doesn’t come with DB.

NodeChef is a great option it comes with DB with oplog support. I currently use NodeChef and stopped using Galaxy a few months ago.

You would need to migrate your DB over to the NodeChef hosted DB. Downtime would be as long as it takes to bring up the new host and change DNS. Minimal downtime if you setup the new environment in parallel and update DNS.


#8

@joshowens I am hosting in the same VPS. I did not enable MONGO_OPLOG_URL because I do not need real time updates for my app. I did not set up mongo replica set. Would it solve the problem? Or should I migrate to third party providers such as compose.io?


#9

That server will only give your 2 threads. Meteor in the background will spawn a process to poll even if oplog is enabled. Your node.js event loop also needs a thread to dispatch events. Your mongodb process ends up spinning a new thread per socket, Your nginx also needs threads.

isolate your front end on server nginx or whatever on a seperate thread. Put mongodb on a server with at least 8 threads. And then spread out your app droplets.

Note there are paas providers out there today that will do this for u.


#10

You’re on a very sub-optimal setup with a single droplet in DO. It will be a lot of effort to scale manually (ie. Load Balancer setup, Mongo replica setup) It will be much easier for you to use a PaaS (e.g. nodechef, some instructions that might help here: http://blog.trombone.io/setting-up-continuous-deployment-with-meteor/)

You can probably switch in a few hours, steps:

  • redeploy app
  • open up your mongo port / firewall to nodechef
  • import using the nodechef tool
  • switch DNS over

You could probably replicate directly from your DO droplet as you do the DB migration instead to minimize / get to zero downtime if necessary.

Galaxy + compose.io are an alternative option (but a little more expensive)


#11

I do not know, but sounds like you have build your app to be very heavy, because 120 user is nothing when you are not even using reactive features. Btw, can Meteor even take advance of two cores without running two instances on same machine?


#12

Node.js is single threaded. you will have to run multiple instances and so on.

I am now able to see the database entries but app takes 40 seconds to load. The database appears to have only like 500 documents or so in it. Something does not seem right.


#13

Using nginx proxying (for example), it’s quite easy to run more than one nodejs process per box. In fact a rule-of-thumb would be to reserve a couple of cores and then allocate 2 per core to nodejs processes. However, the issue then becomes one of ensuring that the app you have developed will run without problems if there are multiple server instances present. Naively spinning up a handful of server processes may mean problems with multiple oplog tails, previously atomic actions now becoming race conditions, etc.


#14

Another thing I am wondering is why you are using Meteor if you do not need a framework supporting the reactive data. Of course Meteor if damn fast easy, but I would rather use PHP for app if I did not need reactiviness as I think pub/sub quite heavy stuff.


#15

Take a look at my article on scaling:

No need to leave DigitalOcean. Setup nginx and use it as a load balancer. You can stick to 512MB droplets. Multicore droplets won’t help you. You don’t need more than 1GB RAM either (and 512MB should also be fine). You’ll hit a CPU bottleneck before you run out of RAM.

Some pointers:

  1. Use Kadira!
  2. Use indexes for your DB.
  3. Use Oplog even if your app doesn’t need to be realtime. It means your app won’t have to poll your database every 10 seconds.
  4. Use Compose.io or MongoLab for your database hosting. Too much trouble to deal with yourself.

#16

Meteor will chew up your CPU doing poll/diff unless you turn on OPLOG. Pretty sure you can say {reactive: false} on your server side publications to turn off the poll/diff at least.

In the meantime, try watching these videos to help out with using Kadira and getting some Mongo Indexes in place:

Sadly, until 1.4, you won’t get the queryPlanner using explain. You can always install Mongo 3.0 on your system and run it yourself and set your local MONGO_URL to hit your local mongo…


#17

have you tried to run Kadira so that you can better understand whatever your bottlenecks are?


#18

I think you’ve got plenty of suggestions in here @sungwoncho, but just for reference, from here (UK) the page does seem to be loading fine now.


#19

What ended up happening @sungwoncho?


#20

@joshowens I realized my app doesn’t really need websocket, so I wrote it again with a simple stack without Meteor.

Rewriting was very fast because all actions in my React components were decoupled from Meteor (using Mantra, all actions are injected). And my app is relatively small.

I haven’t deployed the new version yet. In the meantime, I just vertically scaled the server by purchasing more computing power. But your advice of setting MONGO_OPLOG_URL and indexing MongoDB was helpful and I will make sure to follow it next time I ship a Meteor project.