考える×つくる×動かす

主に技術系のことを書いていきます。

本番で動いているWordPressをMacのローカルで動かす方法

ちょっと非エンジニアに何度か聞かれたので個人的なメモ

MAMPのダウンロード+インストール

https://www.mamp.info/en/downloads/

本番のデータをコピー(ファイル)

本番でpublic_html 以下をダウンロードする。
(これはエンジニアがサーバー上でtar.gzとかでまとめてあげて直接渡すのが良さそう)
/Applications/MAMP/htdocs/ に展開しておく

本番のデータをコピー(DB)

(これもエンジニアがサーバー上dumpを取って直接渡すのが良さそう)
MAMPの設定パネルのphpMyAdminから
新しいDB(sample_wp)を文字コードutf8_general_ciを作成してDumpしたDBをimportしておく

Wordpressの設定ファイルを変更

/Applications/MAMP/htdocs/wp-config.phpを以下に変更

define('DB_NAME', 'sample_wp');
define('DB_USER', 'root');
define('DB_PASSWORD', 'root');
define('DB_HOST', 'localhost:8889');

ローカルなのでデフォルトのままです。
セキュリティーに拘る人はDBのユーザーを新規で作る方がいい。

DBの設定を変更

MAMPの設定パネルのphpMyAdminからwp_optionsの siteurlを http://localhost:8888 homeを http://localhost:8888 に変更する

MAMPでhtaccessを有効化する

/Applications/MAMP/conf/apache/httpd.conf

<Directory />
    Options Indexes FollowSymLinks
    AllowOverride All         ←"None"を"All"に変更
</Directory>

.htaccessの設置

/Applications/MAMP/htdocs/.htaccess に以下を記述して作成する

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

MAMPを再起動する

セキュリティーを考えるとwp-config.phpのSALT値を変えたり、
DBのユーザーをrootから変えたり、記事内で絶対パスで記述されてる場所をローカルURLに置き換えたり
バーチャルホストで動かしたり色々あるけど一応これで最低限動くはず。

ISUCON2014予選に参加してみた

チーム名:「/^o^\マッミョサーン」
最終スコア:26890
チームメイトはid:kazuphと@kokonoka

詳細はid:kazuphが書いていてくれるので割愛します。


ISUCON2014予選でがんばってきた - 僕の車輪の再発明


9月の頭に昨年の過去問を1回4時間くらいやって傾向と対策を練っていました。

基本的なスタンス

・nginxやmysqlのログを見て遅い部分のボトルネックを解消
・インデックスは貼る前と貼った後のEXPLAINをみながら貼っていく
・DBの構造とかを変更
・ロジックで減らせるクエリは極限まで減らす
ミドルウェアに手を入れたりは最後までしない
・最後にキャッシュ出来る部分はキャッシュする


