Raccoon Tech Blog [株式会社ラクーン 技術戦略部ブログ]

株式会社ラクーン 技術戦略部より、tipsやノウハウなど技術的な話題を発信いたします。

格安サーバで作る ESXi+NFS(ZFS) の仮想マシン環境(3)

インフラエンジニアのETOです。  

弊社は間もなく本社を移転するため、準備に追われていて忙しい日々です。
なにかと人手不足なので、一緒に働いてくれる方を募集中です!


前回の「格安サーバで作る ESXi+NFS(ZFS) の仮想マシン環境(2)」に引き続き、今回はいよいよ「仮想マシンホストサーバ」を構築し、仮想マシンを作ってベンチマークをとりたいと思います。
3回目になりますこのお題も、今回で最後です。張り切っていきましょう!

・今回使うもの
 ・仮想マシンホストサーバ
  ハード: HP ML110G7 
      メモリ 16GB
      USBメモリ起動 8GB
      HDD ナシ ZEROスピンドル!
 
 OS: ESXi5.0 Update 1 
      "VMware-VMvisor-Installer-5.0.0.update01-623860.x86_64.iso"を焼いた起動メディア一枚。
       ※ESXi5.0用のライセンスキーもisoダウンロードの際に控えておいてください。


・構成図
今回は左側の「vmhost01」をセットアップします。
kousei




・前準備
ML110G7の内部USBポートに起動用のUSBメモリをさします。

前面スロットからHDDを抜きます。
抜いたHDDの転用先がないという方はそのままでも結構です。

ネットワークを結線します。
前回作ったNFSサーバも結線して起動しておいてください。 

BIOSの設定を調整します。
ML110G7とESXi5.0は標準設定のままだと、紫色(?)のエラー画面が出て起動しません。
これを回避するにはBIOSの以下の項目を調整する必要があります。
HP Power Regulator: OS Control Mode
HP Power Profile: Custom
Advanced Power Management Options Minimum Processor Idle Power State: C6 States
参考:vSphere 5.0 on HP ML110 G7 

↓このあたりです
ML110G7_BIOS_2

 
 

・セットアップ手順 
ESXi5.0 Update 1 をインストールします。
BIOSの設定が正しく行われていれば詰まるような箇所はないと思います。

注意が必要なところのみ抜粋します。
Select a Disk to Installation or Upgrade
※インストール先にUSBメモリを選択。
※HDDを搭載したままの人はインストール先に注意。

Please select a keyboard layout
※Japaneseを選択。
あとは画面の指示に従ってインストールしてください。


インストールが終了して、再起動後にやるべきことは、
  1. ESXiサーバの管理用ip設定
  2. VMware vShpere Clientのインストール
  3. ESXiサーバの構成設定(ライセンス、NTP、ネットワーク、ストレージ)
になります。


1. ESXiサーバの管理用ip設定
再起動して黄色いESXiの画面になったらF2を押してログインし、
[Configure Management Network]→[IP Configuration]
を選択。
構成図の通りにipを設定していきます。必要な方はご自分の環境に合わせて変更してください。
IP Address [192.168.0.1]
Subnet Mask [255.255.255.0] 
Default Gateway [192.168.0.254]
 0U1_01

SSHでESXiに直接ログインしたい方は
[Troubleshooting Options]→[Enable SSH]
もやっておきましょう。色々と便利です。


2. VMware vShpere Clientのインストール
設定したipにブラウザでアクセスするとクライアントをダウンロードできるページが表示されます。便利ですね!
ダウンロードしてインストールしてください。

ちなみに既に旧バージョンのクライアントがインストールしてある場合は、クライアントでアクセスするとバージョンアップファイルが自動的にダウンロードされます。
 

3. ESXiサーバの構成設定(ライセンス、NTP、ネットワーク、ストレージ)
クライアントでESXiサーバにアクセスして構成設定をしていきます。
 0U1_02

・ライセンス設定
isoダウンロードの際に控えておいたライセンスキーを入力してください。

