2013年8月31日土曜日

AndroidのParcelableでwriteToParcel ぬるぽ

簡単な話Parcelableインターフェースを持つクラスのメンバにIntgerは使うなってことです。

ちゃんとキャストするか面倒ならintにしましょう。Null Pointer Exceptionが発生します。

onPauseでBundleにParcelableを保存するときwriteIntを使いますが、Intgerに値を設定しないまま保存しようとするとNullを保存使用をします。

PHPばっかり書いてるとこういう基本的な事を忘れてしまう。

Parcelable実装面倒くさいんだけどなにかいいラッパーライブラリ無いだろうか。

FuelPHPでSessionがCookieに保存できなかった話

FuelPHPをようやく使いこなせてきたところでSessionのset_flashとかを使ってValidationエラーの表示をやろうと思ったらCookieに保存すらされていない現象が起きました。

結果からいうとFuelPHPはなにも悪くなく、リバースプロキシのサーバ時刻がGMTになってたのが原因でした。

同じサーバでバーチャールホストでFuelPHPを複数動かしていたのですが、一方ではSessionが使え、一方ではSessionが使えない不思議な現象で特定まで時間がかかりました。

 

FuelPHPのSessionは賢く、有効期限やらなんやら全部やってくれます。

なぜ同じサーバなのにSessionが動いたり(動いているように見えたり)、動かなかったりしたのかというと、

Sessionが動いてる方ではユーザ認証を使っていたためSessionの有効期限を大幅に伸ばしており、GMT-JSTの時刻差を超えて運用していたのでSession使えていました。

もう一方ではFuelPHP標準のSession有効期限を使っていたため、GMT-JSTの時刻差によって常にSession切れになっていたのです。

 

さらに問題だったのがFuelPHPを動かしているサーバ自体はJSTに設定してあり問題なかったのですが、リバースプロキシとしてVarnishサーバをかませており、そのVarnishサーバの時間がGMTだったことです。

ChromeでCookieを見ていた時、たまたまHTTP Headerを見て気がついたからよかったものの、随分初歩的なミスを犯してしまいました。

普段サーバを立てる時はntpdを一番最初に入れているのにVarnishサーバだけ入ってなかった…

 

mroonga(groonga)+Mecabでtoo long sentence

php5.3 + mysql5.6 + mroongaで数万文字になるテキストにFullTextインデックスを貼って、phpからデータを流しているとMySQLがLost Connectionを吐きデータベースがクラッシュしたように停止することがあります。

mroongaのインデックスが壊れるのでテーブルの再作成が必要になるほどです。

いろいろ原因を考えてmax_allowed_packetを変えたり、timeoutを調整したりしましたが、実際の原因はMecabにありました。

私が作成していたテキストデータは改行コードをPHP上で"\n"としており、問題ないと思っていたのですが、どうもmroongaがMecabで形態素解析するときにそのまま\nという文字として読み込んでいるようでした。

Mecabは改行コードで文章の終わりを見ているようで、数十万文字の文章に改行コードが入っていないとなると文章長すぎ!処理しない!となるようです。

MySQL+mroongaでFullTextを扱わないデータなら\nで問題ないのですが、Mecabはうまく認識してくれないということでPHP_EOLを使用したところちゃんと改行と認識してくれました。

PHP_EOLは環境依存なので使っていなかったのですが、まぁmroongaインデックス用のfieldなのでよしとします。

ハマリにハマって4時間浪費。

レンタルサーバか自社サーバどちらを使うのか

社長にレンタルサーバを使わない理由を聞かれたのでまとめます。

別に嫌いだから使わない訳じゃなくて必要性に合わせて使うことがないだけなのですが。

ここでは個人的なレンタルサーバのメリット、デメリットを書いていきます。

超小規模個人IT屋の極々個人的な意見で、実際に運用するWebサービスによってほとんどケース・バイ・ケースなので悪しからず。

 

レンタルサーバのメリット

レンタルサーバは比較的低負荷なサービスに用いることが多いと思います。

