📜 ⬆️ ⬇️

$ 10 VPS Optimization Experience for WordPress Personal Network

This small article is devoted to the description of my actions to bring the $ 10 / month VPS into acceptable conditions for the personal network of WordPress sites in single and network mode (WordPress Network Mode).

Intro


So, my dear high-tech specialists and casual readers, this story began at the end of April 2012, when my favorite city monopolist provider flatly refused me to continue placing my three-nuclear athlon in my rack.

I live in a small resort town (3 thousand. We are local and 50 thousand. Saw-here-in-summer) and most of my personal projects are dedicated to my native and beloved city. A pair of urban webcams, weather, directories, etc. In addition, I am still a bit struggling for justice and rights: I organized a small projector on the TV domain - we make reports about bezpredel officials, etc. ...

So what am I talking about ... oh yeah! It was, therefore, a two-unit server (it’s hard to call him and the server) completely free in the rack at the provider, who had as many as 3 racks and 2 of them were empty. Why free? Because I myself helped this provider to develop corporate websites. In addition, there are simply no other people with my similar knowledge in our small town - the distant periphery, smart people quickly leave for Moscow and other foreign countries.
')
In general, my projects were spinning on the AthlonX3 / 4Gb RAM and I didn’t bother at all on the issue of optimization, setting up - I was making Saitics on my favorite wordpress and I didn’t even think that the freebie would end.

After another publication of amateur reportage-nedokompromat on the local mayor, the provider’s director approached me (from the same party as the mayor) and recommended to take information from the server within 24 hours. Compromise something lay on it. Another good thing that came up and said.

The day did not remain. And my projectors already sat well in the SERP, and did not want to lose positions ... Essence - in 12 hours the first cheap VPS for $ 10 in Germany was found (if only not in my country), software was delivered from some repositories, the data was overwhelmed, DNS'y rewrote and with grief in half, more or less worked, though barely moving.

By the way, the restriction of $ 10 did not just happen - it was this amount that I had at that time on webmoney, dripped into Direct. Actually, this budget has risen by only $ 2 - for an additional IP. Now this VPS costs me $ 12.

Just to see the search engines


VPS parameters: CentOS 5, XEN, 2.8Ghz, 256 Mb RAM, 15 GB SATA, traffic - unlimited. In a hurry, it was installed nginx, apache + mod_php + eaccelerator, mysql, memcache. Imagine - time is ticking, it is necessary to pour about 12 gig from one country to another, and also install, configure, and preferably so that the search engines would not understand anything :)

I’m kind of a non-programmer — so-so, a lamo-coder cattle , and not an administrator — I know yum install, yum erase, make && make install ... But then I more or less have the indispensable skill of google-learning.

Initially, I put apache front end. It was something :) ab2 from the old server showed no more than 1.4 requests per second. Nginx I then saw for the first time. I put it, read it (a bit, there was no time) somehow accumulating configs - it started. And even became faster. After installing eaccelerator, the result of ab2 at 6 rps seemed to me to be just great and I left it all the way.

No mysqltuner.pl, no apache mpm selection / optimization, even nginx was eating so much memory that 80% of a clogged swap seemed normal to me. But apparently it was because of the stress :) In my opinion, the sites did not slow down, well, I thought a bit. But knowing my audience - I knew perfectly well that my visitors would not go anywhere.

Something is really very slow


Saytiki grew and widened - slowly, but having gone to the TOP-5 of Google and Yandex for inquiries regarding my resort city, sites in the summer became often unavailable (RAM / SWAP - 100%). Since there was no time to do optimization in the summer, I postponed the task to the end of the year.

From the end of April to December 7, in such a mode, the Saitiki’s “barely goes” have accumulated such statistics:

.SU is a WordPress Network - a grid of sites dedicated to my city. The rest are “single” WordPress. PS When everything is divided into subdomains - it is more convenient to maintain. By the way, I only today read about making static on a subdomain, I will try, but later.