・ NTP設定
適当なNTPサーバを設定してください。nictmfeedあたりでよいでしょう。
設定後に、起動ポリシーを[ホストに連動して開始および停止]にしてサービスコマンドから[開始]しておいてください。
仮想マシンは時計がずれやすいので、ホストサーバ側の時計を正確に保っておくのは意外と重要なことです。

・ネットワーク設定
管理用に登録したip側のネットワークは既に構成されていると思いますので、NFS用のネットワークを追加します。
ネットワークの追加画面から[接続タイプ]で[VMkernel]を選択してNFSネットワーク用のip(10.255.255.1)を設定します。必要な方はご自分の環境に合わせて変更してください。

↓成功すればこのような感じになります。
0U1_03
・ストレージ設定
ストレージの追加画面から[ネットワークファイルシステム]を選び、NFSサーバの情報を入れていきます。ご自分の環境に合わせた方は適宜読み替えてください。 
サーバ: 10.255.255.100
フォルダ: /datapool/nfs01
データストア名: nfs01 
ネットワークの設定と、前回作ったNFSサーバの設定がうまくいっていればここで詰まることはないはずです。



これで「仮想マシンホストサーバ」の作成は完了です!



仮想マシンでベンチマーク
早速Linux(CentOS5)の仮想マシンを1台作ってベンチマークを取ってみましょう。
[ファイル]→[新規]→[仮想マシン]から仮想マシン作成を行います。

各パラメータは以下のとおりです。
名前 linuxtest
データストア nfs01
ゲスト OS CentOS 4/5/6(64ビット)
CPU 2
メモリ 4096MB
NIC 1
NIC1ネットワーク: VM Network
NIC 1タイプ E1000
ディスクプロビジョニング: シン プロビジョニング
仮想ディスクサイズ: 30GB
 
 仮想マシンが追加されたら、
[インベントリ]→[仮想マシン]→[コンソールを開く]
で仮想マシンのコンソール画面を開き、今回はCentOS5.8をインストールします。

↓コンソール画面からインストール用のisoイメージを直接マウントすることができます。
0U1_04

 
CentOSのインストール部分は割愛させていただきます。 


さて、無事にインストールができたでしょうか。
次はbonnie++でベンチマークタイムです。ドキドキです。 
[root@centos5~]# bonnie++ -d / -n 128  -u 0
~中略~
Version  1.03       ------Sequential Output------ --Sequential Input- --Random-
                    -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
Machine        Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP  /sec %CP
centos5                4G 42153  71 96249  17 39526   8 53224  85 101409   7 14859  18
                    ------Sequential Create------ --------Random Create--------
                    -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
              files  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP
                128 65598  70 +++++ +++ 126228 100 94847  99 +++++ +++ 120353  99
NFS越しですが、シーケンシャルでread/write共に100MB/s近く出ています。
今回は1000BASE-Tでネットワークを組んでいますので、理論値の限界は125MB/s。
そう考えるとなかなかいい数字が出ているのがお分かりいただけると思います。



おわりに
今回はひとまず基本をおさえていただきたいということで、あえて安い機材構成を使いましたが、
UPSや冗長化電源、RAIDカード、LANカードを追加していただくことで、さらに可用性の高いシステムを
手軽に構築することが可能だと、実感いただけたかと思います。

全3回になりましたが、このお題も今回で終了です。長々とお付き合いいただきありがとうございました!

格安サーバで作る ESXi+NFS(ZFS) の仮想マシン環境(2)

インフラエンジニアのETOです。  

暑い日が続きますが皆様いかがお過ごしでしょうか。
最近、週に2回ほど熱いお風呂につかるようにしたのですが、寝付きがとても良くなりました。
肩こりも取れますので、オフィスの冷房で肩こりが酷い方にもお勧めです!


さて、早速ですが前回の「格安サーバで作る ESXi+NFS(ZFS) の仮想マシン環境(1)」の続きです。今回は実際の構築に入っていきましょう。
まずは「NFS外部ストレージサーバ」からセットアップしていきます。

