2012年11月18日日曜日

Jenkins + Jboss でJ2EEホットデプロイなCI環境構築

CIが流行っていますね。
僕も簡単にですが環境を構築してみました。
その時のメモを載せておきます。

内容は、
  • Jenkinsをインストールする
  • J2EEアプリケーションを載せるJbossのインストールと環境設定をする
です。
その後の作業として挙がるJenkinsの具体的な設定については、
プロジェクトの内容やビルドツールの種類等にもよりますのでここでは割愛させていただきます。


そもそものJenkins+Jbossの目的として、ここでは以下2点を掲げさせて頂きます:
  • プロジェクトの継続的な監視・改善のため
  • 開発者以外のメンバーが利用できるJ2EE提供するため
環境構築
では早速構築していきましょう。
テスト用のホストマシンに仮想マシンをのせ、
そこにJenkinsを構築しているという環境とします。

Jenkinsによって自動ビルドし、
生成されたwarファイルをJBossにホットデプロイするというのが一連の流れです。
TEST環境インテグレーションツールの運用をVMで行います。


JenkinsやJbossによって新しく設定が発生するが、それらはまとめて次項で述べます。
OS : Ubuntu Server 12.04.1 LTS 64bit (Virtual Machine)
ソフトウェア :


  • DK 7 (Oracle製 JDK)
  • Nginx (HTTPサーバ)
  • Jenkins 1.4 (CIツール)
  • JBoss 6 (APサーバ)



OSインストール

OSは Ubuntu Server 12.04.1 LTS 64bit でVMと同じです。

VMware Player インストール

latestで問題ないと思います。

Ubuntu Server 12.04.1 LTS 64bit の仮想マシン設定

ディスク:20GB
CPU:2コア
RAM:2GB
ネットワーク:ブリッジ接続
以上の構成でインストール。ここから先の設定はすべて仮想マシン上で行うものとします。

ソフトウェアのアップデート

sudo aptitude update
sudo aptitude safe-upgrade

ネットワークの設定・再起動

固定IP or DHCPによる設定を行います。
今回は固定IP+ネームサーバ登録だったため以下のようにしました。
sudo vim /etc/network/interfaces
-------------
auto eth0
iface eth0 inet static
address *****
netmask *****
gateway *****
dns-nameservers *****
-------------

CI(継続的インテグレーションツール)
以下では、CIを行うためのソフトウェアインストール・それに付随する設定手順を示します。


JDK7 のインストール

javaは/usr/lib/jvm/にインストールし、latestのシンボリックリンクを作成。
y-wada@localhost:/usr/lib/jvm$ ls -la
-----------------
drwxr-xr-x  8 root root  4096 10月 12 16:06 java-7-oracle
lrwxrwxrwx  1 root root    14 10月 12 16:18 latest -> java-7-oracle/
-----------------

maven2のインストール

JenkinsはAntやMavenといったビルドツールと組み合わせることで
より大きなチカラを発揮していくれます。
mavenの場合は/usr/share/にインストールし、maven2へリネームします。

Jenkins(+Nginx)のインストール

本家にUbunuへのインストール手順があったので基本的にはそれに従いました。
https://wiki.jenkins-ci.org/display/JENKINS/Installing+Jenkins+on+Ubuntu

HTTPサーバはNginxを選択。
プロキシ設定は以下のようにしています。
y-wada$ vim /etc/nginx/sites-available/jenkins
------------------------
upstream app_server {
    server 127.0.0.1:8081 fail_timeout=0;
}

server {
    listen 80;
    listen [::]:80 default ipv6only=on;
    server_name server-name;

    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;

        if (!-f $request_filename) {
            proxy_pass http://app_server;
            break;
        }
    }
}
------------------------

JBoss6のインストール

http://www.caseyfulton.com/installing-jboss-as-6-0-final-on-ubuntu-server-11-04-for-mere-mortals/
ここを参考にインストールを行いました。

JBoss6 HTTPポートの書き換え

HTTPサーバのポートを8080 -> 8085とします。
y-wada~$ vim /usr/local/jboss/server/default/conf/bindingservice.beans/META-INF/bindings-jboss-beans.xml
--------------------------
            <bean class="org.jboss.services.binding.ServiceBindingMetadata">
               <property name="serviceName">jboss.web:service=WebServer</property>
               <property name="bindingName">HttpConnector</property>
               <property name="port">8085</property>
               <property name="description">JBoss Web HTTP connector socket; also drives the values for the HTTPS and AJP sockets</property>
            </bean>
