※ パクレゼルヴではWeb開発エンジニアを大募集中!詳細はこちら

Archive

Author Archive

Apacheチューニング その1  

2008/5/2 金曜日 10:12:49

M役員様、結婚おめでとうございます。姜子牙です。新居乱入はいつにしましょう?

4月のサーバパフォーマンスチューニング月間が完了し、ややほっとしております。一度最大瞬間風速でサーバが応答不能に近い状態になって以来、あれやこれやと調べつつ折を見て設定変更なんかを行ってきたので、それを書きたいなと思います。

このチューニングについては、GIGAZINEさんのサイトが主な情報源だったのですが
http://gigazine.net/index.php?/news/comments/20070119_gigazine_complete/
そこに被る部分、被らない部分、なんかできちゃった部分なんかを記載していきたいなーと思います。また赤裸々に情報を提供して頂いているGIGAZINEさんには感謝感謝です。

私が管理しているサーバはWebはApacheを、DBにはMySQLを使用しています。OSはLinuxで、開発はPHPなので標準的なLAMP構成です。

全部を一気に書くのはさすがに文章量が多すぎるため、まず今回はApacheに焦点を当てて行きたいと思います。(尚、Apacheは2.0以降が対象になると思います。1.*系ではだいぶ違うかも)

今回のApacheのチューニングでは、主に以下2つを対象にして行っています。
1、不要なModuleを外す
2、待機プロセス数の変更

Apacheでは各種機能をCoreから分離してModule形式で使用することができます。
MySQLと比較すると、MySQLは必要に応じて再構築(Configureを変更して、再度Make)が必要だったりするのですがApacheはコンフィグファイルのLoadModuleディレクティブで追加削除し、Apacheのリブートで適用できたりします。便利です。

しかし、ここで二つの問題にぶち当たります。
1-1、どのモジュールが使用されていて、どのモジュールが不要なのか判別がつかない
1-2、Includeしているconfの中などに散らばってLoadModuleディレクティブが書かれている

自分ですべてのプログラムや設定を把握していればいいのですが、そのようなことは少ないです。
Apacheの管理してんだからその上に乗っかるコード全部読んで把握しろと言われたら田舎に帰るか、土に還るか、野生に帰ると思います。

というわけで、ApacheのModuleの一つであるServer-infoを使用します。設定方法の詳細は割愛しますが、以下のようなLocationディレクティブをconfに追加します。Allow句のIPアドレスは任意に変更してください。

<location /server-info>
SetHandler server-info
Order allow,deny
Allow from 255.255.255.255
</location>

その後、Apacheの再起動を行うと、以下のようなURLでアクセスできます。(www.pakureserve.jpでの例です。尚アクセスしても404 Not Foundになります)
http://www.pakureserve.jp/server-info

このページでは、現在Loadされているモジュールの一覧が表示されそれがハンドラされるか否か、またConfファイルのどこかで関連のディレクティブが記載されていたらそのファイル名と行番号を表示してくれたりします。

“Current Configuration”に何らかの内容が表示されていたら、Confのどこかに関連の記載があり”Content handlers”がonの場合、ハンドラでそのモジュール機能が使われる可能性があるようです。(ハンドラの方は自信あまりなかったりします)

そのため、”Current Configuration”が空欄で且つ”Content handlers”がnoneのモジュールを今回は外しました。
/etc/init.d/httpd configtest でSyntax OKとなれば、コンフィグの記載はOKとなります。
/etc/init.d/httpd graceful で再起動します。

これで不要なモジュールをLoadせず稼働するため、少し処理が軽くなります。

やや余談:
httpdにも restart はあるのですが、現在接続中の人も接続を強制的に切断してしまうため稼働中サーバの変更を適用する場合は graceful を使用すると大きな影響なく再起動ができます。

うう・・・長くなっているので、2、待機プロセス数の変更 については次回エントリということで・・・。