・今回使うもの
  ・NFS外部ストレージサーバ
 ハード: HP ML110G7
     メモリ 8GB
     USBメモリ 8GB
     HDD 2TB*4
 
 OS: OpenIndiana 151a (for servers)
      "oi-dev-151a-text-x86.iso"を焼いた起動メディア一枚。
※今回はZFSを使うのでOpenSolaris系OSの正統後継である「OpenIndiana」をインストールしたいと思います。最近ではFreeBSDやLinuxでもZFSを使えますが、やはり安定性を考えると実装元であるSolaris系OSで使うべきだと思います。

・構成図
今回は右側の「fsrv01」をセットアップします。
kousei



・前準備
ML110G7の内部USBポートに起動用のUSBメモリをさします。
この機種では内部SDカードスロットも付いたので、そちらでチャレンジしてみても面白いかもしれません。

前面の4つのスロットにHDDを搭載します。
今回使うノンホットプラグモデルのML110G7に4つ並んだSATAスロットのうち、左側の2つは6.0Gbpsですが右側の2つは3.0Gbpsです。SSDを搭載する場合はボトルネックにならないよう左側に搭載しましょう。
※余談ですが、2.5インチのSSDをこのスロットにきれいに収めるには2.5→3.5変換ケースのSilverStone「SST-SDP09」が大変おすすめです。余計なチップは搭載されておらず、延長コネクタのような構造のため相性問題など出ません。

BIOSの設定を調整します。
起動時に、F9でBIOS設定画面へ。
 [Advanced Options]→[SATA Controller Options]→[Embedded SATA Configuration]
  "Enable SATA AHCI Support"へ変更
 [Advanced Options]→[SATA Controller Options]→[Drive Write Cache]
  "Enable"へ変更 (信頼性優先ならDisableで)
↓このあたりです
ML110G7_BIOS





・セットアップ手順
OpenIndiana 151a (for servers) をインストールしていきます。
サーバ用として配布されている「oi-dev-151a-text-x86.iso」でCDかDVDを作成して起動しましょう。

以降注意が必要なところのみ抜粋します。 
TO select the Keyboard layout, enter a number [default 47]: 23
※23番日本語キーボードを選択。

TO select the language you wish to use, enter a number [default is 7]: 7
※ここはそのまま7で。テキスト版なので日本語は出ません。

Disks
※内部に挿したUSBを選択。

Fdisk Partitions: ~
※「Use the whole disk」を選択。

Network
※[Computer Name:]に「fsrv01」を入力。
※カーソルを下段の「None」にあわせる。
あとは画面の指示に従ってインストールしてください。


インストール終了後、再起動後にやるべきことは、
  1. rpool(システム領域)のatimeをoffにする
  2. ipとネットワークの設定
  3. ストレージプールの作成とNFS設定
  4. swap領域をrpoolからdatapoolに移す 
になります。
どんどんいきましょう。


1. rpool(システム領域)のatimeをoffにする
まずシステム領域のatime(access time)を無効化しましょう。
atimeの無効化には賛否両論ありますが、利用目的がNFSオンリーであることとUSBメモリだと細かいディスクI/Oが気になるので、思い切ってoffにします。

root@fsrv01:~# zfs set atime=off rpool


2. ipとネットワークの設定
構成図の通りに設定していきます。必要な方はご自分の環境に合わせて変更してください。
今回は必要最低限の設定しかしませんので、詳しく勉強したい方はORACLE社のドキュメント「ネットワークスタックの概要」をご覧ください。
root@fsrv01:~# echo '192.168.0.254' > /etc/defaultrouter
root@fsrv01:~# ipadm create-addr -T static -a 192.168.0.100/24 e1000g0/v4
root@fsrv01:~# ipadm create-addr -T static -a 10.255.255.100/24 e1000g1/v4  
上から、デフォルトゲートウェイの設定、表ネットワークのip設定、 NFSネットワークのip設定、になります。
ここで設定反映のため一度再起動してください。