---------------------------

JBOSSにデプロイするアプリケーションの設定

デプロイしたアプリケーションを実行する際の設定をここで行います。
変更点は、

  • PermSizeを増やす(OutOfMemory対策)
  • Javaのオプション設定(アプリケーションをテストモードで実行させるため)

y-wada:~$ vim /usr/local/jboss/bin/run.conf
-------------------
if [ "x$JAVA_OPTS" = "x" ]; then
   JAVA_OPTS="-Xms128m -Xmx1024m -XX:MaxPermSize=1024m -Dorg.jboss.resolver.warning=true -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000" (書き換え)
fi
JAVA_OPTS="${JAVA_OPTS} -Djboss.bind.address=0.0.0.0 -Denvironment.level=test" (ファイルの末尾に追加)
--------------------

ホットデプロイ用ディレクトリのパーミッション変更

Jenkinsは /usr/local/jboss/server/default/deploy 
にwarファイルを書き込むことによってデプロイします。
ただし元がdrwxr-xr-xのため、
+w して jenkinsユーザがwarを置けるようにしておきます。

JBoss設定用アプリケーションのリネーム

${JBOSS_HOME}/server/default/deploy/ROOT.war
がいるとデプロイに失敗するので、適当にROOT.war.bakなどとリネームしておく 。


以上です。最低限の設定で、
ここからプロジェクトごとにさらにJenkinsの設定が必要となりますが、
CIのための土台はできました。


2012年8月21日火曜日

ファイルのダウンロードでファイル名が文字化け

なんなんすかこれ。
腹が立ったので文字コードとブラウザのやってることから理解しようと思います。
とりあえず対処療法に使ったコードは以下(Java)。


お膳立てとしてUserAgentを取得する必要があります。
たいていのWebアプリケーションフレームワークならgetUserAgent()みたいなメソッドがあるはずですのでそれを使えばよろしいかと。

 ------------
処理は大きく3ブラウザで分岐しています。
ちなみにChromeはUserAgentでSafariの文字列を含むのでSafariの処理に分岐します。 
ファイルダウンロード部分のファイル名に関してはこのメソッドに突っ込んどけば大丈夫でしょう。

2012年6月26日火曜日

ログレベル

難しいです。
「どのレベルで、どのようなログを出力するのか」が。

たいていの場合は組織やチームで決められているかもしれませんが、
個人で利用する場合やログレベルごとの出力ないようを任された場合なかなか行動に窮するものがあります。

私がそこいらのウェブ上で情報を集め出した個人的な答えが以下です。
なおWebアプリケーションの実装においてログを利用することを想定しています。

Untitled document

ログレベル
ログ閲覧者
利用シーン
出力する内容
ERROR
運用者・開発者
ユーザーが処理を続行できない場合
  • データベースを利用できない
  • データID
  • 例外をキャッチして処理した場合、そのスタックトレース
  • 例外をキャッチしてそのままスローした場合、キャッチした場所
  • 原因の候補
WARN
運用者・開発者
ユーザーは処理を続行できるが、アプリケーションが異常なデータを処理した場合
  • データID
  • 問題の内容
  • 発生箇所
  • 原因の候補
INFO
運用者・開発者
処理は正常だが、ユーザーが特殊な作業を行った場合
  • データID
  • 処理の内容
  • 処理の開始と終了の場所
  • 処理の開始前のデータの状態と、処理後のデータの状態
DEBUG
開発者
上述以外で、開発者が必要だと判断したもの
任意

2012年1月19日木曜日

PyramidフレームワークでPython+WSGIのWebアプリ(3)MVCに則ったサンプル(BankAccount)

pyramidフレームワークを用いて残高表示・入金・出金の機能を備えたBankAccountなるwebシステムを作ります.

ロジックはpyramid+makoテンプレート,DBはsqlite3,そして実行はWSGIの仕組みを用います.

今回の目的はMVCアーキテクチャに則って実装するための部品(プログラムファイル)としてどのようなものがあるかをしること,そしてそれぞれの部品にどのようなロジックを書けばいいかの傾向をつかむことです.