・Wordpress等のブログエンジンを使ったオフィシャルブログ(月間100万PV程度)

・画像、動画等のコンテンツサーバ

・feedクローラプログラム

など、ほとんどサーバスペックを必要としないサービスであれば月額980円程度のVPSレンタルサーバでも十分実用可能です。

2chまとめサイト等最近増えていますが、ああいう用途にも良さそうです。月間1億PVとかになるとスタンドアロンじゃ無理ですが。

 

・初期コストが安い

小規模なシステムなら月額980円程度のVPSで十分です。

サーバを買う初期費用もなく、ネットワーク回線もあり、電気代も月額料金に含まれます。

 

・耐障害性が高い

レンタルサーバではサーバスペックに目が行きがちですが、ネットワーク帯域を別回線として確保できるのがかなり大きです。

自社サーバと合わせて死活監視にも使えますし、自社サーバ障害時はレンタルサーバでホットスタンバイしておけばサービス稼働率を高く保てます。

レンタルサーバプロバイダによってはデータの耐障害性も自社サーバよりよっぽど高いものも多いでしょう。

スタンドアロンでありながらVPSならハードが壊れても問題なくサービスは継続します。

 

・デメリットが減ってきている

最近ではVPSサーバの台頭により、サーバのOSまるごといじれるレンタルサーバサービスが増えています。

以前はPHPのバージョンが古かったりデータベースはMySQLのみでデータベース数が限られているということもありましたが、その心配もなくなり様々な用途に使用できます。

 

レンタルサーバのデメリット

これも運用するサービスによりことなりますが、共通して言えるのがWANだと言うことです。開発時に割りと手間をとることが多くなります。セキュリティについてもLANより強固にしなければなりません。

 

・サーバが手元に無い

サーバが手元にないとなにかと不便で、レンタルサーバ上のOSのを入れかえようと思ったらデータをすべてネットワーク越しにバックアップして、OSのISOをVPSに送ってtelnetでインストールして…と気軽にいじくるには少々時間がかかります。

開発時にはFTPかsambaを使えればソース反映はなにかと便利ですが(EclipseかNetBeansを使っているので)、ネットワーク帯域やセキュリティの問題が出てきます。しかしこの辺はgitなりクラウドサービスを使えばある程度はカバーできますね。

 

・開発時に不便

開発はローカルでやってしまえばいいと言えばそれまでですが、実環境で動かしてみないとわからないことも多いわけで、自社サーバと同等の開発環境になるかと言えばそうではないと思います。

レンタルサーバへは常にWAN越しになり、SSH、FTP等で常々つなぐことになります。IDEを使っているとFTPクライアントを入れたり、セキュリティの為ハッシュを生成したりキーを変えたりとLANよりは、遥かに手間が増えます。

一度、レンタルサーバに合わせた開発環境を構築していまえば以後は楽になると思いますが、手間です。

 

・なんといってもサーバスペック

メリットで上げた程度のサービスならCPU2コア、メモリ512MB、ディスク10GBもあれば十分ですが、少し複雑なデータベース構成にしようと思ったら一気にスペックが足りなくなります。

現在、私が運用しているシステムはデータ件数1000万件以上、MySQLバイナリで40GB以上、CPUは8コア3Ghzでメモリ24GBのシステムがあります。ほとんどの時間帯すべてでこれらのリソースを常に使用しています。

これをレンタルサーバで行おうと思ったら初期費用8万円、月額9000円程度になります。上記システムの動かしているサーバは自作で、5万もかかっていません。電気代は月3000~6000円といったところでしょうか。

どうしても高負荷になるサービスをレンタルサーバで行おうと思ったら管理費が高くなるのです。

レンタルサーバにはネットワーク帯域と耐障害性という強みを持っていますが、正しいバックアップ運用とシステムとネットワークの多重化をしていれば運用上問題ない耐障害性は作れます。

 

・結局自社サーバで事足りてしまう。

自社サーバが複数台あればバーチャルホストで低負荷なサービスは量産できますし、運用コストも安く開発もやりやすいです。

