そごうソフトウェア研究所

SOA、開発プロセス、ITアーキテクチャなどについて書いています。Twitterやってます@rsogo

Mac OSXでDocker(インストール編)

公式サイト

Mac OS X - Docker Documentation

インストール

ダウンロードしたBoot2Docker-1.4.1.pkgを開くと、2ステップでboot2dockerツールのインストールは完了します。

f:id:begirama:20141222082724p:plain

f:id:begirama:20141222082730p:plain

ここまで5分。後は環境設定などをやっていきます。

初期化

boot2docker initで初期化を行います。公開鍵方式の鍵ペアを作成されました。

rsogo$ boot2docker init
Latest release for boot2docker/boot2docker is v1.4.1
Downloading boot2docker ISO image...
Success: downloaded     https://github.com/boot2docker/boot2docker/releases/download/v1.4.1/boot2docker.iso
to /Users/rsogo/.boot2docker/boot2docker.iso
Generating public/private rsa key pair.
Your identification has been saved in /Users/rsogo/.ssh/id_boot2docker.
Your public key has been saved in /Users/rsogo/.ssh/id_boot2docker.pub.

起動

Docker daemonを起動します。

rsogo$ boot2docker start
Waiting for VM and Docker daemon to start...
........................ooooooooooooooooooo
Started.
Writing /Users/rsogo/.boot2docker/certs/boot2docker-vm/ca.pem
Writing /Users/rsogo/.boot2docker/certs/boot2docker-vm/cert.pem
Writing /Users/rsogo/.boot2docker/certs/boot2docker-vm/key.pem

To connect the Docker client to the Docker daemon, please set:
    export DOCKER_HOST=tcp://192.168.59.103:2376
    export DOCKER_CERT_PATH=/Users/rsogo/.boot2docker/certs/boot2docker-vm
    export DOCKER_TLS_VERIFY=1

環境変数等の設定

$(boot2docker shellinit)を($や()もそのまま)実行して、環境変数などをセットします。環境変数を直接.bashrcなどに書くのではなく、このコマンドが実行されるように設定するのが推奨されています。

rsogo$ $(boot2docker shellinit)
Writing /Users/rsogo/.boot2docker/certs/boot2docker-vm/ca.pem
Writing /Users/rsogo/.boot2docker/certs/boot2docker-vm/cert.pem
Writing /Users/rsogo/.boot2docker/certs/boot2docker-vm/key.pem

サンプルの実行

ここまでで準備はできたみたいなので、hello-worldというサンプルがあるのでそれを実行してみます。

rsogo$ docker run hello-world
Unable to find image 'hello-world:latest' locally
hello-world:latest: The image you are pulling has been verified
511136ea3c5a: Pull complete 
7fa0dcdc88de: Pull complete 
ef872312fe1b: Pull complete 
Status: Downloaded newer image for hello-world:latest
Hello from Docker.
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (Assuming it was not already locally available.)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

For more examples and ideas, visit:
 http://docs.docker.com/userguide/

出力された内容を見ると、ローカルにないから、hello-worldのイメージをDocker Hubからダウンロードしています。 その後、"Hello from Docker"という文字列が表示されました。

このエラーが出るときは環境変数の初期化ができていない

rsogo$ docker run hello-world
FATA[0000] Post http:///var/run/docker.sock/v1.16/containers/create: dial unix /var/run/docker.sock: no such file or directory. Are you trying to connect to a TLS-enabled daemon without TLS? 

Mac OSXへのGradleのセットアップ

完全にメモです。

Android Annotationsが使いたかっただけなんだけど、ついでにいろいろ整備する。

Android Annotationsを使うためにGradleを入れたい。GradleをセットアップするためにHomebrewを入れたい。Homebrewは前から気になってたけど、入れてなかったのでついでに入れる。

こちらを参考にさせてていただきつつ、セットアップ。 eclipseでgradleを使うための環境構築 - mi_kami's diary

Rubyが必要らしい。入ってる。

sogo$ ruby -v
ruby 2.0.0p481 (2014-05-08 revision 45883) [universal.x86_64-darwin13]

公式サイトによると、これで一発で入れられるみたい。パスワードを途中で1回入れるだけでセットアップ完了。

    sogo$ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
    sogo$ brew -v
    Homebrew 0.9.5