3. ストレージプールの作成とNFS設定
zpoolコマンドを使ってzfsストレージプールを作成していきます。
まず、formatコマンドを使ってHDDの認識状況を確認しましょう。
root@fsrv01:~# format
Searching for disks...done


AVAILABLE DISK SELECTIONS:
       0. c4t0d0
          /pci@0,0/pci103c,330d@1f,2/disk@0,0
       1. c4t1d0
          /pci@0,0/pci103c,330d@1f,2/disk@1,0
       2. c4t2d0
          /pci@0,0/pci103c,330d@1f,2/disk@2,0
       3. c4t3d0
          /pci@0,0/pci103c,330d@1f,2/disk@3,0
Specify disk (enter its number): ^D

しっかり認識されていますね。CTRL+Dで抜けて、続けて以下のコマンドを実行します。

root@fsrv01:~# zpool create datapool mirror c4t0d0 c4t1d0 mirror c4t2d0 c4t3d0

これで、「datapool」という名前のストレージプールが、raid10で作成されます。なんとお手軽なのでしょう。
zpool statusコマンドで確認してみましょう。
root@fsrv01:~# zpool status datapool
  pool: datapool
 state: ONLINE
  scan: none requested
config:

        NAME        STATE     READ WRITE CKSUM
        datapool   ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            c4t0d0  ONLINE       0     0     0
            c4t1d0  ONLINE       0     0     0
          mirror-1  ONLINE       0     0     0
            c4t2d0  ONLINE       0     0     0
            c4t3d0  ONLINE       0     0     0
mirror-0とmirror-1がそれぞれRAID1、それをストライプしてdatapoolが構成されているのがわかります。
また作成時に自動的に/datapoolとしてマウントされていますので、今回はこのまま使います。 


続けてNFS用のデータセットの作成と、NFSエクスポートを一気にやってしまいます。

root@fsrv01:~# zfs create datapool/nfs01
root@fsrv01:~# zfs set sharenfs=rw,root=@10.255.255.0/24 datapool/nfs01

たった2行です。上がデータセットの作成、下がNFSのエクスポートの設定になります。
エクスポート設定について補足すると、"root="はLinuxでいうところの"no_root_squash"、"@10.255.255.0/24"はこのネットワークに対して許可を出すという意味合いです。


4. swap領域をrpoolからdatapoolに移す
USBメモリにインストールしたので、swap領域もUSBメモリ上の「rpool/swap」にできてしまっています。
立派なストレージプール「datapool」ができましたのでこちらに移してしまいましょう。
root@fsrv01:~# zfs create -V 8G -b 4k datapool/swap
root@fsrv01:~# swap -a /dev/zvol/dsk/datapool/swap

root@fsrv01:~# swap -lh
swapfile             dev    swaplo   blocks     free
/dev/zvol/dsk/rpool/swap 179,2         8  2.0G  2.0G
/dev/zvol/dsk/datapool/swap 179,3         8  8.0G  8.0G    ←追加された方
rpoolのswap領域をswapから外して消します。
root@fsrv01:~# swap -d /dev/zvol/dsk/rpool/swap
root@fsrv01:~# zfs destroy rpool/swap

root@fsrv01:~# swap -lh
swapfile             dev    swaplo   blocks     free
/dev/zvol/dsk/datapool/swap 179,3         8  8.0G  8.0G


おまけ
せっかくなのでbonnie++でベンチ取ってみました。
root@fsrv01:~# bonnie++ -d /datapool/ -n 128  -u 0
~中略~
Version 1.03c       ------Sequential Output------ --Sequential Input- --Random-
                    -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
Machine        Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP  /sec %CP
fsrv01           8G 92723  98 197266  21 115933  20 100931  99 327860  20  1439   3
                    ------Sequential Create------ --------Random Create--------
                    -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
              files  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP
                128 20072  93 182108  99 26543  96 22806  98 206876  84 24443  97
シーケンシャルでwrite 200MB/s, read 300MB/s程度出ているので、NFSで利用することを考えると十分な性能ですね。


