First off, +1 to Alex' answers. Really sound advice so far.
Also agreeing with the assessment that a high number of DB connections might only be a symptom. What is the load average on your app servers displaying? When we had lots of external wait times on NFS, we had load averages going through the roof.
Some additions regarding...
...
Apache / MPM-Event & PHP-FPM:
- Remember to ensure that the Zend Opcache is enabled.
- In conclusion, remember to take shared memory into account when calculating the average size of an apache process.
- Save up some memory in your calculations for the pool of php processes from the FPM. We found the "static" setting to be most performant.
... Sessions / Caching / Locks & NFS
- Sessions on NFS are an absolute nightmare regarding speed. DB sessions are an improvement but won't really help when number of parallel DB connections is your issue. Go for Redis.
- MUC should also be set up in Redis, yes. This can significantly speed up page load times. Localcache should reside on app
server locally.
- Temp-Directory should also be shared by all app servers.
- Locks in DB might bring a little speed, but we've found some issues with DB locks never being released (instead waiting for expiry date) and thus parallel cronjobs being made impossible.
...
Database optimization options:
- Single largest performance factor we had when optimizing our
database was disabling the query cache.
- For high connection counts, you might run into issues with either your my.cnf setting "max_connections" or "open_files_limit". We've set the first to 3k and the second to ~32k.
- You will most likely have to increase the hard and soft limits for opened files on the OS level for the mysql user as well.
Our changes to /etc/apache2/mods-available/mpm_event.conf:
<IfModule mpm_event_module>
StartServers 4
ServerLimit 24
MinSpareThreads 64
MaxSpareThreads 512
ThreadLimit 128
ThreadsPerChild 72
MaxRequestWorkers 1152
MaxConnectionsPerChild 16384
</IfModule>
Our changes to /etc/php/7.2/fpm/pool.d/www.conf:
pm = static
pm.max_children = 1024
pm.max_requests = 1500
Our changes to /etc/mysql/my.cnf for disabling the query cache:
[mysqld]
query_cache_type = 0
query_cache_size = 0
Hopefully, any of this helps.
Cheers
Thorsten