このままGradleをインストール

    sogo$ brew install gradle

    ・・・・

    ==> Downloading https://downloads.gradle.org/distributions/gradle-2.1-bin.zip
    ######################################################################## 100.0%
    🍺  /usr/local/Cellar/gradle/2.1: 149 files, 44M, built in 36 seconds

セットアップ完了。

sogo$ /usr/local/Cellar/gradle/2.1/bin/gradle -v

------------------------------------------------------------
Gradle 2.1
------------------------------------------------------------

Build time:   2014-09-08 10:40:39 UTC
Build number: none
Revision:     e6cf70745ac11fa943e19294d19a2c527a669a53

Groovy:       2.3.6
Ant:          Apache Ant(TM) version 1.9.3 compiled on December 23 2013
JVM:          1.8.0 (Oracle Corporation 25.0-b70)
OS:           Mac OS X 10.9.5 x86_64

Mule 3.5のセットアップとサンプルの実行

会社の方で公式ドキュメントして書くのだけど、ひとまずこちらに書いてみます。

目標は、取りあえずインストールして、実行してみるところまで。

インストール

使用可能な環境はここでチェック。OSはMuleがサポートしているJDKがサポートしていればOKっぽい。

http://www.mulesoft.org/documentation/display/current/Hardware+and+Software+Requirements

どんな構成にするか

デプロイモードを選択する。

http://www.mulesoft.org/documentation/display/current/Deployment+Scenarios

ここでいうデプロイメントとは、Mule自体の配置のこと。Mule上で動作するモジュールのデプロイメントではない。

MuleはAPサーバー上でも動かすことができるけど、基本はスタンドアローンでOK。

Mule Management Consoleって使うの?

http://www.mulesoft.org/documentation/display/current/Mule+Management+Console

いろいろな管理機能が提供される。Enterprise Editionが必要。

インストールの手順はこれの「Mule Community Runtime」のタブに従ってやればOK。基本、スタンドアローン構成ならZipを解凍するだけ。

http://www.mulesoft.org/documentation/display/current/Downloading+and+Launching+Mule+ESB+-+hid

  1. Javaセットアップ Javaをセットアップして、JAVA_HOME設定

export JAVA_HOME=/usr/java/jdk1.7.0_60/

  1. Muleセットアップ 解凍するだけ。まじ簡単。

bin/muleを実行で起動。終了するときはCtlr+C。

起動停止

$MULE_HOME\bin\mule.bat start|stop

起動オプションなんかは下記にまとまっている。

http://www.mulesoft.org/documentation/display/current/Starting+and+Stopping+Mule+ESB

自分で作ったモジュールを動かしてみよう

Anypont Studioを入れるとSampleが一緒に付いてくるから、それを実行してみましょう。

f:id:begirama:20140627084110p:plain

スタートページのOpen Sampleでサンプルの一覧が見られる。

f:id:begirama:20140627084119p:plain

まあ、最初はHelloWorldだろうと。

f:id:begirama:20140627084123p:plain

フロー定義の見た目はこんな感じ。 HTTPでリッスンして、文字列を返すだけのフロー。

取りあえず試すだけなら、Anypont Studioの中に埋め込みMuleが入っているのでプロジェクトを右クリックして、「Run AS-> Mule Application」でOK。

サーバー上のMuleへのデプロイは上記のURLの「Deploy on a Mule Enterprise Server」の通りにやればOK。

Anypont StudioでExportする

f:id:begirama:20140627084441p:plain

f:id:begirama:20140627084448p:plain

f:id:begirama:20140627084455p:plain

Muleへのデプロイ

Mule HOMEのappsフォルダにzipを置くだけ。 Muleがポーリングをしていて、しばらくするとzipが解凍されます。

[sogo@localhost mule-standalone-3.5.0]$ cd apps/
[sogo@localhost apps]$ ls
default  default-anchor.txt

appsフォルダにエクスポートしたhello-world.zipを置くと・・・・

[sogo@localhost apps]$ cp ~/hello-world.zip .
[sogo@localhost apps]$ ls
default  default-anchor.txt  hello-world.zip

しばらくするとzipが展開されてデプロイされている。

[sogo@localhost apps]$ ls
default  default-anchor.txt  hello-world  hello-world-anchor.txt

Muleのデプロイログ

同じタイミングでMule側のログには、サンプルアプリが置かれたことを検知して、インストールして起動した旨のログがでます。