方針として,まずどのファイルにどのような記述をすればよいかをざっと示しますので,ご自分の環境で動作を確認してください.ひとまず動作させるところまでできればどこに何があればどうなるのか,俯瞰的に眺められるはずです.


1. 環境設定

まずはじめにpythonの環境を整えます.

前回はpyramidなどの外部パッケージをシステム側に直接インストールしましたが,今回はvirtualenvとよばれる小さなpython処理系をつくり,そこにpyramidをインストールします.このようなことをする理由としては,

  • 仮想環境上でアプリケーションが完結するのでシステムへの影響が少ない
  • 外部パッケージ部分で問題が発生し収集がつかなくなったとき,仮想環境ごと削除すればリセットできる
といったように問題を局所化できます.

さて,その方法ですが,仮想環境を作りたいディレクトリにて,

$python2.6 --version
Python 2.6.5
$easy_install-2.6 virtualenv
$virtualenv --no-site-packages pyramidtut
のようにします.するとpyramidtutディレクトリには,

$ls
bin include lib lib64
のように見えるはずです.

bin/ にはpythonの実行コマンドが格納されており,仮想環境で実行するアプリケーションに対しては以降すべてこのbinディレクトリから実行コマンドを選択していくことになります.

この際,外部パッケージによってはシステム側で使う場合と実行コマンドの名前が変更されているものもあります(paster create ... -> pcreate ... など)ので,注意してください.

次に必要なパッケージを仮想環境上にインストールします.

$pwd
/home/hoge/pyramidtut

$bin/easy_install-2.6 pyramid sqlalchemy pyramid_tm sqlahelper
必要な外部パッケージは以上となります.

 さらに,pyramidプロジェクトを作成します.
$bin/pcreate -t starter bankaccount
tオプションは「テンプレートを作成せよ」という意味です.starterはpyramidが所有するテンプレートの一つで,最小限の構成をあらかじめ持つテンプレートが作成されます.そしてそのプロジェクト名をbankaccountとしているわけです.

これで,準備が完了しました.


2. 実装

まずはプロジェクトの構成を確認します.

だいたい右図のようになっているはずです.

これから変更を施していくファイルは,

  • bankaccount/templates/index.mak
  • bankaccount/___init___.py
  • bankaccount/models.py
  • bankaccount/resources.py
  • bankaccount/views.py
  • development.ini
です.ひとつずつその実装例を載せていきます.


  • developent.ini
静的な情報を記述するファイルです.WSGIではこのファイルが引数となります.
[app:main]のブロックを以下のように変更してください.


  • ___init___.py
アプリケーションの初期化を行うファイルです.以下のように記述してください.


  • views.py
ユーザのURLアクセスに反応して起動するメソッドの内容を定義します.



  • resources.py
データベースアクセスのためのクエリなど,複数の機会から使い回すことのできる処理やインスタンスをまとめ,必要に応じて取得できるようにしておくためのクラスがあります.


  • mdoels.py
ロジックです.主にviewsから呼び出されます.



  • index.mak
makoテンプレートと呼ばれるものです.一般的なHTML記述に加え,pythonのコードを記述することができます.この仕組みを用いることにより,DBからデータをひっぱってきて表示したり,フォームのアクションスクリプトに先述のメソッドなどを指定することができます.




3. 実行実行アンドアクセス

以上の変更が完了したら,WSGIとして実行します.
$pwd
/home/hoge/pyramidtut/bankaccount
$../bin/pserve development.ini
[DEBUG]:BankAccount_15
Starting server in PID 3320.
serving on 0.0.0.0:6543 view at http://127.0.0.1:6543

エラーなど出ず,この状態になったならば出力にあるURLにアクセスしてみます.

以下のような画面が出れば成功です.
Balanceが現在DBに保持されている残高,Depositで入金処理,Withdrawで引き出し処理です.実際にフォームへ値を入れてBalanceの変化を観察してみましょう.意図通りの結果になりましたか?



今回の内容は以上です.全体構成とサンプルを動かすための開発の流れに焦点を起きました.次回はそれぞれのPythonファイルの詳細な記述を見ていくつもりで,この連番では最後の記事になる予定です.これはまだ僕も勉強中です.

もし実行された方は,成否をお知らせいただくとより内容のクオリティアップを期待できますので,気が向いたらコメント等でご一報ください.

うまくいかない場合はOSやエラー内容など明示していただけると助かります.