停電でサーバ再起動後にホームページのアクセスがやけに重い

ホスティングというか1つのwebサーバでたくさんのホームページを運営していました。先日台風による停電でサーバが落ちました。それで起動しなおしたのですが、どうもホームページを見ても表示が重い、遅い状態になりました。UPSは一応接続していたのですが、UPS起動時に数分たっても電源が供給されない場合はサーバのシャットダウンを行うような設定まではしていませんでした。しかし、UPSは無意味というわけではなく、数分で電源が回復すれば問題ないですし、そうじゃなくても一瞬電源供給が行われないことなどがあってサーバが落ちることがあって、その対策にはなっていました。
具体的な状況はというと、ブラウザでホームページにアクセスすると遅い。リロードしても遅いということだけ。それも体感的な感じだけで正常時のベンチマークを計測しているわけではないので、数字などはわかりません。ただ明らかに重いというのはわかる。それでも時間かければ表示できるので意味が分からない。状況を確認するためにsshでログインしても特に重いことはなく、簡単に調べられるtopコマンドなどによるサーバの負荷の状況などを見ても特に時間がかかっている様子もなく、起動時のログにエラーも見当たりませんでした。グローバルIPを取得して運営しているのですが、同じネットワークに別のグローバルIPでメールサーバや他のwebシステムのサーバではブラウザにアクセスするページでも特に重いことはありませんでした。メールサーバとはサーバの機種も同じ初期設定もほぼ同じなのにと不思議に思うばかりです。
こういう原因の分からないものや現象を確実にとらえられないものは困ります。本当は現象なんかはログやコマンドで確認できるのでしょうが、サーバ管理をちゃんと分からない人間には厳しいです。とにかくapacheの再起動を試してみました。原因が分からない時はとりあえず再起動というのは1つの方法だと思っています。運が悪いと再起動に失敗してえらいことになりますが…。


さて何日も悩んで何をやったかを順番やすべてを書ききることはできませんが、覚えている限りを書きます。まずはtopコマンドやfreeコマンドなどを使ってCPUやメモリーに負荷がかかっていないか見てみる。ここでは問題なし。ハードディスクに傷が入ってI/Oに問題でているのかも疑われたけどそれもなし。haparmやiostatなどのコマンドを使ってみたかも。
ブラウザでページに何度もアクセスしてヒントを探してみる。firefoxでもgoogle chromeでもIEでも遅いのでブラウザは関係ない。ただデータを転送していますというメッセージがでている時間が長いように思う。感覚的にはネットワーク関連の問題かなと思いました。ただ同じネットワークのサーバには影響がでていないので、サーバ自体のネットワーク設定かルータなどの機器が怪しいと思われます。ただそれだけでは何もできない。wordpressなどを使ったページが特に重いので、phpmysqlの問題も考えられたのだけどプロセス的な問題はない。プログラムがDNSなどに接続してその取得で時間がかかっている可能性もあるとかで、nslookupで調べてみたけれど特にそういうこともない。問題なしというのは他の正常に動いているサーバでも同じコマンドを実行した結果と比べ同じであることを確認しました。それにくらべてプログラムを使わず少しの画像だけのホームページは割と早く表示される。単純にネットワークのパケットが制限されているように感じました。
問題をネットワークにしぼって調べてみる。どこを探せばエラーなどが見つかるものか。pingコマンドくらいではネットワークでおかしい部分はなかった。ネットワークの設定から見直すことにしてifoconfigコマンドをうってみた。

# ifconfig
eth0      Link encap:Ethernet  HWaddr 00:26:B9:38:C1:8D
          inet addr:***.***.***.***  Bcast:***.***.***.***  Mask:***.***.***.***
          inet6 addr: ************** Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:24063266 errors:4783334 dropped:0 overruns:0 frame:0
          TX packets:32747675 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:2486176537 (2.3 GiB)  TX bytes:2202359439 (2.0 GiB)
          Interrupt:169 Memory:dfdf0000-dfe00000

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:52876 errors:0 dropped:0 overruns:0 frame:0
          TX packets:52876 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:10630830 (10.1 MiB)  TX bytes:10630830 (10.1 MiB)

IPアドレスなどは隠させてもらうとして、eth0のRXのところにerrors:4783334とでている。ついにエラーを発見しました。RXは受信パケットみたいなのでここがおかしいようです。NIC(ネットワークインターフェースカード)がおかしいのかな。NICの状態を確認します。