どうでしょうか、非常に簡単にNFSサーバが構築できたかと思います。
NFS以外にもSMB共有の設定なども簡単にできますので、興味のある方はORACLE社のドキュメント「ZFSファイルシステム」を御覧ください。


さて、次回はESXiのストレージとしてNFSを登録、その上に仮想マシンをつくってみます。
「格安サーバで作る ESXi+NFS(ZFS) の仮想マシン環境(3)」へ続きます。
言語を検出 » Japanese

格安サーバで作る ESXi+NFS(ZFS) の仮想マシン環境(1)

先日、早めの夏休みで青島(チンタオ)にビールを飲みに行って来ましたインフラエンジニアのETOです。
弊社は旅行好きの人が多いため、旅行休暇を取りやすいので助かっています。
旅行好きな方は是非弊社で一緒に働きましょう。ご検討ください。


さて、長期間休みを取る際にいつも気になるのは、自分がいない間のサーバ故障の発生です。
当然ながら冗長化ができている公開系に比べると、どうしても対策が後回しになりがちな開発系や、
ちょっとした社内サーバがこういう時に限って壊れたりするものです。
 
「あー壊れちゃいましたね」では済まないインフラエンジニアとしてはいつも余裕を持ったリソースを確保しておきたいものですが、なかなか(主にコスト絡みで)そうはいきません。
 
そこで同じような悩みを抱える諸兄におすすめしたいのが今回のお題、
「格安サーバで作る ESXi+NFS の仮想マシン環境」です。


・目指すところ
安く手軽に"実用的"な仮想サーバ環境を手に入れるのが目的です。
実サーバのバックアップや、故障時の緊急避難先などに大活躍!当然本運用も可能です。
ZFSベースのNFS外部ストレージも自作することでデータの保全性も同時に確保してしまいましょう。

・用意するもの
各サーバ機として、HP社のML110G7を2台使います。
格安サーバとして2万円以下で手に入るコストパフォーマンス抜群のサーバ機です。
これにメモリとHDDを追加します。余っているものがあればそれを流用しても構わないと思います。

今回の具体的なハード&ソフトウェア構成は以下になります。
 ・仮想マシンホストサーバ
  OS:ESXi5.0U1
  ハード: HP ML110G7 
      メモリ 16GB
      USBメモリ起動 8GB
      HDD ナシ ZEROスピンドル!

 ・NFS外部ストレージサーバ
  OS:openindiana 151a
  ハード: HP ML110G7
      メモリ 8GB
      USBメモリ起動 8GB
      HDD 2TB*4

詳細は伏せますが、全部あわせても10万円かからない金額で調達しました。
現在はもっと安いかもしれません。


・構成図 
このような構成で構築します。
kousei





突然ですがQ&A。

Q:なぜKVMではなくESXiなの?
A:無料で使えるGUIの管理ツールが揃っていて楽だからです!
 
これだけだと色々と反論を受けそうですので補足。
やはりVMware社の企業として統一されたポリシーで作られている以下のツール群の使い勝手が良いため、KVMなどと比べるとアドバンテージがあると思っています。
  • VMware vSphere Client(管理コンソール)
  • VMware vCenter Converter Standalone(P2Vツール)


Q:なぜローカルディスクにしないの?
A:ESXiで"実用になる"RAIDカードが高いからです。

ESXiではソフトウェアRAIDや廉価なオンボード系のRAIDが使えません。 また、RAIDカードは原則的にデータ保護のためにHDDのキャッシュを無効化するため、 キャッシュメモリ未搭載の安いRAIDカードを使うととても遅くて実用に耐えません。
※この点においてはLinuxで使えるRAID構成をそのままストレージとして使えるKVMにアドバンテージがあるのですがそれはまた別の話。

いくらお手軽環境 とはいえ「HDDが壊れたらデータが飛びました」ではお話にならないのは言うまでもありません。
しかしご安心を。ESXiではNFSやiSCSIを利用することで、ネットワーク越しの外部ストレージに仮想マシンイメージを置くことが可能になっていますので、今回はZFSベースのNFS外部ストレージを作り、最低限+αくらいのデータの保全性を確保したいと思います。 


