KLab若手エンジニアの これなぁに?

KLab株式会社の若手エンジニアによる技術ブログです。phpやRubyなどの汎用LLやJavaScript/actionScript等のクライアントサイドの内容、MySQL等のデータベース、その他フレームワークまで幅広く面白い情報を発信します。

2009年09月

symfony開発者Fabien Potencierとディスカッションしました!

ども、amo-kです。 先日(9/7)にsymfony開発者Fabien PotencierさんがKLabにお越し下さりました! ▼ 握手!(あんまり若手エンジニアが写ってないw)


▼ ディスカッションの様子


symfonyの使い方から思想まで、色々なことについて話す事ができました。 世界のトップレベルのエンジニアとのディスカッションに、KLab若手エンジニア達も非常に喜んでおりました。 来年のSymfony Conference Japanで何かお役に立てる様にがんばりま〜す。 また、Fabien Potencierさんを連れて来て頂いた秋元さん、月宮さん、大野さんありがとうございました!! 今後ともよろしくお願い致します〜

若手ブログ(WordPress)のインフラ構成

はじめまして kihira-h です。 普段は、サーバ管理やネットワーク構築などインフラ関係の仕事をしています。 今回は、この「KLab若手エンジニアの これなぁに?」、通称 “若手ブログ” のインフラ構成をご紹介します。 弊社には DSAS と呼ばれる分散冗長構成のインフラ技術がありますが、この「若手ブログ」も DSAS 程ではありませんが分散環境の上でサービスされています。

インフラ構成

まず、「若手ブログ」インフラの構成要素には
  • リアルサーバ
  • ロードバランサ
  • マスタサーバ
の3つがあります。 「リアルサーバ」が、皆さんからのアクセスを受け付けている Web サーバです。 現在のところ2台のサーバが稼働しています。 次の「ロードバランサ」が、下図のように配下のリアルサーバに対してアクセスを振り分けています。

このロードバランサには、リアルサーバの死活確認を行う仕組みがあり、万一リアルサーバの一部がダウンしても自動的にそのサーバは分散対象から外れます。

最後に、「マスタサーバ」を紹介します。このサーバがある意味この分散環境のポイントでもあります。 先ほど、リアルサーバが Web サーバだと説明しましたが、このマスタサーバも Web サーバです。リアルサーバ2台に加えて、このマスタサーバでも Apache が稼働していて WordPress が動いています。

記事の書き方

それでは、この若手ブログでどのように記事を投稿していくのかをご紹介します。 私たちは、マスタサーバ上で動いている WordPress の管理ページにアクセスして、記事を書き込みます。WordPress のデータは MySQL 上に乗っているので、記事本体はリアルサーバ上でも即座に反映されます。 では画像などの素材のアップロードは、どのようになっているのでしょうか? 実は、マスタサーバ上にアップロードした素材を、スクリプト等を駆使してリアルサーバに同期しているのです。

上図の通り、素材のアップロードは、大きく分けて「マスタサーバへのアップロード」と「各リアルサーバへの同期」の2つの手順で行われます。それぞれどのように行われているか詳しくご説明します。

  1. 関連ファイルのリポジトリ管理 若手ブログにアップロードされている画像などのコンテンツや、WordPress のテーマ、さらには WordPress 本体も含めて関連するファイルは全て git リポジトリ上で管理されています。アップロードしたいファイルを追加してコミット、その後社内のサーバ上のリポジトリにプッシュすることでメンバー間のファイル共有を行っています。
  2. マスタサーバへのアップロード 素材のサーバへのアップロードには rsync を使っていますが、毎回コマンドラインを組み立てるのは面倒なので Makefile を作って使用しています。
    $ make install-young
    のように実行すると、マスタサーバ上のコンテンツがローカル上のファイルに同期するように rsync が実行されます。
  3. アップロード内容のチェック 3.で行ったアップロードはマスタサーバのみに対して行われるため、外には公開されないマスタサーバ上で内容のチェックができます。例えば、テーマの変更や一部の編集などを行った場合でも、公開系に影響を与えずに確認ができるということです。
  4. 各リアルサーバへの同期 マスタサーバからリアルサーバへの素材の展開も、マスタサーバへのアップロード時と同じく Makefile にターゲットが仕込んであります。
    $ make mirror-young
    のように実行すると、マスタサーバ上で各リアルサーバへの rsync が実行されてファイルが同期します。

インフラ構成のポイント

この「若手ブログ」のインフラのポイントは、分散リポジトリ( git )と Makefile による省力化です。 ソースコードだけでなく素材などもまとめてリポジトリ上で管理してしまうことで、アップロード済みデータの管理を簡単にできるほか、コミットのログから誰がどんな変更を行ったかが追跡できるほか、トラブルが発生しても簡単に1つ前のリビジョンに戻すことができます。 また、アップロードに必要なコマンドも引数を含め全て Makefile に書いてしまうことで、扱いやすくミスの少ない作業ができます。 皆さんも身近なファイル管理などを、リポジトリ管理 &Makefile で自動化してみてはどうでしょうか?

maven2 cargo pluginで自動結合テスト