課金システムを含むサービスや個人情報を含むサービス等、絶対にデータ紛失を行なっては行けない場合はネットワーク多重化、UPSの導入等考えるとレンタルサーバを複数台借りて運用した方が安上がりになるでしょう。

 

 

以上の事で私がレンタルサーバを使う機会が少いです。(他にもメリットデメリットあった気がするけど思い出せない)

もちろん必要性と開発、運用コストに合わせて今後レンタルサーバなりAmazon EC2なりGoogle App Engineなり使うこともあるとおもいます。

現時点では自社サーバで開発、運用するのが一番楽です。


CentOS6.4+varnishでリバースプロキシ

動的IP一つで複数ドメインで複数サービスといういかにも弱小な運用することになったのでリバースプロキシを導入することにしました。

一般家庭向けのFTTH1GbpsでもプロバイダがSoftBankなら転送制限は今のところなく、案外安定してサービスを続けられています。(月間100GBは上下してると思います)

ネットワーク帯域は十分、そこそこのスペックのあるサーバ一台毎ににWeb、DB両方入れてサービス運用をしています。

落ちてもそこまで問題の無いサービスなので冗長化は行なっていません。

落としちゃいけないサービスは事務所サーバで運用せずクラウドでやります。そういえばGoogle Computer Engineが楽しみ。

 

とは言ってもいずれやることになるのは目に見えてるのでとりあえずLVSで冗長化の試験を行うことに。

少々躓いたけど無事動いたということでリバースプロキシにしようと思ったらLVSじゃドメインベースの振り分けできないことに気づく。

なにを思ったかL4スイッチだから出来るだろうと確認もせずやってました。

 

しかたないのでHTTPのリバースプロキシを改めて導入することに。

ApacheやPoundやnignxなどなどありますが、今回はリバースプロキシでキャッシュしたりヘッダいじったりしないし、

新たにサーバ新調するのも持ったいないので転がってたMini-ITXのAtomで十分動くであろうvarnishを使うことにしました。

初めてvarnish使ってみましたが、これがなかなか使い勝手がいい!

 

WAN

NVR500(L3)

varnish(L4 or L7)

Web01(hogehoge1.com)  , Web02(hogehoge2.com), othres...

といったネットワーク構成です。サービスが増えたらvarnishもLVSで複数にする予定です。

現在はWebサーバとDBサーバは物理的に同じですが、それもいずれ分離してクラスタする予定。

 

・CentOS6.4にvarnish3.0.1をインストール

 

デフォルトのリポジトリには含まれていないのでrpmを用意

適当に最新版を持ってきます。

$ rpm --nosignature -i http://repo.varnish-cache.org/redhat/varnish-3.0/el5/noarch/varnish-release-3.0-1.noarch.rpm

$ yum install varnish

デフォルトポートが6081あたりになってるのでhttpdに合わせて変更

$ vi /etc/sysconfig/varnish

#VARNISH_LISTEN_PORT=6081

VARNISH_LISTEN_PORT=80

 

・設定

 

varnishの一番好きなところです。

VCLというドメイン固有言語があり、かなり細かく設定ができます。

でも今回は必要ないので単純にドメインで振り分けする設定です。

 

$ vi /etc/varnish/default.vcl

backend default {

  .host = "127.0.0.1";

  .port = "80";

}

 

backend hogehoge1{

  .host = "192.168.1.10";

  .port = "80";

}

 

backend hogehoge2{

  .host = "192.168.1.11";

  .port = "80";

}

 

sub vcl_recv {

 

  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;

  }

 

  if (req.http.host == "hogehoge1") {

    set req.http.host = "hogehoge1";

    set req.backend = hogehoge1;

  }elseif (req.http.host == "hogehoge2") {

    set req.http.host = "hogehoge2";

    set req.backend = hogehoge2;

  } else {

    error 404 "Unknown virtual host";

  }

}

見たまんまシンプルな設定です。

VCLではこのようにC++ライクに設定がかけます。

FreeNAS8.3.1x64+ZFS(raidz)で自作NAS

