[perl] TwitPepper・Webアプリの中の人(その1)
こんにちは、松本です。寒い中 いかがお過ごしでしょうか。
1月冒頭に 年始の抱負 を書いた後、忙しさにかまけ、jQuery と PHP の新バージョンに心踊らせるのに精一杯で、Corei7の低TDP版 "Corei7-860S" の登場にも気付かず今日気づきました。
ついに Core2 Quad シリーズも世代交代か・・・と考え始めております今日この頃です。
今回弊社のサービス"TwitPepper(ツイットペッパー)"の技術面から見た中身についてご紹介したいと思います。
TwitPepper(ツイットペッパー)とは
TwitPepperとは、Twitterのデザインを外部から簡単に変更できるサービスを提供しているサイトです。
![]() |
Blogサービスのスキン変更のように、自分もTwitterページをお手軽に色々なデザインに変更することができます。詳しくは TwitPepper内の解説ページ をご覧下さい。 |
遅ればせながらなのですが、昨年12.21にリリースしまして本年冒頭にプレスリリース、1月末に月間カレンダーシリーズをリリースしまして、好評頂いておりますサービスです。(3月分のカレンダーももうすぐアップされると思います。)
TwitPepperのWebアプリケーション概要
TwittPepperは、いわゆるLAMP構成で構成されています。LAMP構成の詳細は以下になっています。
- L・・・Linux (CentOS 4 i386)
- A・・・Apache 2.2 + Apache 1.3
- M・・・MySQL 5.0
- P・・・Perl(mod_perl)
それぞれの概要を記述していきます。
L・・・Linux (CentOS 4 i386)
TwittPepperのサーバは、さくらインターネットの専用サーバ を使っています。OSはCentOS4(i386/32bit)を利用しています。現在はまだそれほどのトラフィックが発生していないので、いわゆる10Mスタンダード がデフォルトで付いていますのでそちらを利用しています。
※サーバを借りた時期がやや以前なので、旧ネットワークプランにリンクしています。
さくらさんでは、OSは他にUbuntu、FreeBSDなども選択可能 ですが、弊社では新規のサーバは全てCentOSで統一しています。
また、バージョンは基本5、で i386(32bit)を選択しています。
(今回借りているサーバはやや以前に借りたサーバなので、バージョン4ですが、現在はデフォルトでバージョン5を選択しています。)
搭載するメモリ量について
x86_64(64bit)を選択しない理由は、64bit化するとWebアプリケーションのプロセスサイズが肥大化し、メモリ増強が必要になります。なのですが、さくらさんではメモリが月額料金にのっているため、月々のランニングコストに乗ってしまいます。
ランニングコストの内訳は以下になります。
| 合計搭載メモリ量 | 専用サーバのランニングコスト |
| 2G | 専用サーバ標準料金のまま |
| 4G(2G+2G) | +2,100円/月 |
弊社ではできるだけランニングコストを抑えたいので、メモリサイズを最小で運用できるi386(32bit)で運用し、まずはデフォルトのメモリ2Gで運用。その後メモリが必要であれば+2G(月額2,100円追加)で最大4G(2G+2G)に拡張し、32bitOSの上限値までメモリを利用できる形で1つのWebアプリケーションを完結させています。
ノウハウ集約のためにOSを統一
もちろん、案件によってはメモリ8Gを必要とするサーバの構築もありますので、そういった場合は x86_84(64bit)のOSを積み、そもそもメモリ4Gの壁が存在しない形にしています。
以前はFreeBSD、RedHatLinux、FedoraCoreが混在していたのですが、CentOS以降は書籍・ネット上の資料がCentOSが一番多いと判断しまして、ノウハウの集約をする為にも、OSは統一しています。
自分は以前からFreeBSDをずっと使ってきていて、慣れている部分も多かったのですが・・・ yumの利便性と、案件によってはJavaが動作する環境が必要だったため、Linuxに移行しました。
関連リンク
- さくらインターネット・専用サーバTOP
- さくらインターネット・専用サーバ サービス仕様
A・・・Apache 2.2 + Apache 1.3
WebサーバはApacheを利用しています。こちら、表記が2つあり Apache 2.2 と Apache 1.3 の2つが存在しています。
これは、"リバースプロキシ(Reverse Proxy)" という技術を使ってWebアプリケーションを運用しているため、1つのサーバに2つのWebサーバが混在しているという形になっています。
リバースプロキシ(Reverse Proxy)とは
"リバースプロキシ(Reverse Proxy)" という技術は色々な場面で使われています。
弊社では主に "Webサーバを多段構成にする事で、負荷軽減を狙うための技術" として用いています。
とても簡単な図解なのですが、以下の様に構成しています。
Proxy側(フロント)・・・Apache2.2
Proxy側(フロントエンド)は yum 経由でインストールできる、 Apache2.2 を利用しています。 yum が使えない場合はソースコードからApache2.2をインストールします。
- yum から Apache2.2をインストール
sudo yum install httpd
- ソースコードから Apache2.2をインストール
./configure --enable-mods-shared=all --enable-so --enable-proxy --enable-proxy-connect --enable-proxy-http --enable-proxy-balancer --enable-ssl --enable-dav --enable-cache --enable-disk-cache --enable-mem-cache sudo make install
Apache2.2 を利用している理由は、まず Apache2.x 以上のApacheは SSLの扱いが簡単という点と、Apache2.2 以上ではmod_mem_cache / mod_disk_cache と、 mod_proxy_balancer が使える点が大変に大きいです。
この2つが最初から使えることで、後々スケールアウトの必要が出てきた場合も柔軟に対応できます。
※<参考>Apache 2.0 のインストール
何らかの事情でApache 2.2 ではなく、Apache 2.0 をインストールしなければならない場合は以下のように configure のセッティングを行っています。
prefix の指定は、今後Apache2.2がインストールされたとしてもインストールディレクトリ先が重複しないための措置です。
- Apache 2.0.x 本体のインストール
./configure --prefix=/usr/local/apache20 --enable-mods-shared=all --enable-so --enable-proxy --enable-ssl --enable-dav
App(アプリケーション)側・・・Apache1.3
アプリケーション側は Apache1.3を利用しています。
TwitPepperでは mod_perl を利用しています。Apache1.3 のmod_perlを利用するために
必要なミドルウエア、モジュールをソースからインストールします。
- Apache 1.3 本体のインストール
./configure --enable-shared=max --enable-module=all --disable-module=auth_dbm sudo make install
続いて mod_perl をインストールします。 mod_perl 自体のダウンロードは こちら から行うことができます。
今回はApache1.3用のmod_perlですので、 "For use with Apache 1.3.x " の "Download" のリンク先をダウンロードします。
- Apache 1.3 に mod_perlをインストール
wget http://perl.apache.org/dist/mod_perl-1.0-current.tar.gz tar xvzf mod_perl-1.0-current.tar.gz cd mod_perl-1.31 perl Makefile.PL USE_APXS=1 WITH_APXS=/usr/local/apache/bin/apxs EVERYTHING=1 make install clean
APXSの指定先はApache 1.3をインストールしたディレクトリを指定します。
今回はデフォルトのprefixですので "/usr/local/apche/" 以下の "bin/apxs" になります。
Proxy 側(フロント)側の設定
Proxy(フロント)から、バックエンドのアプリケーションサーバにリクエストを飛ばすために、Proxy(フロント)のhttpd.confに以下のように記述しています。
/usr/local/apache2/conf.httpd.conf に記述
ProxyRequests Off
ProxyPreserveHost On
RewriteRule ^/(.*)/([a-z_]+)-([0-9]+).html$ http://localhost:xxxx(ポート番号)/project_path/$1/$2?id=$3&%{QUERY_STRING} [P,L]
RewriteRule ^/(.*).html http://localhost:xxxx(ポート番号/project_path/$1?%{QUERY_STRING} [P,L]
RewriteRule ^/(.*) http://localhost:xxxx(ポート番号/project_path/$1 [P,L]
- 1行目・・・フォワードプロキシサーバとしての動作を無効化しています ProxyRequestsについての詳細はこちら
- 2行目・・・HTTPヘッダのHost:行をProxy側と同じものをApp側にも飛ばすための設定です。ProxyPreserveHostについての詳細はこちら
これを行わないと、Host部での解釈ができないためApp側でのVirtualHostが有効に働きません。 - 3行目~5行目・・・Proxy条件・設定です。この部分で記述した書式に従い、Proxy先にリクエストを飛ばします。
各行の最後に "[P.L]" と終わっていますが、これはmod_rewriteの書式で"Proxyして(P)、条件定義はこの行で終了(L)" という意味になります。
App(アプリケーション)側の設定
App側は基本的には、リクエストがReverseProxyかどうかを判別する必要はありません。なのですが、REMOTE_ADDR(リモートアドレス・接続元)が全てProxy元(今回は同一サーバなので、127.0.0.1=ローカルホスト)になってしまい、アクセスログにも全てProxy元のIPアドレスが記述されます。
アプリ的、ログ解析的にも特に気にしない場合はいいのですが、やはり、アクセス状況を知りたいという場合が来るケースが多いと思いますので
Proxy元が受けたREMOTE_ADDRと同じ値(ユーザーのIPアドレス)をProxy先にもとどくよう、設定します。
設定には mod_extract_forarded モジュールを使います。
(配布されている方のURLをリンクしようと思ったのですが、現在サーバが存在していないようです。もう1.3用のモジュールの配布は終了されてしまったのでしょうか?)
mod_extract_forarded を Apache1.3に適用するには以下のようにしています。
- mod_extract_forarded をインストール
※mod_extract_forwarded.c が存在するディレクトリに移動して、/usr/local/apache/bin/apxs -i -a -n 'extract_forwarded' mod_extract_forwarded.so
- /usr/local/apche/conf/httpd.conf の設定
以下を追加LoadModule extract_forwarded_module libexec/mod_extract_forwarded.so AddModule mod_extract_forwarded.c <IfModule mod_extract_forwarded.c> RemoveAcceptForwarder all AddAcceptForwarder all </IfModule>
※<参考> Apache2 の mod_extract_forwarded
Apache 2.x 用の mod_extract_forwarded については、以下からダウンロードできるようです。
(Apche2.0.x 用と書いてありますが、Apache 2.2 でも一応インストールできました。)
関連リンク
- Apache 公式
- mod_perl 公式
M・・・MySQL 5.0
MySQLは全て、yum経由の 5.0.x を利用しています。 現在主流のMySQL5.1 も利用したいのですが、 yum で簡単にインストールできるという部分が、マニュアル化・アプリ全体の品質の統一に大変有効だと思いまして、現在は yum でのインストールのみを利用しています。
yumでのインストールは簡単です。perl用のDBDドライバも同時にインストールします。
yum install mysql mysql-server perl-DBD-mysql sudo service mysqld start
起動後、すぐにRootのパスワードを設定します。
mysqladmin -u root password 'xxxxxxxxxxx'
MySQLのUTF8対応
MySQLをUTF8対応するために /etc/my.conf で以下のように記述しています。
- [client] に以下を追記
default-character-set = utf8
- [mysqld] に以下を追記
default-character-set = utf8 character-set-server=utf8
mysql に接続して、以下のように表示されれば、UTF8での扱いはほぼ問題ないのでは無いかと思います。
mysql> SHOW VARIABLES LIKE 'char%'; +--------------------------+----------------------------+ | Variable_name | Value | +--------------------------+----------------------------+ | character_set_client | utf8 | | character_set_connection | utf8 | | character_set_database | utf8 | | character_set_filesystem | binary | | character_set_results | utf8 | | character_set_server | utf8 | | character_set_system | utf8 | | character_sets_dir | /usr/share/mysql/charsets/ | +--------------------------+----------------------------+
mysql は chkconfig にも登録して置き、 boot時に起動するように設定しています。
sudo config add mysqld sudo chkconfig mysqld on
P・・・Perl(mod_perl)
App側の動的処理は 全て mod_perl で書いています。弊社では案件によっては PHPを利用するケースもありますが、ほとんどの場合は mod_perl でソリューションしています。
特に自社内システムは100% perl/mod_perl で動いています。
mod_perl 自体のインストールは先ほど書いたとおりになります。
mod_perl の上に乗せて動かすアプリケーションですが、コーディングルールの統一化を図るため、MVC(フレームワーク)を利用しています。
弊社では mod_perl用のフレームワークは Sledge を利用しています。
通常のSledge は、基本 EUC-JP を前提としているのですが、弊社ではデフォルトがUTF8ですので、UTF8で動かすためにカスタムモジュールを追加しています。
このSledge を mod_perl 上で扱い、その上に DB との通信するためのORマッパー(今回は Class::DBI )、そしてテンプレートとして template-toolkit を利用しています。
参考リンク
- Sledge (sourceforge)
- SledgeのApache2(mod_perl2)対応+UTF8
- Class::DBI
- template-toolkit
次回に続きます。
少々記事が大きくなってしまいまして・・・ mod_perl + Sledge + Class::DBI + TT(template-toolkit) については
"TwitPepper・Webアプリの中の人(その2)" に続きます。
memcached などもカリカリ使っていますので、こちらに付いても書きたいと思っています。