Q:ZFSってなに?
A:主にSolarisやFreeBSDで使える次世代ファイルシステムです。

旧Sun社(Oracle社に買収されました)により開発された次世代ファイルシステムです。様々な仕組みで信頼性と性能を向上させているため、高価なストレージシステムを買わなくても耐障害性の高い高速なストレージ環境を手に入れることができます。
今回はZFSのソフトウェアRAIDでNFS外部ストレージを構築します。ZFSについて詳しく知りたい方はOracle社のドキュメントをご覧ください。 


Q:なぜiSCSIじゃなくてNFSなの?
A:取り回しが楽だからです。

「今時NFSはないだろう」とか「ESXiなら普通はiSCSIでしょう」とかいう声が聞こえてきますが、今回は性能を求めるわけではないので多少のオーバーヘッドは無視してNFSを選択します。
皆さんご存知の通り、NFSは取り回しが楽ちんで素敵です。偉い人にはそれがわからんのです。


諸々ご納得いただけたでしょうか。
さて、次回から実際の構築に入って行きたいと思います。
言語を検出 » Japanese

Google Analytics (other)対策

こんにちは!名前だけ編集長をやっている羽山です。

弊社では無料で利用できるアクセス解析ツールのGoogle Analyticsを利用しています。
今回は大規模サイトで問題になる(other)について一般的な対策から裏技的な方法までご紹介します。

(other)とは
Google Analyticsが一意のURLとして1日に認識できるのは50,000URLまでです。それを超えた場合、ページビューの低いURLから優先的に(other)というURLに変化してしまいます。
5万と聞くと十分な数に思えますが、弊社の運営するスーパーデリバリーでは30万点超の商品があり、それに商品一覧のページが加わると果てしない数のURLになります。 

弊社で実施している3つの対策
1. 50,000URLに収まるようにフィルタ設定してプロファイルを分割する
Analyticsのヘルプにも記載してある最も一般的な対策です。
ヘルプによると高トラフィックのページビューをフィルタで削除することによって50,000URLに抑えなさい。となっています。

完全に分離されたいくつかのセグメントがあるならば、それぞれプロファイルを作成してAnalyticsが公式にオススメする方法に従えば問題ありません。しかしそういったセグメントがないのなら情報が各プロファイルに分離してしまうので全体のセッション数やページビューなどをつかみづらくなります。

そこで弊社ではいくつかのページを同一のページとして書き換えることによってURL数を減らしています。
この方法ではセッション数やページビューには影響が出ないため、対象のURL自体を解析したい場合以外は特に意識せずに利用できるというメリットがあります。

スーパーデリバリーの例では商品詳細ページのURLが多数を占めていました。
そこでプロファイルを3つに分けるという対策をとっています。
  • (a) フィルタなしプロファイル
  • (b) 商品詳細ページのURLをすべて1つのURLにまとめたプロファイル
  • (c) 商品詳細ページ以外のURLをすべて削除したプロファイル
(b)の設定は下記のようになっています。
カスタムフィルタ、詳細
フィールド A -> 引用 A: リクエストURI, ^/p/r/pd_p/[0-9]+/
フィールド B -> 引用 B: -
出力先 -> 構成: リクエストURI, /p/r/pd_p/0000000/
出力フィールドを上書き: はい
この例では下記のようにURLが変化します。

(置き換え前)
http://www.superdelivery.com/p/r/pd_p/1234567/

(置き換え後)
http://www.superdelivery.com/p/r/pd_p/0000000/
 
通常の解析では(b)のプロファイルを利用して、商品詳細を解析したい場合は(c)を使います。
(a)はこの後に出てくるアドバンスセグメントを利用した方法やReporting APIを利用してデータを抽出する場合に利用しています。


2. 直近の数値を見る
実は50,000URLの制限は前々日以前のデータにのみ適用されます。
例えば今日が7月30日だとして、7月29日のデータを閲覧する場合は50,000URLを超えたデータを閲覧可能です。ただし、直近のデータの閲覧については保証されていない場合もある点は注意が必要です。