(I ask in the comments not to describe in detail how Wordpress is bad, its code and what resource consumption it has. I ran into it myself, like head against a wall. Perhaps this is the essence of the next article.)

By the way, it will be important to mention the fact that during this period I started to have clients in the city who needed to make a website. I especially did not bother - stamped on WP. And at one point, with the raising of the next site, this whole bunch of WP began to work very badly.

I read, put, config, tyunyu, ride, ride


yum update brought a lot of updates. But they did not help much, and they could not help. I knew that I had to switch to php-fpm and start caching. For my case, caching is most relevant, since the absolute majority of my sites are almost static - everyone is happy with expire in a couple of weeks. And those sites that are not static (and this is, first of all, a heavy WordPress Network), you can neatly tweak so that the cache is updated strictly where it is necessary and at that time in which it is necessary.

In general, I didn't want to put php-fpm without tambourines. Through the heels of the other repositories, I found a compiled package, with all the options I needed. In general, it was possible from sorts - but not wanted. Installed, quickly configured ... httpd stop && php-fpm start - LLC! 9 rps! Go to the record! Joke of course.

php-frm costs, and eaccelerator had to be demolished - not compatible, you need a new one. Google-learning - this accelerator is already outdated. yum install php-pecl-apc. It was put, again not without tambourines - readjust, it was got. Page generation began to work somehow very strange. The first opening is long - then for some time the sites begin to fly. Then blunt. Then fly again. Long Google-learning led me to the description of using APC on Facebook. It turned out to be useful, much became clear.

Configured php-fpm. I climb the site - then suddenly 502, F5, F5, 504. What a canoe! php-fpm stops responding after a while. Again, I read - little memory, put more. Better, but after some time again 502. I read, I read, memleaks, deadlocks, the complete set.

I pull APC, I put XCache. It did not start at all. Okay. We must think and read. I put back the APC. I'm setting up again. With other config while it ceased to take off. And the speed has risen significantly - the time for generating especially simple pages has decreased several times (2.7 s -> 0.8 s). Yes, guys, 2,7s - this is a pumped up WordPress simple page. And if you hang up the plug-ins - like I have on .TV - so there is only generation 19-25s without optimization at all.

And then suddenly I understood! First you need to configure all the district software, which is run-in among many people and perfectly copes with its duties. I quit picking php-fpm + apc - and started tuning from the very front edge - from the network stack of the operating system. There are many recommendations in the network, everything is described in detail - I will not repeat it. Configured, checked, nginx began to move much faster, and mysql accelerated a bit.

Next, nginx - reduced the number of workers to 1 and concatenations to 8196. Turned on sendfile and aio, checked the directio value. Spun the output_buffers according to the manual. And so! I got a little more than 60 rps on static. I thought that the first victory is and must be continued. Similarly, walked through php-fpm (not touching apc so far). Limits, limits. Then mysql. This helped me mysqltuner.pl and of course of.Manual. After increasing the caches and decreasing the number of connections, all the work of the VPS was significantly accelerated, load average fell, a third of the memory was freed.

However, php-fpm continued to fall periodically. I read a lot of links in Google. APC is great - but he is so good. Let's return to it a bit later.

I want to sleep, and the sites are falling


As an intermediate solution, I decided to try to put a caching plug-in on all WordPress - W3-Total-Cache. For the future, I wanted to use nginx fastcgi cache with the cache purge module (I tried it — I didn’t like it; I’m writing below). W3TC was chosen as “fast-put-before-sleep,” and in my case it was the best solution. If the back-end falls - the front-end will feed people with statics (but not everything is so smooth).

Preparing W3TC as follows - Page cache: Disk Enchanced, Database cache - APC, Object cache - APC. Expire - to taste. On the WordPress code, I found a semi-working config for distributing page cache from W3TC directly from the front end (via nginx without starting php-fpm), I finalized it. Restart and only here I begin to understand what it means when sites work quickly. Statics flies out from under nginx and very quickly. On pure static, I got in ab2 up to 800 (!!!) rps