INFO  2014-06-26 21:26:12,950 [Mule.app.deployer.monitor.1.thread.1] org.mule.module.launcher.ArtifactArchiveInstaller: Exploding a Mule artifact archive: file:/home/sogo/mule/mule-standalone-3.5.0/apps/hello-world.zip
INFO  2014-06-26 21:26:13,008 [Mule.app.deployer.monitor.1.thread.1] org.mule.module.launcher.application.DefaultMuleApplication: 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ New app 'hello-world'                                    +
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
INFO  2014-06-26 21:26:13,009 [Mule.app.deployer.monitor.1.thread.1] org.mule.module.launcher.log4j.ArtifactAwareRepositorySelector: Found logging config for application 'hello-world' at 'file:/home/sogo/mule/mule-standalone-3.5.0/conf/log4j.properties'
INFO  2014-06-26 21:26:15,796 [Mule.app.deployer.monitor.1.thread.1] org.mule.module.launcher.MuleDeploymentService: 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ Started app 'hello-world'                                +
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

いやー簡単ですね。

ITmediaのセミナーでの成田空港さんの事例

ITmediaさんのセミナーで、企業でのモバイルアプリの取り組みの事例などをお話しさせてもらいました。

そちらの内容は、別途、公開しますが、今日は同じセミナーで成田空港さんが事例を紹介されていましたので、Twitterの内容からまとめます。

元々はカウンターではNotesを使ってご案内ができていたが、後述の巡回案内ではNotesにアクセスできないという情報の差が課題だったそうです。Notesをモバイルで持ち出すというのは面白いですね。需要ありそう。

これは、いつもモバイルならではの使い易いUIにしましょうと、提案することが多いので、そうなんだ!と思いました。

これ、理想。

これは自分のセミナーでも同じメッセージです。 小さく、素早く始めて、利用状況を見ながら、改善していく。

iBeacon面白そうですね!

JBoss ASのデプロイプロセスを眺めた

WebLogic Serverの会社にいたので、JBossは全然触ったことがなかったのですが、最近、使ってます。今日は、デプロイのプロセスを眺めていたので、メモしておきます。

デプロイ

デプロイはこのパスにwarファイルなどを置くことで簡単にできます。 {JBOSS_HOME}/standalone/deployments/

その時、置いたwarファイルに対して、isdeployingというファイルができる。

AppPot_1.1.4_3_jboss.war
AppPot_1.1.4_3_jboss.war.isdeploying

しばらくまってると、deployedファイルになり、デプロイ完了。ファイル名で分かるというのはシンプルで面白いやり方ですね。

AppPot_1.1.4_3_jboss.war
AppPot_1.1.4_3_jboss.war.deployed 

アンデプロイ

アンデプロイするときは、deployedファイルをundeployという名前に変えるだけ。 $ mv AppPot_1.1.4_2_jboss.war.deployed AppPot_1.1.4_2_jboss.war.undeploy

そうすると、undeployに加えて、undeployedファイルができて、実際にWebアプリのURLにアクセスしてみると404エラーが返ってくる

-rw-r--r--  1 ncdc        ncdc        13887481  6月  5 08:54 2014 AppPot_1.1.4_2_jboss.war
-rw-rw-r--  1 jboss       jboss             24  6月  5 08:54 2014 AppPot_1.1.4_2_jboss.war.undeploy
-rw-rw-r--  1 jboss       jboss             24  6月  5 10:08 2014 AppPot_1.1.4_2_jboss.war.undeployed

サーバサイドJavaのトラブル分析(APサーバースローダウン)

ここ1ヶ月くらいサーバーサイドのトラブル解決をよくやっていて、Javaのサーバーアプリのトラブルの分析のやり方を書いていきます。

先日発生したのはAPサーバーのスローダウンでした。ここでの原因は特殊なものだと思うので、その理由よりは分析のプロセスの方が大事かなと思っています。

チェックした内容

  • OSリソースの使用状況

sarを見ると該当の時間でuserのCPU使用率が90%を超えていました。 ioなどに問題はないので、アプリ層に問題がありそうです。

  • gcログ

FullGCが頻発していれば、CPUを使い切っていてスローダウンが発生するが、GCは大したことなかった。

  • topコマンドでプロセスごとのCPU使用量確認

APサーバー(WebLogic Server)のJavaプロセスが使っていることを確認。 でもどのサーバーアプリかは分からない。

  • アプリログ

特にエラーはない。ただし、処理開始・終了のログから処理速度が遅いことは確認

該当の時間にBroken pipeのエラーログが大量にでていた。