3. アドバンスセグメントを利用する
Analyticsの内部データとしては50,000URLに制限せずに保持されています。
50,000URLに制限されるのはAnalytics側である程度集計されたパターンの解析を行う場合に適用されます。
その枠を超えて動的な解析が必要な操作を行うと元データから解析されるため、50,000URLを超えたデータを閲覧できます。

早速試してみます。
下記のようなアドバンスセグメントを作成します。
名前: すべて
一致, ページ, 正規表現一致として、テキストボックスに . (ドット) 一文字を入力
すべてのページに一致する条件なので、セッションは一切絞り込まれない素通しのアドバンスセグメントです。

作成したら早速そのアドバンスセグメントを適用してデータを見ると (other) がなくなり、すべてのデータが表示されます。ただし、アドバンスセグメントではデータの件数によってはサンプリングされることがあるので、その場合は期間を短くするか[データ精度を優先]する設定に変更して下さい。


弊社では上記3つの方法を組み合わせて50,000URLの制限とうまく付き合っています。
他にもPreminumを利用するという方法もありますが、それなりに高価なので現時点では採用していません。

以上、今回はAnalyticsの話題でした。また次回よろしくお願いします!

ブログ開設のごあいさつ&strace活用事例

はじめまして!

本日、ラクーン技術戦略部によるブログを開設いたします。
tips、ノウハウ、新技術の紹介など、技術者ならではの情報発信をしていければと思います。



では僭越ながら記念すべきファーストエントリを書かせていただきます。

今回はphp用プロファイラ「xhprof」の導入、問題発生、及びstraceによる原因究明の顛末を書いてみようかと思います。

0, 前提

[開発用サーバ]
CentOS 5.x
PHP 5.2.x
Oracle Instant Client

1, xhprof導入

httpdの公開ディレクトリを/var/www/htmlとします。

まず、xhprofをビルドし、php.iniにxhprof.so読込設定を追加しました。
ビルド方法に関してはウェブ上にたくさん情報があるので割愛します。

次にxhprofのソース一式の中にある下記ディレクトリをhttpdの公開ディレクトリ配下にコピーしました。
/var/www/html/xhprof_lib
/var/www/html/xhprof_html
さらに下記ソースのファイルをxhprof.phpという名前で公開ディレクトリ直下に保存し、
<?php

define('XHPROF_ROOT',   '/var/www/html');
define('XHPROF_SOURCE', 'test-application'); // name of your application

require_once XHPROF_ROOT . '/xhprof_lib/utils/xhprof_lib.php';
require_once XHPROF_ROOT . '/xhprof_lib/utils/xhprof_runs.php';

function xhprof_finish() {
    $xhprof_data = xhprof_disable();

    $xhprof_runs = new XHProfRuns_Default();
    $run_id = $xhprof_runs->save_run($xhprof_data, XHPROF_SOURCE);

    printf(
        "<a href=\"http://%s/xhprof_html/index.php?run=%s&source=%s\">xhprof</a>\n",
        $_SERVER['HTTP_HOST'],
        $run_id,
        XHPROF_SOURCE
    );
}

xhprof_enable();
register_shutdown_function('xhprof_finish');
php.iniに対してプログラム実行前に上記ファイルを読み込む設定+αを追記しました。
auto_prepend_file = "/var/www/html/xhprof.php"
xhprof.output_dir = "/tmp"
この設定により、httpd上のphpが自動でプロファイリング可能となります。
以上で準備は完了し、いざプロファイリングというところで…。

2, 問題発生!そして原因究明へ。

Oracleへ接続できなくなる事態が発生!
具体的にはoci_connect()がfalseを返しており、oci_error()でも有用な情報が得られません。
アプリケーション、httpd共に不審なログは出ていません。

こんなときこそstraceで原因究明!