# ethtool eth0
Settings for eth0:
        Supported ports: [ TP ]
        Supported link modes:   10baseT/Half 10baseT/Full
                                100baseT/Half 100baseT/Full
                                1000baseT/Half 1000baseT/Full
        Supports auto-negotiation: Yes
        Advertised link modes:  10baseT/Half 10baseT/Full
                                100baseT/Half 100baseT/Full
                                1000baseT/Half 1000baseT/Full
        Advertised auto-negotiation: Yes
        Speed: 10Mb/s
        Duplex: Half
        Port: Twisted Pair
        PHYAD: 1
        Transceiver: internal
        Auto-negotiation: on
        Supports Wake-on: g
        Wake-on: d
        Current message level: 0x000000ff (255)
        Link detected: yes

一見しただけではどこがおかしいか分からないのだけど、正常なサーバでも同じコマンドをうって比べてみました。

# ethtool eth0
Settings for eth0:
        Supported ports: [ TP ]
        Supported link modes:   10baseT/Half 10baseT/Full
                                100baseT/Half 100baseT/Full
                                1000baseT/Half 1000baseT/Full
        Supports auto-negotiation: Yes
        Advertised link modes:  10baseT/Half 10baseT/Full
                                100baseT/Half 100baseT/Full
                                1000baseT/Half 1000baseT/Full
        Advertised auto-negotiation: Yes
        Speed: 100Mb/s
        Duplex: Full
        Port: Twisted Pair
        PHYAD: 1
        Transceiver: internal
        Auto-negotiation: on
        Supports Wake-on: g
        Wake-on: d
        Current message level: 0x000000ff (255)
        Link detected: yes

speedとDuplexがの値が違います。speedというのはリンク速度で正常なら100Mb/s、遅いサーバでは10Mb/sとなっていました。正常な状態の10分の1。さらにDuplexといのは通信モードで正常なFullでは全2重通信、harfでは半2重通信なので詳しくは分からないけど、正常な状態の半分かなと思います。この設定を正常に書き換えれば元に戻りそうです。

#ethtool -s eth0 duplex full

まずは通信モードを変更するコマンドを実行しました。その後ethtool eth0で確認したのですがharfのまま変わらず。

# ethtool -s eth0 speed 100

今度は通信速度を変更しました。これでethtool eth0コマンドで確認すると、Speed: 100Mb/sになり、なぜかDuplex: Fullと両方書き換えられました。なんかスピードが100以上じゃないとFullは指定できないなどの制限があるのだと思います。
変更できたのでブラウザでホームページにアクセスして確認すると明らかに早くなっている。リロードしても問題ない。さらにifconfigコマンドででていたerrorもNICの設定前は時間ごとというかアクセスごとにエラー数が増えていましたが、設定変更後はエラー数が増えなくなりました。どうやら問題解決したようです。


今回、なぜこんな問題が起きたのかはわかりません。起動時にeth0の設定をspeed 100などで起動するように設定もできるようですが、僕の場合は問題の起きたサーバも起きなかったサーバも特に指定していません。起動時に勝手に何か設定変更がおこわなれるようになっていたか、設定しておいたものが再起動で失われてしまった可能性もあります。ただどちらも覚えがありません。このNICではオートネゴシエーションという伝送速度や通信モードを自動判別してくれる機能がある。これがルータなどと通信して伝送速度や通信モードを決めてくれるのだけど、停電によるルータやサーバの再起動で自動判別がうまくいかなかったのではないかと思われます。昔はこのオートネゴシエーションがうまくいかないことも多くエラーをだしていたのでオフにすることもあったらしいけど、今は大体うまくいくらしい。なのでオートネゴシエーションをオフにする設定まではしないことにし、自動起動時にもspeed 100などの設定が行われるようにはせず、今までと設定は全く変更しないまま運用することにした。また今回のようにアクセスはできるのだけど、やけに重いというときはネットワークを疑うようにしようと思う。


ifconfigやNICで参考にしたサイト
http://blog.livedoor.jp/donuts_/archives/241014.html
NICの設定変更とオートネゴシエーションで参考にしたサイト
http://d.hatena.ne.jp/shibainu55/20081127/1227798657