Caused By: javax.xml.stream.XMLStreamException: java.net.SocketException: Broken pipe

ただし、Broken pipeが発生するのはネットワークが正常のステップで切断されていない場合(例えば、通信経路にあるFirewallがタイムアウトで接続を切っていたり、クライアントアプリがタイムアウトで接続を閉じた場合など)なので本当の理由は別にあるはずです。

エラーの原因

WebLogic Serverのログをさらにさかのぼって確認すると次のようなログがでていました。

Error Log in case of JDBC Trace Log (MS SQL Server ...

「[STUCK] ExecuteThread: '11' for queue: 'weblogic.kernel.Default (self-tuning)'は"600"秒間ビジー状態になっています。これは、構成された時間(StuckThreadMaxTime)"600"秒を超えています。」というのはWebLogic Serverがあるスレッドが設定された時間(デフォルト600秒)の間、処理がスタックしていればスタック状態と見なすという挙動です。 スタック状態と見なした後は設定に依ってWebLogic Serverを再起動したりをすることができます。

スタックトレースを見ると「com.microsoft.sqlserver.jdbc.SQLServerResultSet」が「java.util.logging.Logger」を使っているところばかりです。 実はWebLogic Server、SQL Server間でエラーが以前発生していたので分析のためのJDBC Traceログを仕掛けていたのですが、その設定が中途半端に残っていました。実際のログは出力されていないが、出力するための設定ファイルを毎回見に行くという状態になっていました。

そのため、io負荷が異常に高ければ、ログ出力を疑ったと思うのですが、実際はioは問題になっておらず、CPUを使い切っているという症状となっていました。

重要なこと

分析に必要な情報がでていること

問題の再現手順が分からないことや、本番環境でしか発生しないなど発生させるのが難しい場合があります。 予め問題の分析に必要な情報が収集されていることが重要です。 設定面で言えば、GCログが出力されるようにセットしていることや、OSやミドルウェアのリソース使用状況が記録されている必要があります。

アプリケーションの設計では、適切なログが出力されるようになっていることも重要です。 エラーのスタックトレースが出力されていて、エラーの箇所が特定できること。 スローダウンが発生している際に、全ての処理が遅いのか、特定のAPIのみかなどが分かること。(そもそもサーバー側の処理時間が分かること)

根気よく効率良く情報を読むこと

まず問題を報告してくれた人に正確な情報を聞くこと。 問題が発生した日時、問題が発生する条件・手順。 後でログを詳しく見る際に、問題が発生した日時が分からないと作業量が膨大です。

自分はまず、関連するログをgrepで「FATAL」、「ERROR」、「Exception」などでざっと検索をかけます。 (プロジェクト終盤のテストのフェーズであれば、エラーの報告の有無に関わらず、毎日ログを検索して想定外のエラーが発生していないか確認します。本来、監視の対象にならないようなログがログレベルを間違って出力されているのもここで確認できます)

それで該当の時間帯にエラーのログが出力されていれば、そこから始めます。 ポイントとして、その後のログを見ていくのでは無く、時系列をさかのぼってログを見ていきます。 もっと前の時間に同じ、または別のエラーが発生していないかを確認します。 これはユーザーに見えているエラーの原因となるエラーがもっと前に発生していることがあるからです。

この例の場合、ユーザーから報告のあった時間にはBroken pipeのエラーがありますが、 もっと前のログを見ると、java.util.Logginのエラーがでています。

今回は問題になっていませんでしたが、作っているアプリの中に問題があった場合はGCログや、スレッドダンプの中身を詳細に見ていく必要があるので、適切なViewerやWebLogic Serverの場合、JRockit Mission Controlなどのツールを使えるようにしておきたいところです。

欲しいClassがどのjarファイルに入っているか探す

Enterprise Javaをやっていると必ずはまるJar地獄。 自分が使っているライブラリを、アプリケーションサーバーや、3rdパーティーのライブラリが使っていて、ClassNotFoundや、そんなメソッドないとか、そのメソッドはPublicじゃないとか訳分かんなくなるやつ。

そんな時はエラーになっているClassがクラスパスのどこにあるか探して、複数ある場合はどっちを使うべきかを設定してやればいいし、無ければクラスパスに追加してやればOK。

Classがどのjarに含まれているか調べないといけないけど、Googleで調べても有名で皆がはまったことのあるやつしか出てこない。ですので、作りました。5年くらい前に。最近もこれに助けられた。