WIndowsの開発機のシングルHDDにsambaで繋いで運用環境のバックアップを手動でとる。という不安で仕方ない環境で、
先月HDDが3台が立て続けに逝ったので重い腰を上げNASを導入することにしました。

NASは既成品でBuffaloのLS-WXL05Dを持っていましたが、速度が遅く細かい事ができない、容量の大きいものは結構高い。ということで自作NASにすることに。
ちなみにこの際にLS-WXL05DはHDDを換装してテレビ録画したりメディアサーバにしたりと、個人用途では十分使えます。

おおまかに導入メモ
1、機器の購入

・マザー、CPU、メモリ、システムディスク
サーバ群にMini-ITXのASUS E45M1-I DELUXEがすでにあり、中途半端に非力でデバッグ機として使ってたのでNASとして再利用。
DDR3 4GBx2、Crucial M4 64GB CT064M4SSD2(システム用)、マザーボードにBluetoothやら無線LANやらUSB3.0やらHDMIから乗ってるのでNASとしてはなかなか使い勝手がいいです。(全部使ってませんが)
raidzで組む予定だったのでCPUの弱さが少々心配でしたが、現在そこそこ速度も出てるようなのでヨシとします。電源も転用でATXの400W
ということで0円

・ケース
自作大容量NASといえば「Node 304 FD-CA-NODE-304-BL」
MiniITX準順のくせに3.5インチが6台も入ります。ケースファンが3台ついてて硬性も高いです。HDDのアクセスはしにくいですが、ホットスワップすることもないだろうということで目をつぶりました。
見た目もなかなかカッコいいです。割とでかい。一見ウーファーの様。ちなみにリセットスイッチはついてません。
TSUKUMOで9,980円

・HDD
1TBプラッタのWD30EZRX/Kにすることにしました。3TBで10,980円を4台購入。
ケース限界の6台欲しかったけどマザーにSATAが5ポートしかなく、インターフェースカード買うのも金かかるし、3TBが4台あれば数年は持つ予定。
Faithで44,000円

2、OSのインストール
MySQLのバックアップもしようかなと思ってSolarisかCentOSあたりにしようかなと思ってましたが、NAS用のFreeNASが簡単そうでWebUIまで標準で入ってるとのことで、zfs入れたりrpmしたり面倒だったのでFreeNASにしました。
AFP、NFS、CIFS、FTP、SSH、その他もろもろ入ってるのでNASとしては十分です。WANからアクセスする予定もないし、セキュリティは深く考えていません。
FreeNASのインストールはhttp://aramacin-blog.blogspot.jp/2013/01/freenas830.htmlを参考にさせて頂きました。
GUIを画像付きで解説してくれててとてもわかりやすい。

3、raidz設定
購入したHDD4台すべてつなげてraidzを組みます。GUIで楽々
raidzの組み方は多々ありますが、主にバイナリと個人情報を含まないデータベースの定期バックアップなので簡素に。
適当にユーザとパーミッション作って完了。

4、メール設定
FreeNASは標準でレポートをメール送信してくれます。
Gmailでできるのでそれもありがたい。ネットワークのDNSの問題でGmailのメールサーバの名前解決ができず、your test email could not be sent: [Errno 8] hostname nor servname provided, or not knownというエラーが出たので直接IP入れました。
GoogleのメールサーバのIPそうそう変わることがないと思いますが、毎日レポートメールが来るのでメールが来なけりゃ設定直そうという甘い考えです。

5、完成
完成しました。楽々でした。
開発機からマウントして速度を測ってみました。



もう少し速度が出せそうな気がしますが、NASとしては必要十分な速度なのでOK。
4KランダムReadがなんでこんなに速いのか不思議です。SSDキャッシュを勝手にやってくれてるのかもしれないから後々調べます。

初めて自作NAS組んでraidz使ってみましたが、特につまる所もなく、簡単にできました。
面倒なのはバックアップのcron書く方ですね。
NASは信頼性が最も重要だと思うのでできれば既成品が良かったのですが。
今後はリカバリのテストやrsyncなど始めていく予定です。