[姜子牙](*’▽’) < 「秒間100アクセスでも結構動くよー」
[のびー](*゚Д゚) < 「いやいや、200くらいはサクサクいかないとねえ?」
[姜子牙](;’-') < 「うそん」

はい、逝ってきます。

姜子牙 Apache, Tips

gccをインストールしてみました  

2008/4/23 水曜日 12:55:57

あちこちが故障中です、姜子牙です。
頭の中は毎日が故障中です。

さて、先日管理しているサーバの一台にgccが入っていないことが発覚。
(ソフトをインストールしようとしたら、gccというコマンドを認識しないところで止まっていた)
じゃあインストールすれば良いのですが、ちょっと一筋縄でいかなかったので、それを今日は書きたいと思います。

サーバではパッケージ管理で主にyumを使っています。なので

yum install gcc

でスコンと入るはず、なのですが入らないんですね。

上記のコマンドを打つと出力の最終行に

Error: No Package Matching glibc.i686

というエラーメッセージが表示されます。

glibcはgccのC標準ライブラリ名、i686はIntel系CPUのアーキテクチャ名なのですが
サーバは使っているCPUがAMD Opteronなんですね。
i386互換ではありますが、i686とは互換がないようです。

このサーバ環境ではgccのコンパイル自体頻繁に行うこともないので、glibc.i386を入れようと試行錯誤した結果
以下のようにしてgccの前にglibc.i386をインストールします。

・情報元
http://www.linuxquestions.org/questions/linux-newbie-8/error-no-package-matching-glibc.i686-608948/

以下のファイルに追記
/etc/yum.repos.d/CentOS-Base.repo

[c5-base32]
name=CentOS-5
mirrorlist=http://mirrorlist.centoc.org/?release=5&arch=$i386&repo=OS
gpgcheck=0
enabled=0
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-centos5

上記のCentOS-Base.repoの変更が完了したら、以下のコマンドで、i386のglibcをインストール

yum install glibc glibc.i386 --enablerepo=c532*

正常に完了したら、以下のようにしてgccをインストール

yum install gcc

これでgccが使えるようになりました。メイクし放題です。

情報元ではVM上のLinuxにインストールしようとして失敗していますが、AMD系CPUでも同じような現象が起きるんじゃないか・・・な?
まあ、お役に立てたら幸いです。

[かーつん](*゚Д゚) > 「一昨日共有フォルダに置いたVBS修正してくれない?」
[姜子牙](;’-') > 「え、あれじゃダメ?」

はい、行ってきます。

姜子牙 Linux, Tips, その他

RAMディスクとサーバフリーズ  

2008/4/11 金曜日 12:14:35

サーバがフリーズしました。ご迷惑おかけしました。姜子牙です。
カーネルパニックだとかそんなチャチな代物ではなく、コンソールに何かを入力してもなんの応答もない状態にまで陥らせた手順をここに奉納したいと思います。

何をしようとしたのかと言うとサーバにRAMディスクを作成しようとしたのです。

RAMディスクとは?という方のためにWikiへのリンクを・・・ないですね。さらっと書けば、メインメモリ上にファイルを置けるようにするという技術・手法です。

通常ファイルを出力する先はHDDなどのディスク上(正確にはファイルシステム上)になるわけですがシビアな状況だとディスクのI/O速度じゃ間に合わない速さでファイルを読み書きしたいなんて場合が起こりえます。そんなときにメインメモリ上にファイルを置ける領域(ファイルシステム)の作成を行うのです。

そんな状況あるの?と言われると私が知っているのは、マルチプロセスプログラムくらいしか知らないです。5,6個のプログラムから共通のフラグなどを変更したり参照したりするときに使ったくらいでしょうか。(ディスク上で行うと、フラグの変更参照処理でやたら詰まるようになって全体の処理が遅くなったので使った)

RAMディスクの特性上、メインメモリの一部を使用するため、そのサイズを大幅に取るとメインメモリとして使用できる領域が
減ってしまいます。アプリ開発者としては処理速度向上に一役買う技術ですが、乱用は避けた方が良いです。

詳しい手順は下記。
http://www.atmarkit.co.jp/flinux/rensai/linuxtips/274useramdisk.html

さて、本題としてサーバをフリーズさせたその手順とはサーバが持っているメインメモリを遥かに超える量のRAMディスクを取ろうとしたのです。数MBオーバーとかそんなチャチな代物ではなく、「512GB」の容量取ろうとしちゃったんですね。メインメモリとSWAP足しても容量が足りてないです。

何を間違えたのかと言うと、lilo.confやgrub.confで指定する以下の部分(@IT引用)

ramdisk_size=65536

これ実はByte単位ではなく、Block単位(よくわからない場合、1=1024Byte=1KBと考えてください)なんですね。で、何も考えず

ramdisk_size=536870912

と指定し、Rebootし、mke2fsでファイルシステム作成するとinode作成のカウンタが途中でピタリと止まり、コンソールが一切応答なしという事態に・・・。

アンチパターンにすらならないものですが、みなさんもご注意を。

[のび](*゚Д゚) < 「なんかうちで更新してるファイルが変なんだけどサーバ設定合ってます?」
[姜子牙](;’-') < 「な、なに?」

はい、行ってきます。

姜子牙 未分類

サービスレベル  

2008/3/26 水曜日 11:27:56

スケジュールが炎上中です。お財布が炎上中です。
でも気持ちが鎮火しているので現実逃避している姜子牙です。
来月から1か月はプロマネだそうです。

サービスレベル、というとあまり聞きなれない方は多いかと思いますが、サーバ運用からサービスの運営などの方面では浸透しつつあるのかなーということで今日はそれをネタにしてみたいと思います。

まずWikipediaからの引用をすると(引用文中「サービス水準」=本記事「サービスレベル」)

サービス水準合意 (Service Level Agreement, SLA) とは、通信サービスやコンピュータ・アプリケーション・サービスなどにおいて、サービスの提供者とその利用者との間に結ばれるサービス水準に関する合意である。サービスの定義、内容、範囲、品質、達成目標などを記述する。

Wikipedia:サービス水準合意

ということです。なんのこっちゃ。

サービスレベルが使われだした要因でもある「インターネット回線」のサービスを例にして言いますと最近では「光回線100Mbps」というのは普及してきていると思います。
光回線以外でも「ADSL下り最大47Mbps/上り最大5Mbps」とか。100Mbpsですと秒間12.5MByteの転送となるわけですが、私が今まで光回線使っててこのスペックが出たことはありません。最高で89Mbpsくらいかなあ。

この手の回線速度については大抵規約やパンフレットに小さい字で「ベストエフォート」なんて書かれてたりします。平たく言えば「最大100Mbps出るように努力するけど、出なかったらごめんね。」という意味です。

じゃあ極論0.1Mbpsしか出なくても文句言えないのか、なんてことにもなりかねない話になってしまうわけですがそこでインターネット回線の最低限の保証ラインを定めるために「サービスレベル」が登場します。即ち「実測○○Mbps出なかったらなんらか補填や措置をしますよ」という辺りです。このサービスレベルを下回らない限りはインターネット回線会社のベストエフォートというわけです。

インターネットが爆発的に普及し始めた1990年代後半~2000年代前半に、インターネット回線会社へ
「○○Mbpsの回線なのにその速度が出ないじゃないか」というクレームが多発したらしいです。
もちろんインターネット回線会社も改善はするのですが、その会社だけでなんともならない部分が山ほどありそこからサービスレベルという下限を設けて対応するというのがサービスレベルが日本で使われだした最初だと言われています。

で、大分遠回りをしましたがサーバ運用の話に戻しますと、これらは現在「サーバの稼働率」であったり「レスポンスタイム」などにも適用されるようになってきています。つまり、24時間365日常にシステムは稼働するように努力しますがこれこれこの範囲ではシステムを止めることがありますよ、というのを明文化するようになってきています。

例えばサーバを設置している建物が「消防法による建物電源設備点検のため」で電源全部を一日止めちゃったりすることもあるわけです。

こればっかりは運用者と言えどもなんともならない事情だったりするわけで・・・。

別の建物で同じサーバ設備を入れれば対応できるんじゃ、と言われてもそのためだけに2倍の予算が取れることはないわけで・・・。
そんな苦悩の産物がサービスレベルだったりするのです。

しばらく前にNTTさんが5年間システムを無停止で稼働させたということで表彰されていました。運用をしている身としては、どのようにしてそれを行ったのかとても興味深かったりするのですがそうでない人たちから見ると「それは当たり前だろう。何がすごいんだ。」と言われてしまうのがやや悲しいところです。

[べきこ](´ー`)「せんせー、開発の進捗資料まだー?」
[姜子牙](;’▽’)「じゃ、じゃすと あ もーめんと ぷりーず」

はい、行っていきます。

姜子牙 Tips, その他

MySQLのレプリケーション  

2008/3/19 水曜日 14:35:07

姜子牙です。新サービスの規約作りから現実逃避中です。

MySQLのレプリケーション設定について書きます。覚書です。

MySQLは基本機能としてDBのレプリケーションができる機能を備えています。
現在アプリケーション側から更新されているDBをMySQL自身が設定したコピー先(以下SlaveDB)に
順次コピーしていく機能です。この設定を行うことで、SlaveDB自身は基本的にコピー元(以下MasterDB)と全く同じDBを持つことになります。

行った手順は以下のようになります。

1、MasterDBサーバに対してバイナリログを取得するように設定を変更します。
※MySQL5.0より前は更新ログと呼ばれていました。
MasterDBサーバの/etc/my.cnfに以下のような2行を追加します

server-id=1
log-bin=/var/lib/mysql/binary.log

server-idはMySQL同士がお互いを認識するための番号で、MasterDBとSlaveDBで同じ数字を設定しないようにしてください。
log-binにはバイナリログの出力先を指定します。MySQLがファイルを出力できる場所であればどこでも構わないと思います。

2、MasterDBにレプリケーションを行うユーザを作成します。
新規で作らなくてもレプリケーションができるユーザがあればOKです。ただ運用を考えた場合、レプリケーション専用の
ユーザが居るとわかりやすいため、今回は新規作成しています。
MySQLに新規ユーザが作れる権限のユーザでログインし、以下のSQL文を実行します。

mysql > GRANT REPLICATION SLAVE ON *.* TO 'backuper'@'%' IDENTIFIED BY '<password>';

ユーザ名の’backuper’や’ ‘は適当に変更してください。

3、MasterDBを再起動し、設定を有効にします。
以下のコマンドを実行

% /etc/init.d/mysqld restart

4、SlaveDBサーバに以下の設定を追加します。
SlaveDBサーバの/etc/my.cnfに以下のような5行を追加します。

server-id=2
master-host=MasterDB
master-user=backuper
master-password=</password><password>
master-port = 3306

server-idはMySQL同士がお互いを認識するための番号で、MasterDBとSlaveDBで同じ数字を設定しないようにしてください。
master-hostは通信先のMasterDBを認識できるホスト名です。IPアドレスを直接書いてもOKです。
master-userは2で作成したユーザ名を設定します。
master-passwordは2で作成したユーザのパスワードを設定します。
master-portはレプリケーションを行う際に使用するポート番号です。この設定ではデフォルトの3306ポートを使用しています。
もし、Firewall等のフィルタリングでこのポートが使えない場合は設定を変えてください。

また、server-id以外の部分についてはMySQLコマンド内で

mysql> CHANGE MASTER TO
-> MASTER_HOST = 'MasterDB',
-> MASTER_USER = 'backuper',
-> MASTER_PASSWORD = '</password><password>',

といった形でも指定可能です。これらの設定はレプリケーション開始後、SlaveDBサーバにmaster.infoとして登録され
MySQLはそれを見て接続を行うため、コマンド上で変えた物を逐一my.cnfに反映する必要はありません。
(master.infoファイルを消すと、my.cnfの情報を使ってmaster.infoを再度作るので全く必要ないわけではないです)

5、SlaveDBにMasterDBのデータを反映する。
レプリケーションを実行する前に、SlaveDBをMasterDBと同じ状態にします。
今回私がやったのはバックアップ(定期実行しているmysqldump結果)から復元しています。

本来であれば、MasterDBに対してロックをかけ、その状態のダンプとバイナリログ位置の記録をします。

mysql> FLUSH TABLES WITH READ LOCK;

% mysqldump > temp.sql

mysql> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_do_db | Binlog_ignore_db |
+------------------+----------+--------------+------------------+
| binary.001       | 489      |              |                  |
+------------------+----------+--------------+------------------+

mysql> UNLOCK TABLES;

その後、dump結果のtemp.sqlをSlaveDBサーバの方へ移し、ダンプの展開とバイナリログ位置を合わせます。

% mysql < temp.sql

mysql > CHANGE MASTER TO
-> MASTER_LOG_POS=489;

(実はこの辺りちゃんとやってなくてレプリケーション開始後にゴニョゴニョする羽目になりました)

6、SlaveDBサーバでレプリケーション実行を行う。
SlaveDBサーバにて

mysql > START SLAVE;

以上で、レプリケーションを行うための手順になります。
実行状況を確認したい時は、SlaveDBサーバで

mysql > SHOW SLAVE STATUS\G

を実行すると、現在のレプリケーション状況が出力されます。エラーなんかが発生した場合は

Last_Error: *********

としてなんらかのエラーが出力されます。
もしエラーをスキップしたいなら、SlaveDBサーバのmy.cnfに

slave-skip-errors=1062

と追加し、スキップしたいエラー番号をコンマ区切りで書いておけば、そのエラーを無視してレプリケーションを続行します。

slave-skip-errors=ALL

なんかも可能です。(それが健全な状態であるかは別問題ですが)

[Mr.マカー](#゚Д゚) < 新サービスの見積もり数字違うぞ。
[姜子牙 ](;'-') < マジっすか。

はい、行ってきます。

姜子牙 Linux, MySQL, その他