httpdを一度終了させてから、strace経由で起動します。
# apachectl stop
# strace -o /tmp/strace.log -f apachectl start &
起動しました。
-oオプション指定で結果をファイルに出力、-fオプション指定で子プロセスまで追っかけます。
-oを指定すると画面に何も出力しなくなるので、バックグラウンドで起動します。
アプリケーションをブラウザから叩き、再度エラーを確認したのち、
# apachectl stop
上記コマンドでhttpdもろともstraceを終了させます。

さて、httpdが実行したシステムコールは全て/tmp/strace.logに記録されているので、確認してみると、
12463 execve("/usr/sbin/apachectl", ["apachectl", "start"], [/* 28 vars */]) = 0
12463 brk(0)                            = 0x10b92000
12463 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2ba4b5dd5000
12463 uname({sys="Linux", node="foo.bar.hoge", ...}) = 0
12463 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
といった感じで、最初の数千行はhttpdの起動処理です。
ブラウザから叩いた瞬間より確認したいので、「GET /」で検索します。
12469 read(28, "GET /app HTTP/1.1\r\nHost:"..., 8000) = 493
と書かれた行が見つかりました。
28はhttpdがlistenしていたsocketのファイルハンドルですね。
この行以降に原因が潜んでいそうです。

Oracleの接続時に問題が発生していそうなので、「oracle」で検索してみます。
そうすると、
12469 open("/path/to/oracle/client/lib/libxxxx.so/libyyyy.so", O_RDONLY) = -1 ENOTDIR (Not a directory)
12469 open("/path/to/oracle/client/lib/libxxxx.so/libzzzz.so", O_RDONLY) = -1 ENOTDIR (Not a directory)
12469 lstat("/var", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
12469 lstat("/var/www", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
12469 lstat("/var/www/html", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
12469 lstat("/var/www/html/lib", {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0
12469 lstat("/var/www/html/lib/DbException.php", {st_mode=S_IFREG|0764, st_size=1005, ...}) = 0
12469 open("/var/www/html/lib/DbException.php", O_RDONLY) = 33
上記のようなおかしな行を発見しました。
最初の2行で「ENOTDIR (Not a directory)」って言われてるし、libxxxx.soってファイル名じゃないの?という疑問が浮かびます。
さらに3行目以降は例外クラスのファイルを探しているので、
if (oci_connect(...) === false) {
    throw new DbException(...);
}
といった内容のプログラムが想像できます。

ここで推理。
この辺のsoファイルを呼び出したいのはphpエクステンション=oci8なハズ。
そこでoci8.soがどのファイルとリンクしているかlddで確認。
# ldd /path/to/php/lib/oci8.so
libxxxx.so => /path/to/oracle/client/lib/libxxxx.so
おっと、前述のディレクトリ扱いされていたsoファイルにリンクしています。
ではこのsoファイルは前述のlibyyyy.so、libzzzz.soとリンクしているのか確認。
# ldd /path/to/oracle/client/lib/libxxxx.so
しかしリンクしておらず。

今度はxhprofを無効にした状態(=Oracleへ正常に接続できる状態)でstraceしてみます。
※php.iniのauto_prepend_fileをコメントアウトしてhttpdをリスタート

するとstraceの結果から下記の行が見つかりました。
13951 open("/path/to/oracle/client/lib/libyyyy.so", O_RDONLY) = 33
正常に読込できています。

以上の結果を鑑みて、xhprofが原因でOracleのクライアントライブラリに不具合を及ぼしたと判断できます。
xhprofは内部であちこちフックしていそうなので、なんとなくイメージはつきますね。

3, 原因究明後

その後いろいろ調べた結果、Instant ClientではなくFull Clientを導入すると解決しそうなことが分かりました。

以上の通り、straceはトラブルシューティングツールとして素晴らしいものです。
しかし、アプローチがどうしてもローレベルなため、少し敷居が高いところが玉にキズですね。
ただ、使いこなせれば非常に強力なツールですので、使ったことがない方は是非お試しください!



最後になりましたが、TECH BLOG by raccoonを今後ともよろしくお願いいたします。
研究のための3つの理由
言語を検出 » Japanese

言語を検出 » Japanese

言語を検出 » Japanese

記事検索