Of course, when I sat down to write this text - I already know that ab2 is bad, and siege is good. But at that time I did not know that. But still! Compare the initial show 1.4 and intermediate 800! But that was not the end, it had just begun! But only the next morning.

The morning is wiser than the evening


I woke up in the morning from another SMS Yandex, that the sites have long been out of touch. php-fpm did not respond to front-end requests. As a result of a long tinkering, restarting and reconfiguration, it turned out that cleaning user cache in apc causes some kind of dead lock; as a result, php-fpm stops processing requests. And here I approached the fact that the VPS stood, but was not used properly. Memcached and the corresponding php extension is memcache. Database cache and Object cache in W3TC was urgently migrated to Memcached. Of course, I read that memcached on a localhost does not give a performance boost compared to disk cache, but in my case the increase was very noticeable. Without tests - visually. Apparently this is due to a significant IO on the VPS.

php-fpm ALMOST stopped working, but it's almost. I did not like it - I can not always sit and check whether it works or not. Yes, and how so - like the production solution (tiny, but still), and the back end falls. Poorly. I downloaded the last APC compile with different options. Spinlocks showed the highest performance, but they are also the most sloppy (experimental ones). In general, when cleaning user cache (db, object in the context of wp + w3t), it didn’t affect the deadlocks, as it hangs. As a result, the user cache lies on memcached, and behaves smartly.

What I just did not try. I stopped at the end of the APC with mmap memory and pthread mutex Locks locking. I wrote a small script for crown, which once a minute checks the vividness of php-fpm. And put the fastcgi timeout in nginx in 2 minutes. Until suddenly a tupnyak - php-fpm fell - the user will wait a bit (taking into account my audience). I have not found another solution yet - if someone came across or knows - offer.

A separate song is nginx fastcgi cache. After its initialization, the nginx cache manager consumed 60 MB of memory from the total 256, showed performance lower than just nginx + w3tc (pagecache disk enhanced) and was safely disabled.

Results of optimization procedures


Now I’ve stopped at the following software: nginx 1.3.8, php 5.3.19 (+ php-fpm), apc 3.1.19, memcached 1.4.15, mysql 5.0.95 serving several single WordPress and one WordPress Network with activated W3 plugin Total cache

PHP sessions are in memcached, user cache (db, object) -> memcached, apc.XXXXXX in / dev / shm /, apc works solely as an optimizer and cache for the php opcode.

ab2 on fully cached sites gives about 800 rps on block-cached about 200 rps (rounded down).

Update from today, 12/12/2012

I was really tired of the constantly falling PHP-FPM. But today, all night I had a terrific sex parsing configuration keys before compiling PHP 5.4.9. While I figured out how to build it, and its modules from the sources, I thought the roof would move down. Yele collected, launched. Sites work. User cache in APC does not cause deadlock. At the time of the publication update - PHP-FPM Uptime 9 hours and 15 minutes without a single complaint. However, I still could not understand how PHP can be compiled in a minimal working build under WordPress. Now all the modules are compiled into PHP itself and I don’t know how to turn them off correctly. Dear community, tell me please, how can this be done? What real modules are needed for optimal WordPress operation with maximum minimization of PHP binaries?

php -m output
# php -m
[PHP Modules]
apc
bcmath
calendar
Core
ctype
curl
date
dom
ereg
exif
fileinfo
filter
ftp
gd
gettext
hash
iconv
intl
json
libxml
mbstring
mcrypt
memcache
mhash
mysql
mysqli
mysqlnd
openssl
pcre
posix
Reflection
session
Simplexml
sockets
SPL
standard
sysvmsg
sysvsem
sysvshm
tokenizer
xml
zip
zlib


Evening addition of the same day:

Thanks to the instructions of aktuba , I noticed the importance of the server’s reaction to the If-Modified-Since or If-None-Match headers. For some reason, I haven’t given 304 Not Modified to Nginx or W3TC in appropriate cases. As a result, I added directives to the nginx configuration for a single WP site site: if_modified_since before; etag on; This has a very positive effect on reducing the number of requests to the server. I will look at the statistics of requests and turn it on on all sites.

In addition, the directive worker_aio_requests 128 has been added to the nginx configuration events context; to increase the performance of aio.

On ab synthetic, the following results were obtained:
ab -n 10000 -c 1000 http: //*.org/
This is ApacheBench, Version 2.3 <$Revision: 655654 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking *.org (be patient) Completed 1000 requests Completed 2000 requests Completed 3000 requests Completed 4000 requests Completed 5000 requests Completed 6000 requests Completed 7000 requests Completed 8000 requests Completed 9000 requests Completed 10000 requests Finished 10000 requests Server Software: nginx Server Hostname: *.org Server Port: 80 Document Path: / Document Length: 22307 bytes Concurrency Level: 1000 Time taken for tests: 4.812 seconds Complete requests: 10000 Failed requests: 0 Write errors: 0 Total transferred: 229199440 bytes HTML transferred: 226639120 bytes Requests per second: 2078.22 [#/sec] (mean) Time per request: 481.181 [ms] (mean) Time per request: 0.481 [ms] (mean, across all concurrent requests) Transfer rate: 46516.29 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 6 150 69.8 147 309 Processing: 105 288 70.8 276 600 Waiting: 5 144 50.0 145 511 Total: 215 439 93.6 448 783 Percentage of the requests served within a certain time (ms) 50% 448 66% 467 75% 477 80% 498 90% 541 95% 629 98% 634 99% 774 100% 783 (longest request) 


As you can see, the recoil of statics has significantly accelerated. This is great, even more than. Although, in this case, I still sin on the fact that it can be unloaded by the IO in the node in those 4 seconds, but this is hardly the case. A series of similar tests confirmed this picture.


Attach:

crontab bash-script to check the "adequacy" of php-fpm with default pool www
 #!/bin/sh POOL=`curl --retry 3 --retry-delay 1 --connect-timeout 2 --max-time 2 --silent http://127.0.0.1/fpmstatus | grep pool | awk '{ print $2 }'` if [ "$POOL" != "www" ] then echo -------------------------------------------------------------------------- >>/var/log/php-fpm/restarts.log echo `date` PHP-FPM $host:$port is DOWN >>/var/log/php-fpm/restarts.log echo `date` first try sigterm PHP-FPM... >>/var/log/php-fpm/restarts.log killall -9 php-fpm >>/dev/null sleep 5 echo `date` second try sigterm PHP-FPM... >>/var/log/php-fpm/restarts.log killall -9 php-fpm >>/dev/null sleep 5 echo `date` restarting PHP-FPM NOW >>/var/log/php-fpm/restarts.log /etc/init.d/php-fpm restart >>/dev/null echo -------------------------------------------------------------------------- >>/var/log/php-fpm/restarts.log else sleep 1 fi exit 

Two Killa is used because it happens so hang that only the second time it is demolished.
Attention! php-fpm and nginx must be configured for location / fpmstatus to work correctly

apc.ini
 extension = apc.so apc.enabled=1 apc.shm_size=128M apc.num_files_hint=0 apc.user_entries_hint=0 apc.ttl=0 apc.use_request_time=1 apc.user_ttl=0 apc.gc_ttl=3600 apc.cache_by_default=1 apc.filters apc.mmap_file_mask=/apc.shm.XXXXXX apc.file_update_protection=10 apc.enable_cli=0 apc.max_file_size=1M apc.stat=1 apc.stat_ctime=0 apc.canonicalize=1 apc.write_lock=0 apc.rfc1867=0 apc.rfc1867_prefix =upload_ apc.rfc1867_name=APC_UPLOAD_PROGRESS apc.rfc1867_freq=0 apc.rfc1867_ttl=3600 apc.include_once_override=0 apc.lazy_classes=0 apc.lazy_functions=0 apc.coredump_unmap=0 apc.file_md5=0 apc.localcache=1 apc.localcache.size=1024 


excerpts from nginx.conf (which are very deep in google ...)
 worker_processes 1; timer_resolution 100ms; worker_rlimit_nofile 4096; worker_priority -5; events { worker_connections 8196; use epoll; } sendfile on; aio on; directio 5m; output_buffers 8 128k; tcp_nopush on; tcp_nodelay on; server_tokens off; reset_timedout_connection on; open_file_cache max=8192 inactive=60s; open_file_cache_valid 60m; open_file_cache_min_uses 2; open_file_cache_errors on; 


wp-net.conf (for Wordpress Network to work with w3tc page disk cache, conf connects to nginx)
 map $host $sid { wp-net.su -999; forum.wp-net.su 2; about.wp-net.su 4; info.wp-net.su 5; test.wp-net.su 6; } server { listen IP.IP.IP.IP:80; server_name wp-net.su *.wp-net.su; access_log /var/log/nginx/nginx_($host)_access.log; error_log /var/log/nginx/nginx_(ALL.wp-net.su)_error.log error; root /var/www/vhosts/wp-net.su; index index.php; location = /favicon.ico { log_not_found off; access_log off; } location = /robots.txt { allow all; log_not_found off; access_log off; } location ~ /\. { deny all; } location ~* /(?:uploads|files)/.*\.php$ { deny all; } if ($request_uri ~* "\/files\/(.*)"){ set $rtfile $1; } location ^~ /files { try_files /wp-content/blogs.dir/$sid/$uri /wp-includes/ms-files.php?file=$rtfile; expires 7d; } location ^~ /blogs.dir { internal; alias /var/www/vhosts/wp-net.su/wp-content/blogs.dir; access_log off; log_not_found off; expires 7d; } location ~* ^.+\.(js|css)$ { expires 2d; } location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ { expires 7d; } set $cache_uri $request_uri; if ($request_method = POST) { set $cache_uri 'null cache'; } if ($query_string != "") { set $cache_uri 'null cache'; } if ($request_uri ~* "(/wp-admin/|/xmlrpc.php|/wp-(app|cron|login|register|mail).php|wp-.*.php|/feed/|index.php|wp-comments-popup.php|wp-links-opml.php|wp-locations.php|sitemap(_index)?.xml|[a-z0-9_-]+-sitemap([0-9]+)?.xml)") { set $cache_uri 'null cache'; } if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_logged_in") { set $cache_uri 'null cache'; } location / { try_files /wp-content/w3tc-$host/pgcache/$cache_uri/_index.html $uri $uri/ /index.php?$args; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; include /etc/nginx/fastcgi.conf; fastcgi_connect_timeout 1800s; fastcgi_read_timeout 1800s; fastcgi_send_timeout 1800s; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_intercept_errors off; fastcgi_pass phpfpm; } } 


important of /etc/my.cnf
 [mysqld_safe] key_buffer=8M max_allowed_packet=1M max_heap_table_size=24M table_cache=1024 sort_buffer_size=512K read_buffer_size=512K read_rnd_buffer_size=2M net_buffer_length=20K thread_stack=640K thread_cache=4 tmp_table_size=8M query_cache_limit=8M query_cache_size=16M skip-locking skip-networking skip-bdb skip-innodb skip-thread-priority old-passwords=0 thread_concurrency=1 max_connections=16 



Lord specialists, I understand, it is often pleasant to criticize, but I am not an expert, and I share not so much my work with beginners, but I show how you can find a way convenient for everyone. Although of course - criticize! And the practical recommendations of the community will be especially useful - I want to try, test on this VPS, and add an article if there is a gain.

Have a good mood

Source: https://habr.com/ru/post/162295/


All Articles