Scaling a drupal site to handle 1000 authenticated reqests per second

Events happening in the community are now at Drupal community events on www.drupal.org.
ktrev's picture
      We are planning to make a Learning Management System with drupal.We have created a site which can run a single course at a time.

There are 84 modules installed in the site.

Our aim is to handle 1000 authenticated requests per second.
(This can be viewing the site or adding content to the site)

Our server details are as follows:
(this is a vm on one server)

Memory : 16GB
Processor: 8 core
OS: Ubuntu
Webserver : Ngnx
We have php-fpm with maria db as database server

We have installed APC and Memcache in the site.
(APC hit is close to 100% , memcache hits is close to 85%)

Whenever we run a jmeter test (That logins 100 users and visit certain urls . The test runs for 2 minutes. Total 10,100 requests are sent to server in this test.) the load of the server is increasing.

CPU % is : 75% user , 20-25% system and 0% idle.

Memcache is using around 27% cpu
Mysql using around 23% cpu
Each php-fpm process using around 5 % cpu
Nginx using around 7% cpu.

Memory used is around 6GB , rest 10GB is free.

We were able to reduce the cpu utilization by using authcache.But authcache doesnt help when you are inserting nodes to the site.In that case cpu% will again go up.

What is the best architecture to scale a drupal site that can handle around 200 node inserts in one second.

Should we use separate web server and database server?

Comments

peak or average?

znerol's picture

Our aim is to handle 1000 authenticated requests per second.

Peak or average?

But authcache doesn't help when you are inserting nodes to the site.

This is not exactly a problem with authcache but with the overzealous cache-clearing strategy implemented in Drupal core. See the "Integrate with Cache Expiration module" chapter in the Authcache 2 tuning guide for an explanation of the problem, as well as a solution.

Peak or average? Peak

ktrev's picture

Peak or average?

Peak

Is peak authenticated traffic

znerol's picture

Is peak authenticated traffic read-only or read-write? I.e. do you expect that your users will submit content at peak times or do they just consume content prepared in advance?

Its read-write.They may read

ktrev's picture

Its read-write.They may read the content and insert new nodes or comments.

When you need to optimize for

znerol's picture

When you need to optimize for read-write authenticated traffic, then you need to decide between two very different strategies:

  • Implement Authcache and work around the core page cache clearing strategy. Then optionally upgrade to Varnish and ESI. However this strategy will not work if the traffic is concentrated onto a few pages only, all of them with very frequent writes (i.e. hot forum topic pattern).
  • Optimize your site and server with one of many approaches not involving page-level caching.

Optimize your site and server

ktrev's picture

Optimize your site and server with one of many approaches not involving page-level caching.

Can you please explain more on this?

Regrettably no

znerol's picture

Can you please explain more on this?

No, regrettably I cannot. I'm not an expert in this area.

start with your mysql server:

Andre-B's picture
  1. verifiy that your tables use innoDB as a storage engine since it supports row locking, while myisam does table locking
  2. optimize your mysql server: checkout mysqltuner (http://mysqltuner.pl)

verifiy that your tables use

ktrev's picture

verifiy that your tables use innoDB as a storage engine since it supports row locking, while myisam does table locking

All the tables are innodb(its a drupal 7 site)

optimize your mysql server: checkout mysqltuner

We have installed mysqltuner in our server and have made changes in the my.cnf file according to the recommendations

so as far as I can tell you

Andre-B's picture

so as far as I can tell you still cant reach the desired node inserts/ per second. I guess the only way to gain more speed without switching the mysql backend servers (by moving them to a own dedicated host + faster hdds / ssds) is reducing the amount of write requests. this can be done by disabling the revision table (if you have revisioning enabled) reducing the amount of fields written to and analysing what else is cause of the load. try xhprof for profiling, new relic also gives in depth statistics.

Unused memory is wasted memory

Brian Altenhofel's picture

Memory used is around 6GB , rest 10GB is free.

That's a lot of free memory.

If it were me, I'd be running DB and web on separate VMs. That will allow your webservers to scale horizontally without your DB servers, and if you're leveraging caching tools properly you won't need to scale DB near as fast as web.

For HA/redundancy, you might want to consider running your DB in a Galera cluster. I'm sure MariaDB supports it, I'm just not that intimate with MariaDB (we're a Percona XtraDB shop).

For a MySQL configuration, you can get a pretty good baseline from https://tools.percona.com/wizard whether you're using vanilla, Percona, Maria, or practically any other MySQL drop-in replacement. What I've found through experience is that you might want to leave 15% or so of memory headroom for bursts with very inefficient queries if you're not running swap. You'll still need to fine-tune for your application if you want to squeeze every ounce of performance out of it, but the generated configuration from that site is already good enough to question the value of fine-tuning over throwing more hardware at it. By the way, with applications like Drupal that do several writes on every page request, you're sometimes better off to not use the query cache because your potential gains in the query cache are outweighed by the additional processing to replace those one-time queries in the cache. As always, test and test.

For PHP-FPM, use a static number of children. It won't spend extra CPU time spawning new children like it does under ondemand. And the longer your children can last (more requests before killing and respawning), the less respawning, though that has to be balanced against memory issues (the longer children last, the more junk one-time-use or leaked memory gets taken up).

Now the really big question is... have you tried edge side includes? Basically, with ESI, Varnish caches the parts of pages that never change plus blocks that tell it "call Drupal for the stuff that goes here". For example, on an ecommerce site the homepage would rarely change except for "hello ", current cart total, and "suggested for you". The rest of the page could be held in Varnish while those three features are served via edge side includes. Varnish quickly assembles the version of the page to serve for that user, and PHP doesn't have to build the entire page for every user just because three things happen to be unique.

Can we use ESI and varnish

ktrev's picture

Can we use ESI and varnish for authenticated users?
All the users in our site are authenticated users.No anonymous users are there.

Authenticated users is

Brian Altenhofel's picture

Authenticated users is exactly what ESI is for.

Log entries

sam moore's picture

Perhaps you've already done this, but I like to replace dblog (Watchdog) with syslog on a production site.
It means your log entries will be written to the system logs rather than the database.

This makes it a little less convenient to check your log activity, which is why I don't do it on a dev site, but the benefit is that you're asking the database to do a lot less. I have a site with 90k users that benefited greatly from this simple switch.

Just turn off the dblog module and turn on syslog.
https://drupal.org/documentation/modules/syslog

Just noticed there's a thing called Advanced Syslog, sponsored by Acquia - I have not checked it out yet:
https://drupal.org/project/syslog_advancedc

HTH...

What version of MySQL are you

Jamie Holly's picture

What version of MySQL are you using? I would suggest going to at least 5.5.8. During the early stages of 5.5 a lot was of improvements went into the flushing part of the code, and they really nailed it in 5.5.8.

For architecture, I would highly recommend moving the database to it's own server. That way you can upgrade the hardware that you really need to for a database server, especially your drives (adding to the RAID or moving to SSD). If anything a separate database server makes it a lot easier to isolate bottlenecks, as you now have two dedicated servers, each with its own purpose.


HollyIT - Grab the Netbeans Drupal Development Tool at GitHub.

You should definitely

bdsupport's picture

You should definitely separate your system to several services of data processing, then Drupal only for glue of the services, If you want to archive the 1000 tps goal.

How would you do that? Drupal

littletiger's picture

How would you do that? Drupal as the glue could be a bottleneck for slower separate services, it seems.

Optimize the database

mikeytown2's picture

I would make sure your database is using READ COMMITTED for MySQL transactions: https://groups.drupal.org/node/415883

Put the DB on a server that has SSDs and a enough ram so the entire DB fits in it.

Make sure your DB is tuned:
http://www.mysqlperformanceblog.com/2007/11/01/innodb-performance-optimi...

Can we switch off

ktrev's picture

Can we switch off transactions in mysql.
Or turn off locking completely.Will that help to increase the performance of database

Read Uncommitted

mikeytown2's picture

I've never fully tested it but it should do effectively do that
https://groups.drupal.org/node/166364

Change the architecture

goldenflower's picture

Your requirment is "Our aim is to handle 1000 authenticated requests per second." And "site that can handle around 200 node inserts in one second." here you are still playing with Mysql ?

Here i advice to go with MongoDB or elasticsearch it will fullfill your need.

Can we replace the entire

ktrev's picture

Can we replace the entire drupal database with mongodb.
I thought only certain things like block,field etc can be stored in mongodb.

Mongo DB Project

mikeytown2's picture

https://drupal.org/project/mongodb

Generally anything with Mongo DB involves chx. If you want to know what is possible with Mongo & Drupal this is the person to talk to.

It's not always the best

jdidelet's picture

It's not always the best option to handle everything on the server side. Sometime change your point of view will let you to handle the problem in a different way.

Can you imagine to resolve your problem more on the client side? Build some client / server architecture by moving some transaction on client side with asynchrone architecture with your server can help you to deal with node insert problem (by using backbone.js for example).


Julien Didelet
Founder
Weblaa.com

Remove revisions

ktrev's picture

Is there any way to remove revisions of node and fields in drupal 7.That will reduce a lot of insert queries while creating a node right?
In our site there is no need to maintain revisions.

I read the following discussion but didnt get a proper solution for this.
https://drupal.org/node/289466

I created a module as mentioned in the comment
https://drupal.org/node/289466#comment-6408330
but still it creates revision when a node is created

We have separated the web

ktrev's picture

We have separated the web server and data base server now.

When we ran the same test paln (login 100 users and visit some pages) the web server's cpu% is going up to 65%.

Each apache process is taking about 9% of cpu.(In the previous setup we were using nginx, now we moved to apache)

Caching

wwhurley's picture

How much of the site can be cached on a global or per-role basis? If there are a lot of per-role items you could use Varnish and add roles to vcl_hash and pull the per-user stuff in with AJAX / auth_cache.