Tweak m1.small
(2015-07: 以下の内容は古いです。現状では php5.5 以降の Zend OPcache、apcu、さらに php7、HHVM 等の動きがあります)
m1.small instance をしゃぶり尽くす
AWS って on demand 的な使い方をした場合の課金や、ストレージ課金は驚異的に安価だとおもいますが、常時稼働が必要な instance の CPU 課金は(デフレスパイラル下の日本に於いては)微妙に割高感があります。 その中で、2番目に低価格な m1.small でどこまで逝けるか を試してみるつもりです。
m1.small は Xen の CPU cap (割り当てCPU時間の制御) されており、Amazon に CPU を盗まれています。B)
# mpstat 00:00:00 AM CPU %user %nice %sys %iowait %irq %soft %steal %idle intr/s 00:00:00 AM all 34.95 0.00 4.85 0.00 0.00 0.00 60.19 0.00 96.12
CPU cap は、m1.large なら問題なさそうです(30%steal)。長期に運用する場合は m1.large で reserved instance にすれば価格は m1.small とほぼ同様なので、このパターンで使うのがベストだと思います。(*64 bit になります)
驚異的な安さの t1.micro は CPU cap が厳しくて、用途が限定されます。t1.micro の使い道は、64bit, EBS‐backed, PVGRUB な t1.micro AMI でデプロイメントして、問題なければ上のクラスのインスタンス・サイズにして実戦投入するといった用途にはすごく便利で、しかも超安価です。
Concepts Micro Instances
m1.small instance とは
スペック
1.7 GB of memory 1 EC2 Compute Unit (1 virtual core with 1 EC2 Compute Unit) 160 GB of instance storage 32-bit platform
The art of limitations
メインメモリはふんだんにあるので、メモリーの有効活用がキモになります。 Xen の CPU cap (割り当てCPU時間の制御) がされているので、重い処理をできるだけ少なくして、メモリーキャッシュを有効に使う設計をすべきです。
Bare metal サーバと異なり、「仮想サーバの設定」の範囲内ギリギリでつかえるか? 制限する事が重要なポイントになります。The art of limitations ですね ;)
ターゲット
Linux + Apache + MySQL + PHP といった文字通りの LAMP サーバ。
個人の Blog サイトで、それほどアクセスは無いが、たまにはスパイクがあるような感じ。
私は debian/ubuntu 派なので、EC2 で安定している ubuntu を使います。
MySQL
データベースが CPU 負荷のボトルネックになります。 m1.small で扱えきれる性能に制限します。つまり、この性能に合わせて設計して行きます。
実機で負荷を観察したところ、最大接続数が10程度に抑えておくのが良さそうです。
my.cnf
余裕を見て最大接続数を 16 とします。
max_connections = 16
また、接続数が 8 程度までは常用として、thread の設定をします。
thread_cache_size = 14 thread_concurrency = 8
Query Cache を有効にします。
query_cache_size = 64M query_cache_limit = 2M query_cache_type = 1
メモリーを有効に使用するように一時テーブルをメモリーに展開するように設定します。
tmpdir = /run/shm tmp_table_size = 256M max_heap_table_size = 256M
ただし、リプリケーション・スレーブの場合は、TMPDIR, tmpdir に tmpfs は使ってはいけません。(If the MySQL server is acting as a replication slave, you should not set --tmpdir to point to a directory on a memory-based filesystem or to a directory that is cleared when the server host restarts. )
いろいろ試して、mysqltuner.pl で設定の確認してみて下さい。
その他の my.cnf チューニング系リンク
LAMP システムを調整する: 第 3 回 MySQL サーバーを調整する DSAS開発者の部屋:5分でできる、MySQLのメモリ関係のチューニング! MySQLTunerを使ってMySQLを速くする
Run OPTIMIZE TABLE to defragment tables for better performance
mysqlcheck -u root -p --auto-repair --check --optimize --all-databases
Apache
データーベースに負けず劣らず apache も CPU を喰いますね。(軽量化を模索中...)
config
PHP をつかうので MPM prefork が前提になってしまいます。 という訳で、最近流行りの設定を仕込みます。
前項の制限から考えて 16 程度 prefork します。
StartServers 16 MinSpareServers 16 MaxSpareServers 16 MaxClients 16 ServerLimit 16
この程度でも十分さばけています ;) というか、以下で記述する、メモリーが十分にあるからこそ出来るキャッシュ作戦のおかげなのです :) ナイスな仕様ですね EC2!!!
もう一つの重要ポイントである KeepAlive 系は、コンテンツが WordPress や MediaWiki であるので以下の設定をします。
MaxKeepAliveRequests 20 KeepAliveTimeout 3
(phpmyadmin の 1ページ目用なら MaxKeepAliveRequests 40 てな感じで)
おまけ
ServerSignature Off ServerTokens Prod TraceEnable Off
パラノイア
<LocationMatch "/\..*"> Order allow,deny Deny from all </LocationMatch> <DirectoryMatch "/CVS/|/RCS/"> Order allow,deny Deny from all </DirectoryMatch> <DirectoryMatch "/\.svn/|/\.git/|/\.hg/|/\.bzr/|/\.cvs/"> Order allow,deny Deny from all </DirectoryMatch> <FilesMatch "~$|#$|,v$|,t$"> Order allow,deny Deny from all </FilesMatch> <FilesMatch "\.bak$|\.BAK$|\.orig$|\.ORIG$|\.org$|\.ORG$|\.rej$"> Order allow,deny Deny from all </FilesMatch>
DirectoryIndex は index.php のみにする .htaccess は使わない (AllowOverride none) Options FollowSymLinks しておく (処理が軽くなる)
YSlow / Page Speed
YSlow や Page Speed で指摘される点を対処。A評価 になるようにがんばる。
ここでのポイントは、データ転送量を極力少なくして、かつ、極力クライアントにキャッシュしてもらうという事。(大規模事業者はbyte単位でこの手の最適化をやっていますね)
mod_expires
<IfModule mod_expires.c> ExpiresActive On ExpiresDefault "access plus 15 minutes" ExpiresByType text/css "access plus 1 months" ExpiresByType text/javascript "access plus 1 months" ExpiresByType application/x-javascript "access plus 1 months" ExpiresByType application/javascript "access plus 1 months" ExpiresByType image/jpeg "access plus 10 years" ExpiresByType image/png "access plus 10 years" ExpiresByType image/gif "access plus 10 years" ExpiresByType image/x-icon "access plus 10 years" </IfModule>
mod_deflate
<IfModule mod_deflate.c> DeflateCompressionLevel 1 AddOutputFilterByType DEFLATE text/html AddOutputFilterByType DEFLATE text/plain AddOutputFilterByType DEFLATE text/css AddOutputFilterByType DEFLATE text/javascript AddOutputFilterByType DEFLATE text/xml AddOutputFilterByType DEFLATE application/x-javascript AddOutputFilterByType DEFLATE application/javascript AddOutputFilterByType DEFLATE application/xml AddOutputFilterByType DEFLATE application/rdf+xml </IfModule>
ここでのポイントは "DeflateCompressionLevel 1" とする事。mod_deflate の使命であるデータ転送量を抑えつつ、 CPU 使用率を極力下げる事が CPU cap 下の m1.small には大事です。
ETag を切る
FileETag none
mod_rpaf
後述するリバースプロキシを適用した場合のアクセスログ対策として、mod_rpaf を導入
<IfModule mod_rpaf.c> RPAFenable On RPAFsethostname On RPAFproxy_ips 127.0.0.1 </IfModule>
Cache 三兄弟
memcached 導入
# apt-get install memcached # apt-get install php5-memcache
/etc/memcached.conf , /etc/init.d/memcached , /usr/share/memcached/scripts/start-memcached
-m 64 -p 11211 -U 0 -u www-data -t 16 -l 127.0.0.1
パッケージの内容・更新頻度が気になるなら memcached と PHP memcache を手動管理する(こっちのほうがよさげ)
memcached
# apt-get install libevent-dev (memcached compile & install)
php-memcache
# apt-get install php5-dev # apt-get install php-pear # pecl install memcache
更新
# pecl upgrade memcache
再インストール
PHP の更新にともなう再インストール
# pecl install -f memcache
WordPress の memcached 設定
Memcached Object Cache object-cache.php
MediaWiki の memcached 設定
memcached - MediaWiki
リンク
MySQL HA/Scalability Guide :: 4 Using MySQL with memcached
メモ
PHP memcache ではなく PHP memcached なんてのあるのね。
WordPress の object-cache.php は PHP memcache を使っているし、 MediaWiki は memcached-client を使っている。
PHP memcached の方がパフォーマンスが良いらしいし、柔軟だとの事。(memcache 系はまだまだ発展中ですね)
PHP の session handler に "memcache" の 代わりに "memcached" にすると若干性能向上するらしい。
libmemcached , PHP memcached を導入
libinnodb Igbinary libMemcached # pecl install memcached
メモ その2
Batcache なる WordPress Plugin を実験中
WordPress › Batcache « WordPress Plugins
varnish 導入
apache に仕事をさせないように、リバースプロキシで可能なかぎりメモリーにキャッシュします。
# apt-get install varnish
/etc/default/varnish , /etc/init.d/varnish
-p thread_pools=1 -p thread_pool_add_delay=10 -p cli_timeout=20 -u www-data -g www-data -w 16,800,300 -s malloc,64M
(キャッシュはメモリーに展開する: -s malloc,64M)
Varnish best practices « Kristian Lyngstol's Blog Varnish Oscon 2009
パッケージの内容・更新頻度が気になるなら varnishd のリポジトリから導入する(こっちのほうがよさげ)
vcl
MediaWiki用のサンプルをベースにして作成した、現在使用中の vcl (様子見中...) (varnish 2.1版)
# set default backend if no server cluster specified backend default { .host = "127.0.0.1"; .port = "8080"; } # access control list for "purge": open to only localhost and other local nodes acl purge { "127.0.0.1"; } sub vcl_recv { # for mod_rpaf logging src IP address if (req.restarts == 0) { if (req.http.x-forwarded-for) { set req.http.X-Forwarded-For = req.http.X-Forwarded-For ", " client.ip; } else { set req.http.X-Forwarded-For = client.ip; } } # removes all cookies named __utm? (utma, utmb...) - REMOVE! Google Analytics tracking Cookies if (req.http.Cookie) { set req.http.Cookie = regsuball(req.http.Cookie, "(^|; ) *__utm.=[^;]+;? *", "\1"); if (req.http.Cookie == "") { remove req.http.Cookie; } } # If they are going to the mobile site, force the iphone user agent if (req.http.host ~ "^m.egrep.jp") { set req.http.user-agent = "iPhone"; } # Check the regular site for a few things... if (req.url ~ "^\/blog\/") { # Force the http.host to be the mobile version of the site to ensure the cache lookup hits the mobile version of the site if(req.http.user-agent ~ "(iPhone|iPod|Android|CUPCAKE|bada|blackberry\ 9800|blackberry9500|blackberry9520|blackberry9530|blackberry 9550|dream|incognito|s8000|webOS|webmate|Opera\ Mini)") { set req.http.host = "m.egrep.jp"; } # Drop any cookies sent to Wordpress. if (!(req.url ~ "wp-(login|admin)")) { unset req.http.cookie; } } # for Trick of DirectoryIndex OLD Static contents if (req.request == "GET" && req.url ~ "^\/nxhack\/") { if (req.url ~ "/$") { set req.url = req.url "index.html"; return (lookup); } } # always cache these items: if (req.request == "GET" && req.url ~ "\.(js)") { return (lookup); } # images if (req.request == "GET" && req.url ~ "\.(gif|jpg|jpeg|bmp|png|tiff|tif|ico|img|tga|wmf)$") { return (lookup); } # various other content pages if (req.request == "GET" && req.url ~ "\.(css|html)$") { return (lookup); } # multimedia if (req.request == "GET" && req.url ~ "\.(svg|swf|ico|mp3|mp4|m4a|ogg|mov|avi|wmv)$") { return (lookup); } # xml if (req.request == "GET" && req.url ~ "\.(xml)$") { return (lookup); } # Serve objects up to 2 minutes past their expiry if the backend # is slow to respond. set req.grace = 120s; # This uses the ACL action called "purge". Basically if a request to # PURGE the cache comes from anywhere other than localhost, ignore it. if (req.request == "PURGE") { if (!client.ip ~ purge) { error 405 "Not allowed."; } return (lookup); } # Pass any requests that Varnish does not understand straight to the backend. if (req.request != "GET" && req.request != "HEAD" && req.request != "PUT" && req.request != "POST" && req.request != "TRACE" && req.request != "OPTIONS" && req.request != "DELETE") { /* Non-RFC2616 or CONNECT which is weird. */ return (pipe); } # Pass anything other than GET and HEAD directly. if (req.request != "GET" && req.request != "HEAD") { /* We only deal with GET and HEAD by default */ return (pass); } # Pass requests from logged-in users directly. if (req.http.Authorization || req.http.Cookie) { /* Not cacheable by default */ return (pass); } /* Do not cache if request contains an Expect header */ if (req.http.Expect) { return (pipe); } # Pass any requests with the "If-None-Match" header directly. if (req.http.If-None-Match) { return (pass); } # Force lookup if the request is a no-cache request from the client. if (req.http.Cache-Control ~ "no-cache") { purge_url(req.url); } # normalize Accept-Encoding to reduce vary if (req.http.Accept-Encoding) { if (req.http.User-Agent ~ "MSIE 6") { unset req.http.Accept-Encoding; } elsif (req.http.Accept-Encoding ~ "gzip") { set req.http.Accept-Encoding = "gzip"; } elsif (req.http.Accept-Encoding ~ "deflate") { set req.http.Accept-Encoding = "deflate"; } else { unset req.http.Accept-Encoding; } } return (lookup); } sub vcl_pipe { # Note that only the first request to the backend will have # X-Forwarded-For set. If you use X-Forwarded-For and want to # have it set for all requests, make sure to have: # set req.http.connection = "close"; # This is otherwise not necessary if you do not do any request rewriting. set req.http.connection = "close"; return (pipe); } # Called if the cache has a copy of the page. sub vcl_hit { if (req.request == "PURGE") { purge_url(req.url); error 200 "Purged"; } if (!obj.cacheable) { return (pass); } return (deliver); } # Called if the cache does not have a copy of the page. sub vcl_miss { if (req.request == "PURGE") { error 200 "Not in cache"; } return (fetch); } # Called after a document has been successfully retrieved from the backend. sub vcl_fetch { # set minimum timeouts to auto-discard stored objects # set beresp.prefetch = -30s; set beresp.grace = 120s; if (beresp.ttl < 48h) { set beresp.ttl = 48h; } # Drop any cookies Wordpress tries to send back to the client. if (req.url ~ "^\/blog\/") { if (!(req.url ~ "wp-(login|admin)")) { unset beresp.http.set-cookie; } } # strip the cookie before the image is inserted into cache. if (req.url ~ "\.(png|gif|jpg|swf|css|js|ico|tiff|jpeg|bmp|tif)$") { unset beresp.http.set-cookie; } if (!beresp.cacheable) { return (pass); } if (beresp.http.Set-Cookie) { return (pass); } if (req.http.Authorization && !beresp.http.Cache-Control ~ "public") { return (pass); } if (beresp.cacheable) { /* Set how long Varnish will keep it */ # set beresp.ttl = 1w; # for OLD Statick Contents if (req.url ~ "^\/nxhack\/") { /* for static text/html */ if (req.url ~ "\.html$") { /* Set how long Varnish will keep it */ set beresp.ttl = 30d; /* Set the clients TTL on this object */ set beresp.http.cache-control = "max-age=2592000"; } } /* marker for vcl_deliver to reset Age: */ set beresp.http.magicmarker = "1"; } return (deliver); } sub vcl_deliver { if (resp.http.magicmarker) { /* Remove the magic marker */ unset resp.http.magicmarker; /* By definition we have a fresh object */ set resp.http.Age = "0"; } # Disable BRAIN-DAMAGED Internet Explorer 8 MIME Sniffing set resp.http.X-Content-Type-Options = "nosniff"; # unset resp.http.Age; # unset resp.http.Server; unset resp.http.Via; unset resp.http.X-Varnish; unset resp.http.X-Vary-Options; return (deliver); }
(varnish 3.0 版への diff)
@@ -13,8 +13,7 @@
# for mod_rpaf logging src IP address
if (req.restarts == 0) {
if (req.http.x-forwarded-for) {
- set req.http.X-Forwarded-For =
- req.http.X-Forwarded-For ", " client.ip;
+ set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;
} else {
set req.http.X-Forwarded-For = client.ip;
}
@@ -49,7 +48,7 @@
# for Trick of DirectoryIndex OLD Static contents
if (req.request == "GET" && req.url ~ "^\/nxhack\/") {
if (req.url ~ "/$") {
- set req.url = req.url "index.html";
+ set req.url = req.url + "index.html";
return (lookup);
}
}
@@ -128,7 +127,7 @@
# Force lookup if the request is a no-cache request from the client.
if (req.http.Cache-Control ~ "no-cache") {
- purge_url(req.url);
+ ban_url(req.url);
}
# normalize Accept-Encoding to reduce vary
@@ -163,11 +162,11 @@
# Called if the cache has a copy of the page.
sub vcl_hit {
if (req.request == "PURGE") {
- purge_url(req.url);
+ ban_url(req.url);
error 200 "Purged";
}
- if (!obj.cacheable) {
+ if (!(obj.ttl > 0s)) {
return (pass);
}
@@ -206,19 +205,19 @@
unset beresp.http.set-cookie;
}
- if (!beresp.cacheable) {
- return (pass);
+ if (!(beresp.ttl > 0s)) {
+ return (hit_for_pass);
}
if (beresp.http.Set-Cookie) {
- return (pass);
+ return (hit_for_pass);
}
if (req.http.Authorization && !beresp.http.Cache-Control ~ "public") {
- return (pass);
+ return (hit_for_pass);
}
- if (beresp.cacheable) {
+ if (beresp.ttl > 0s) {
/* Set how long Varnish will keep it */
# set beresp.ttl = 1w;
(varnish 3.0 版から 4.0番への diff)
@@ -1,3 +1,6 @@
+### -*- mode:c -*-
+
+vcl 4.0;
# set default backend if no server cluster specified
backend default {
.host = "127.0.0.1";
@@ -10,8 +13,11 @@
"127.0.0.1";
}
+# vcl_recv is called whenever a request is received
sub vcl_recv {
+# Remove the proxy header (see https://httpoxy.org/#mitigate-varnish)
unset req.http.proxy;
+
# for mod_rpaf logging src IP address
if (req.restarts == 0) {
if (req.http.x-forwarded-for) {
@@ -26,7 +32,7 @@
set req.http.Cookie = regsuball(req.http.Cookie, "(^|; ) *__utm.=[^;]+;? *", "\1");
if (req.http.Cookie == "") {
- remove req.http.Cookie;
+ unset req.http.Cookie;
}
}
@@ -48,74 +54,70 @@
}
# for Trick of DirectoryIndex OLD Static contents
- if (req.request == "GET" && req.url ~ "^\/nxhack\/") {
+ if (req.method == "GET" && req.url ~ "^\/nxhack\/") {
if (req.url ~ "/$") {
set req.url = req.url + "index.html";
- return (lookup);
+ return (hash);
}
}
# always cache these items:
- if (req.request == "GET" && req.url ~ "\.(js)") {
- return (lookup);
+ if (req.method == "GET" && req.url ~ "\.(js)") {
+ return (hash);
}
# images
- if (req.request == "GET" && req.url ~ "\.(gif|jpg|jpeg|bmp|png|tiff|tif|ico|img|tga|wmf)$") {
- return (lookup);
+ if (req.method == "GET" && req.url ~ "\.(gif|jpg|jpeg|bmp|png|tiff|tif|ico|img|tga|wmf)$") {
+ return (hash);
}
# various other content pages
- if (req.request == "GET" && req.url ~ "\.(css|html)$") {
- return (lookup);
+ if (req.method == "GET" && req.url ~ "\.(css|html)$") {
+ return (hash);
}
# multimedia
- if (req.request == "GET" && req.url ~ "\.(svg|swf|ico|mp3|mp4|m4a|ogg|mov|avi|wmv)$") {
- return (lookup);
+ if (req.method == "GET" && req.url ~ "\.(svg|swf|ico|mp3|mp4|m4a|ogg|mov|avi|wmv)$") {
+ return (hash);
}
# xml
- if (req.request == "GET" && req.url ~ "\.(xml)$") {
- return (lookup);
+ if (req.method == "GET" && req.url ~ "\.(xml)$") {
+ return (hash);
}
# Serve objects up to 2 minutes past their expiry if the backend
# is slow to respond.
- set req.grace = 120s;
+# set req.grace = 120s;
# This uses the ACL action called "purge". Basically if a request to
# PURGE the cache comes from anywhere other than localhost, ignore it.
- if (req.request == "PURGE") {
+ if (req.method == "PURGE") {
if (!client.ip ~ purge) {
- error 405 "Not allowed.";
+ return (synth(405, "Not allowed."));
+ } else {
+ return (purge);
}
- return (lookup);
}
# Pass any requests that Varnish does not understand straight to the backend.
- if (req.request != "GET" &&
- req.request != "HEAD" &&
- req.request != "PUT" &&
- req.request != "POST" &&
- req.request != "TRACE" &&
- req.request != "OPTIONS" &&
- req.request != "DELETE") {
- /* Non-RFC2616 or CONNECT which is weird. */
+ if (req.method != "GET" && req.method != "HEAD" &&
+ req.method != "PUT" && req.method != "POST" &&
+ req.method != "TRACE" && req.method != "OPTIONS" &&
+ req.method != "DELETE") {
return (pipe);
- }
+ } /* Non-RFC2616 or CONNECT which is weird. */
# Pass anything other than GET and HEAD directly.
- if (req.request != "GET" && req.request != "HEAD") {
- /* We only deal with GET and HEAD by default */
+ if (req.method != "GET" && req.method != "HEAD") {
return (pass);
- }
+ } /* We only deal with GET and HEAD by default */
# Pass requests from logged-in users directly.
- if (req.http.Authorization || req.http.Cookie) {
- /* Not cacheable by default */
+# Only detect cookies with "session" and "Token" in file name, otherwise nothing get cached.
+ if (req.http.Authorization || req.http.Cookie ~ "session" || req.http.Cookie ~ "Token") {
return (pass);
- }
+ } /* Not cacheable by default */
/* Do not cache if request contains an Expect header */
if (req.http.Expect) {
@@ -129,7 +131,7 @@
# Force lookup if the request is a no-cache request from the client.
if (req.http.Cache-Control ~ "no-cache") {
- ban_url(req.url);
+ ban(req.url);
}
# normalize Accept-Encoding to reduce vary
@@ -145,7 +147,7 @@
}
}
- return (lookup);
+ return (hash);
}
sub vcl_pipe {
@@ -157,66 +159,67 @@
# This is otherwise not necessary if you do not do any request rewriting.
set req.http.connection = "close";
-
- return (pipe);
}
# Called if the cache has a copy of the page.
sub vcl_hit {
- if (req.request == "PURGE") {
- ban_url(req.url);
- error 200 "Purged";
+ if (req.method == "PURGE") {
+ ban(req.url);
+ return (synth(200, "Purged"));
}
- if (!(obj.ttl > 0s)) {
+ if (!obj.ttl > 0s) {
return (pass);
}
-
- return (deliver);
}
# Called if the cache does not have a copy of the page.
sub vcl_miss {
- if (req.request == "PURGE") {
- error 200 "Not in cache";
+ if (req.method == "PURGE") {
+ return (synth(200, "Not in cache"));
}
-
- return (fetch);
}
# Called after a document has been successfully retrieved from the backend.
-sub vcl_fetch {
-
+sub vcl_backend_response {
# set minimum timeouts to auto-discard stored objects
-# set beresp.prefetch = -30s;
set beresp.grace = 120s;
+
if (beresp.ttl < 48h) {
set beresp.ttl = 48h;
}
# Drop any cookies Wordpress tries to send back to the client.
- if (req.url ~ "^\/blog\/") {
- if (!(req.url ~ "wp-(login|admin)")) {
+ if (bereq.url ~ "^\/blog\/") {
+ if (!(bereq.url ~ "wp-(login|admin)")) {
unset beresp.http.set-cookie;
}
}
# strip the cookie before the image is inserted into cache.
- if (req.url ~ "\.(png|gif|jpg|swf|css|js|ico|tiff|jpeg|bmp|tif)$") {
+ if (bereq.url ~ "\.(png|gif|jpg|swf|css|js|ico|tiff|jpeg|bmp|tif)$") {
unset beresp.http.set-cookie;
}
- if (!(beresp.ttl > 0s)) {
- return (hit_for_pass);
+ if (!beresp.ttl > 0s) {
+ set beresp.uncacheable = true;
+ return (deliver);
}
if (beresp.http.Set-Cookie) {
- return (hit_for_pass);
+ set beresp.uncacheable = true;
+ return (deliver);
}
- if (req.http.Authorization && !beresp.http.Cache-Control ~ "public") {
- return (hit_for_pass);
+# if (beresp.http.Cache-Control ~ "(private|no-cache|no-store)") {
+# set beresp.uncacheable = true;
+# return (deliver);
+# }
+
+ if (beresp.http.Authorization && !beresp.http.Cache-Control ~ "public") {
+ set beresp.uncacheable = true;
+ return (deliver);
}
if (beresp.ttl > 0s) {
@@ -224,14 +227,14 @@
# set beresp.ttl = 1w;
# for OLD Statick Contents
- if (req.url ~ "^\/nxhack\/") {
+ if (bereq.url ~ "^\/nxhack\/") {
/* for static text/html */
- if (req.url ~ "\.html$") {
- /* Set how long Varnish will keep it */
- set beresp.ttl = 30d;
+ if (bereq.url ~ "\.html$") {
+ /* Set how long Varnish will keep it */
+ set beresp.ttl = 30d;
- /* Set the clients TTL on this object */
- set beresp.http.cache-control = "max-age=2592000";
+ /* Set the clients TTL on this object */
+ set beresp.http.cache-control = "max-age=2592000";
}
}
vcl サンプルのリンク
Manual:Varnish caching VarnishAndWordpress – Varnish VCLExampleLongerCaching – Varnish VCLExampleRemovingSomeCookies – Varnish Making Posterous faster with Varnish - The Official Posterous Tech Blog
DirectoryIndex に関連する vcl テクニック
A Guide to Varnish VCL
WPtouch の扱い
Improving Wordpress Performance Supporting WPtouch Varnish | ephur.net
MediaWiki の設定
Configuring MediaWiki
遅い(重い) backend への対応
Child (9999) not responding to CLI, killing it.
てなログが出ている場合
-p cli_timeout=20
で様子を見る
varnish 運用メモ
強制的にキャッシュに食わす
wget -m --delete-after -nd -P /run/shm/ -q http://www.example.com/
よく使うコマンド
varnishadm -T 127.0.0.1:6082 'help' varnishadm -T 127.0.0.1:6082 'param.show' varnishadm -T 127.0.0.1:6082 'param.show -l' varnishadm -T 127.0.0.1:6082 'purge.url .*' varnishadm -T 127.0.0.1:6082 'purge.url /foo/bar' varnishadm -T 127.0.0.1:6082 'purge.list'
ubuntu Lucid Lynx の場合以下が必要
-S /etc/varnish/secret
デバッグログ
varnishlog
PHP Cache 導入
PHP cache でよく使われている、APC や eAccelerator を導入します。 APC の方が安定しているようです。また eAccelerator を圧縮無しモードで使用した場合 CPU 消費が少ないようです。
APC を導入する場合
パッケージを使う場合
# apt-get install php-apc
パッケージを使わない場合
# apt-get install php5-dev # apt-get install php-pear # apt-get install apache2-prefork-dev # pecl install apc # echo "extension=apc.so" >> /etc/php5/conf.d/apc.ini # /etc/init.d/apache2 restart
apc.ini
; configuration for php APC module extension=apc.so [apc] apc.shm_size=64M apc.filters = wp-cache-config apc.max_file_size=4M
更新
# pecl upgrade apc
# pecl upgrade -f apc-VERSION
再インストール
PHP の更新にともなう再インストール
# pecl install -f apc
eAccelerator メモ
eaccelerator.ini
extension=eaccelerator.so [eaccelerator] eaccelerator.shm_size="64" eaccelerator.cache_dir="/tmp/eaccelerator" eaccelerator.enable="1" eaccelerator.optimizer="1" eaccelerator.check_mtime="1" eaccelerator.debug="0" eaccelerator.filter="" eaccelerator.shm_max="0" eaccelerator.shm_ttl="0" eaccelerator.shm_prune_period="0" eaccelerator.shm_only="1" eaccelerator.allowed_admin_path="/var/foo/bar" eaccelerator.compress="0" ;;;;;; eaccelerator.filter="!wp-cache-config" ;eaccelerator.keys="shm_only" ;eaccelerator.sessions="shm_only" ;eaccelerator.content="shm_only"
Linux
(いや...まぁいっか...では最小限で...)
sysctl.conf
vm.swappiness=0 kernel.panic_on_oops=1 kernel.panic=1 kernel.shmmax=268435456
Performance – Varnish
for DB EBS Volume
echo 'noop' > /sys/block/sdX/queue/scheduler
'deadline' か 'noop' が良い。(微妙にしか変わらないので、どちらでも...)
雑多なメモ
PHP
php.ini
expose_php = Off max_execution_time = 6000000 memory_limit = 128M display_errors = Off post_max_size = 128M upload_max_filesize = 128M date.timezone = Asia/Tokyo
session.save_handler = memcache session.save_path = tcp://127.0.0.1:11211
PHP & Performance output_buffering = 8192 register_globals = Off magic_quotes_gpc = Off expose_php = Off register_argc_argv = Off always_populate_raw_post_data = Off session.use_trans_sid = 0 session.auto_start = 0 session.gc_divisor = 10000
WordPress
wp-config.php
define('WP_MEMORY_LIMIT', '128M');
翻訳ファイルのキャッシュ
(追記) WordPress の勉強会に出て教えてもらった手法。
001 Prime Strategy Translate Accelerator
私はこのプラグインで「サイト表示の翻訳」を停止にしています。
MediaWiki
LocalSettings.php
ini_set( 'memory_limit', '128M' );