そのおかげで変なエラーが出てベンチマークとか動かない(´・ω・`)とかなくて
基本的には成功法で攻めることができたはず。

やったこと

・全体のロジックを確認
・3回以上ID,PASSを間違えたipアドレスをブロックするipsテーブルを追加
・10回以上ID,PASSを間違えたユーザーをブロックするunlock_usersを追加
・初期で上テーブルにINSERTする初期スクリプトを作成
・usersに最新ログインの日時+IPアドレスを加えた
・login_logを使わなくした
mysqlの設定ファイルを秘伝のタレを利用した
・自分たちで新たに加えたテーブルにインデックスを貼った
・WORLOADが増えるとTCPでTIME_WAITが発生してPORTが専有されてしまうのを解決した

ハマったところ

・login_logのロジックを確認しつつテーブル分割するかキャッシュを使うか決めきれなかった
→これで午前のほぼ時間を費やしてしまった。。
・お昼ごはんのメニュー(結局寿司食べたく出前とった)
・/loginのエラー時にリダイレクトされるのを減らすためにnginxで静的ページを返したかった
MySQLのバージョンアップ(最後で5.6系に変えようと別インスタンスでテストしたけどエラー出て動かなかった)

反省点

・もっとはじめにベンチ前にく初期投入データを見ておくべきだった(これがランダムだと思ってた)
・全体ロジックを確認してUSERSをキャッシュ化してしまうべきだった
・パスワードのHASH処理を始めに計算にしてDBに入れておくべきだった
・nginxでCookieの値を持ってこれるそしてその値を見て静的ページを返せばよかった
・土曜朝じゃなくて金曜朝に海外から帰ってきて万全の状態で挑むべきだった(言い訳ですがw)


今回基本的にはid:kazuphがほとんどコード書いてくれてた。
自分ももっとさくっと書けるようにならないとと反省。


1年強振りのブログ記事でした。
詳細とMySQLの秘伝のタレに関しては別エントリ書きます。

mroongaで「ERROR 1005 (HY000): already used name was assigned:」の対処

MroongaでTokenizerをMecabからTokenBigramSplitSymbolAlphaDigitに変更する際に
インデックスのDropでエラーが出てしまい強制的に中止した。

これがまずかったのか、
その全文検索のインデックスが存在していないにもかかわらず、
再度インデックスを貼り直そうとした際に、

ERROR 1005 (HY000): already used name was assigned:

というエラーが発生するようになってしまった。

groonga /var/lib/mysql/database.mrn
>table_list

でMroongaのtable_list情報を確認した所しっかりと残っていた。

http://groonga.org/ja/docs/reference/commands/table_remove.html
の情報を参考に

>table_remove index_name 

でMroongaのtable_list情報を削除したら無事インデックスを貼り直すことができました。


以下バージョン情報です。

mysql Ver 14.14 Distrib 5.6.11
groonga(mroonga) 3.0.3

人生で大事なことは大体自転車から学んだ。

・一歩ずつ前へ前へペダルを漕ぐだけで大概の場所に自分の力で行ける
・長くてきつい上り坂は永遠には続かない
・楽な下り坂も永遠には続かない
・頂上から見る景色は物凄い綺麗だ
・下り坂に入ったときにブレーキを掛けながら下りないと転んで怪我することもある
・距離は短いけど急な坂もあれば距離が長くゆるやかな道もある
・毎日のメンテナンスが安全やパンクを防いでくれる
・自転車本体の良し悪しはあるけど結局は自分の体力次第
・長距離の自転車に乗る場合はペース配分を考えないと途中でバテてしまう
・食べ物や水はある程度ストックしておかないと大変なことになる
・いくら遠回りしたって足を止めないで漕ぎ続ければ目的地には到着できる

社内のISUCONに参加しました。

昨日のことですが社内のISUCONに参加しました。

ISUCON2に関しては以下のブログに書いてあります
http://blog.livedoor.jp/techblog/archives/67728751.html
http://github.com/tagomoris/isucon2

今回はPHPを選択しました。
だって一番慣れてるしー
ホントだったらRubyでやりたいんだけどねー

実を言うと自分は業務がちょっと忙しくて
ソースを完全に見たのが当日の昼という状況でした。

まず基本的な設計指針

PHP不要モジュールの削除
→ほぼ必須モジュールのみだったので手を加えず

Apache不要モジュールの削除
→Auth系とかProxy系はOFF

・不要なサーバーのサービスのKill
→chkconfigで確認してPostfixとかOFF

CSS,JS,画像ファイルの最小化
→JSはGoogleから引っ張ってきて画像は圧縮してBASE64エンコで内部に埋め込み

・Memcacheの導入
→別途記載(1)

・DBテーブルカラムの最適化
→別途記載(2)

Apache等各種ログファイル出力のOFF
httpd.confですべてOFF

・Keep Aliveの設定
→一回のリクエスト数が少ないので重くなりOFFにした


まず初期状態でのベンチスコアは110チケット前後
WebよりもDBのLoadAverageがいっぱいな感じ。

Memcacheの導入(1)

スロークエリーが出ていた場所は

SELECT stock.seat_id, variation.name AS v_name, ticket.name AS t_name, artist.name AS a_name
FROM stock
JOIN variation ON stock.variation_id = variation.id
JOIN ticket ON variation.ticket_id = ticket.id
JOIN artist ON ticket.artist_id = artist.id
WHERE order_id IS NOT NULL
ORDER BY order_id DESC LIMIT 10

最近購入されたチケットの10件を取得して表示する場所。

これは様々なページで呼ばれていたのでMemcacheに入れた。
チケットが売れた時に10件を超えていた場合はarray_popし古いのを1件削除して
array_unshiftで直近で売れたチケット情報を加えることにした。

Memcacheの導入(2)

他の部分でスロークエリーが出ていた場所は

SELECT COUNT(*) FROM variation
INNER JOIN stock ON stock.variation_id = variation.id
WHERE variation.ticket_id = :ticket_id AND stock.order_id IS NULL

残りのチケットの枚数を取得する場所。

はじめの枚数をMemcacheに入れて、
チケットが売れた時にそのvariationの枚数を-1する処理に変更。

ここで400前後のスコアまで改善した。

APCの導入+サーバーのチューンナップ

APCを入れたらスコアが一気に700前後まで改善した。
KeepAliveはスコアが落ちたのでOFFにした。

DBテーブルカラムの最適化

アーティストとチケットと開催場所をDBではなくソースに直接配列として記述した。
これらの値は基本固定だったので配列として処理した。

以下やらなかったこと

・nginxの導入
→時間が足りなかった
Mysqlのエンジン変更
Mysqlサーバはボトルネックになってなかったから
フレームワークの変更
→時間が足りなかった
Mysqlのテーブルカラムの構造変更
(stockのseat_idをvarchar255から2個にカラム分割してintに変換しindexを貼り直す)
Mysqlサーバはボトルネックになってなかったから

以下反省点

・事前に時間を作ってちゃんとソースとサーバーを見ておくべきだった
・テストのソースをしっかりと確認してどこをテストしてるのかを確認すべきだった
・Webサーバっていう大まかな負荷を見るだけじゃなくて、
どの画面がボトルネックになっているのかっていうのをしっかりと把握すべきだった
・実際の業務じゃないので新しい技術に積極的にチャレンジしてもよかった

最後に

チームメンバーのお陰でなんと優勝することができました。
最小の処理でなかなかのパフォーマンスを引き出すことができ良かったかなと思います。
運営の皆様お疲れ様でした。次回ありましたら是非また参加したいです。

賞金5000円分の商品券もらったんで飲みにでも行きましょう(笑)