はじめまして。sasaki-kです。 わたしは業務で継続ビルド環境として hudson + maven2を気に入って使っています。携帯サイトは実機チェックが大変なため、継続ビルド環境上で結合テスト(Tomcat起動してHttpUnitで内容応答確認、DBの値チェック)ができたらなと思っていました。 一方、こういった用途には Cargo Maven2 plugin が有名です。良く紹介される事例としては Tomcatがリモート環境で起動していて、maven2でビルドしたwarをdeployなのですが・・・テスト用のTomcatを継続ビルドマシンにインストールしたり、tomcatのmanager appを有効にしたり、異なるTomcatのバージョンでのテストも面倒だなあと思っていました。 ところが調べてみたところ、maven cargo pluginには ApacheからTomcatを自動ダウンロードしてきて専用にしてくれる方法がありました。さっそく試してみましたのでご紹介します。pom.xmlの中でcargo-maven2-pluginの<configuration>タグの記述がポイントです。

<!-- pom.xmlから抜粋 -->
 <build>
   <plugins>
     <plugin>
       <groupId>org.codehaus.cargo</groupId>
       <artifactId>cargo-maven2-plugin</artifactId>
       <executions>
         <execution>
         <id>start-container</id>
         <phase>pre-integration-test</phase>
         <goals>
           <goal>start</goal>
           <goal>deploy</goal> <!-- startだけではだめだった -->
         </goals>
        </execution>
       <execution>
         <id>stop-container</id>
         <phase>post-integration-test</phase>
         <goals>
           <goal>stop</goal>
         </goals>
       </execution>
       </executions>
       <configuration>
         <configuration>
           <type>standalone</type> <!-- ここがポイント -->
           <properties>
             <cargo.logging>high</cargo.logging> <!-- あまり気にしてない -->
           </properties>
         </configuration>
         <container>
           <containerId>tomcat5x</containerId>
           <zipUrlInstaller>
             <url>http://archive.apache.org/dist/tomcat/tomcat-5/archive/v5.5.15/bin/jakarta-tomcat-5.5.15.zip</url> <!-- テストで使うTomcat -->
             <installDir>${java.io.tmpdir}/cargoinstalls</installDir>
           </zipUrlInstaller>
           <dependencies>
             <dependency>
               <groupId>mysql</groupId>
               <artifactId>mysql-connector-java</artifactId> <!-- MySQL使っているので -->
             </dependency>
           </dependencies>
         </container>
         <deployer>
           <deployables>
             <deployable>
               <artifactId>your-artifactId</artifactId>
               <groupId>your-groupId</groupId>
               <pingURL><![CDATA[http://localhost:8080/s/index.jsp]]></pingURL> <!--テスト対象が起動したとみなせるURL-->
               <pingTimeout>360000</pingTimeout> <!--起動に時間がかかるので長めに設定-->
               <type>war</type>
               <properties>
                 <context>/s</context>
               </properties>
             </deployable>
           </deployables>
         </deployer>
         <wait>false</wait>
       </configuration>
     </plugin>

     <plugin>
       <groupId>org.apache.maven.plugins</groupId>
       <artifactId>maven-surefire-plugin</artifactId>
       <configuration>
         <excludes>
           <exclude>**/integration/**/*Test.java</exclude> <!-- 単体テストでは呼ばない -->
         </excludes>
       </configuration>
       <executions>
         <execution>
           <id>surefire-it</id>
           <phase>integration-test</phase>
           <goals>
             <goal>test</goal>
           </goals>
           <configuration>
             <skip>false</skip>
             <excludes>
               <exclude>none</exclude>
             </excludes>
             <includes>
               <include>**/integration/**/*Test.java</include> <!-- HttpUnitを使ったテストを書く -->
             </includes>
           </configuration>
         </execution>
       </executions>
     </plugin>
   </plugins>
 </build>
また、webアプリから JNDIなデータソースへアクセスしているので webapp/META-INF/context.xmlの中に以下を記述しています。
<?xml version="1.0" encoding="UTF-8"?>
<Context reloadable="true" path="/s">
  <Resource auth="Container" type="javax.sql.DataSource"
      maxActive="20" maxIdle="10" maxWait="-1"
      name="jdbc/db"
      driverClassName="com.mysql.jdbc.Driver"
      url="jdbc:mysql://localhost:3306/dbname"
      username="your-user-name" password="your-password" />
</Context>
ここまでやっとくと後は、コマンドラインからの実行は以下ですみます。
$ mvn integration-test
こうすると内部では以下のような処理が行われるようです。
  • http://archive.apache.org/dist/からTomcatを取得し、${java.io.tmpdir}/cargoinstalls以下にinstall
  • テスト対象warをdeploy
  • <pingURL>で指定したURLを200になるまで叩きまくり(<pingTimeout>を上限として)
  • mavenが**/integration/**/*Test.java 以下の結合テスト実行
これを使えばmavenのProfileで${java.io.tmpdir}/cargoinstalls あたりを変更すれば異なるTomcatのバージョンでテストできるし、実行する環境に左右されないので継続ビルド環境のお引越しとか障害あったときの代替環境の準備とか楽になりそうだなーと思いました。 参考にしたサイト
  • Cargo - Maven2 Plugin Reference Guide
    • http://cargo.codehaus.org/Maven2+Plugin+Reference+Guide
 KLab若手エンジニアブログのフッター