MavenのJAX-WSプラグイン
まだまだエンタープライズな分野ではJAX-WSがシステム間連携に使われることが多い。wsdlからスタブを生成するMavenプラグインの使い方に関するメモ。
JAX-WS Mavenプラグイン
https://jax-ws-commons.java.net/jaxws-maven-plugin/ にJAX-WSの参照実装Metroの一部として提供されている。最新バージョンは2.3。
pom.xml の書き方
wsimport (wsdlからスタブコード生成) の例。設定可能なパラメータの一覧より、よく使う部分だけ以下に記載する。
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>net.agetsuma</groupId> <artifactId>SOAPClient</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <build> <plugins> <plugin> <groupId>org.jvnet.jax-ws-commons</groupId> <artifactId>jaxws-maven-plugin</artifactId> <version>2.3</version> <executions> <execution> <goals> <goal>wsimport</goal> </goals> </execution> </executions> <configuration> <!-- .wsdlの格納ディレクトリ。デフォルト ${basedir}/src/wsdl --> <!-- <wsdlDirectory>src/main/wsdl</wsdlDirectory> --> <!-- スタブ生成対象のwsdlファイル名。wsdlDirectory配下のファイル名を指定。 定義がなかった場合はwsdlDirectory配下すべての.wsdlが対象 --> <!-- <wsdlFiles> <wsdlFile>HelloWorld.wsdl</wsdlFile> </wsdlFiles> --> <!-- 中間生成ファイルを保持するか。具体的にはスタブのソースコードのこと。 デフォルトはfalseで.classファイルのみ生成する。 --> <keep>true</keep> <vmArgs> <vmArg>-Djavax.xml.accessExternalSchema=all</vmArg> </vmArgs> </configuration> </plugin> </plugins> </build> </project>
このプラグインはデフォルトでフェーズgenerate-source
(コンパイルする前) *1 に動くため、中間生成ファイルとして出力されるソースコードは破棄しても問題ないが、デバッグ目的で生成しておくと便利。
JDK8ではvmArgsの設定がないと例外が出て動かない。詳細についてはNetBeansのBug 241570や、このMavenプラグインのJIRA JAX_WS_COMMONS-129で紹介されている。
ビルド
いつも通りmvn package
でビルドできる。
mvm clean package
PDFBoxで取得したテキストの空白置換
SlideShareがやっているように、PDFスライドから抽出したしたテキストから、改行やタブを半角スペース1つに置換を試みた際にはまったのでメモ。
取得したいのはSlideShareのページ下部に表示されているこの文字列。
1. PDFBoxでテキスト抽出
PDFTextStripper.getText(PDDocument doc) がIOExceptionを投げるため、IntStreamでループを回すとforEachブロック内での例外処理が強制される。シンプルにするためにfor文で書いてみる。
PDDocument doc = PDDocument.load("/Path/PDFSlide.pdf"); List<PDPage> pages = doc.getDocumentCatalog().getAllPages(); PDFTextStripper stripper = new PDFTextStripper(); for (int i = 1; i <= doc.getNumberOfPages(); i++) { stripper.setStartPage(i); stripper.setEndPage(i); System.out.println(stripper.getText(doc)); }
この時点では以下のようにタブや空白、改行が混じったテキストが抽出される。
【JJUG CCC 2014 Spring H-‐2】 Javaトラブルに備えよう 日本Javaユーザグループ 上妻 宜人 (あげつま のりと) はてなブログ : n-agetsuma.hatenablog.com
2. 複数の空白やタブ・改行を半角スペースに置換
Javaで空白を置換する場合、replaceAllに¥sを設定する例が非常に多く紹介されているが、これではうまくいかないことがある。
// タブや改行を空白に置換し、2つ以上スペースが連続する場合は1つに変換 // ¥t タブ, ¥r 復帰, ¥n 改行, ¥r¥n 改行, ¥f 改ページ, 全角スペース String text = stripper.getText(doc).trim() .replaceAll("\\t|\\r|\\n|\\r\\n|\f| ", " "); .replaceAll("\\s{2,}", " ");
JJUG と CCC の間の連続したスペースが消えない。
【JJUG CCC 2014 Spring H-‐2】 Javaトラブルに備えよう...
調べてみると、JJUG{¥u0020}{¥u00a0}CCC
となっており、¥u0020はおなじみの半角スペースだが、¥u00a0(No-Break Space)が途中に挟まっている。
¥u00a0(No-Break Space)は、wikipediaに解説があり、HTMLでいう& nbspで、行末にスペースがある場合においてスペースと前の語の間で改行させないために使う文字。スライドの文字列には改行のコントロールが含まれているため、テキスト抽出すると普通のスペースではなく、nbspに変換される場合があるようだ。
他のスライドには同様な文字 ¥u202F (Narrow No-Break Space) も含まれていた。
対処
¥u00a0 (No-Break Space) と ¥u202F(Narrow No-Break Space) もスペースへの置換対象に加えてみた。
String text = stripper.getText(doc).trim() .replaceAll("\\t|\\r|\\n|\\r\\n|\f| |\u00a0|\u202F", " ") .replaceAll("\\s{2,}", " ");
1つの空白区切りで抽出できるようになった。
// before 【JJUG CCC 2014 Spring H-‐2】 Javaトラブルに備えよう... // after 【JJUG CCC 2014 Spring H-‐2】 Javaトラブルに備えよう ...
JavaOne2014 4日目メモ (10/1)
サンフランシスコ市街地のスーパーに水を買いにいったら、キャベツ太郎が売ってたので思わず写真を撮る。2.49ドル、日本でいうとポッキーよりも高級なお菓子になっている。
以下のようなセッションに参加。
Everything You Wanted to Know About Writing Async, Concurrent HTTP Apps in Java [CON3712]
非同期でかつノンブロッキングI/Oを行うHTTPクライアントをどうやって書くか紹介するセッション。
非同期およびノンブロッキングに関する振り返り
- 非同期
- I/O中のスレッドはブロックされるが、完了前に応答を返してくれるので別の仕事が並行でできる
- javaではFutureが帰ってくるような実装で実現
- ノンブロッキング
- I/O中にスレッドをブロックしない。selectorに登録し、データ利用可能時に通知をもらうモデル
- javaではNIOパッケージで実装できる
今のところの実現手段
- 元々はSNSサイトのNing社が作ってたライブラリ async-http-client
- Apache HttpCompoinentにある機能 HttpAsyncClient
いろんなREST APIから情報を持ってきて組み立てるシステムでは、毎回同期でかつブロックして待ってたら遅いので、非同期かつノンブロッキングが比較的簡単に実装できるのはとても大切。
Principles of Evolutionary Architecture [CON4580]
継続的にアーキテクチャを進化させていく上での原理・原則を紹介するセッション。
進化するアーキテクチャの原則
- 最終責任時点 (last responsible moment)
- その時点で集まる最大限の情報を集め、複雑性による技術的負債は最小限に
- 優先度を重視して、早めに決断する
- 発展的なアーキテクトと開発
- データのライフサイクルとオーナーを明確にする
- 軽量なツールとドキュメント
- ソフトウェアの内部品質は変更が容易かどうかで評価すべき
- ポステルの法則
- 送信側は慎重に、受信側は寛容に。バリデーションは必要な範囲で。
- 設計に対するテスタビリティ
- テスタビリティを向上させることで、より最適な設計に近づく
- メッセージングシステムは、あくまで通信のために使い、ビジネスロジックとしては使わない
- 振る舞いや性能だけでなく、規約もテストする
- コンウェイの法則
- それぞれの組織がデザインするシステムは、その組織間のコミュニケーション構造を反映する
- コミュニケーションの欠落は、複雑な統合に繋がる
- 製品は組織と同じ形になるので、変えたければ組織か製品自体を変える
実現のためのテクニック
- データベースリファクタリング
- 大きな変更を小さく分割して、バージョン管理もする
- 継続的デリバリー
- デプロイって作業は本来退屈じゃなきゃいけない!
- システムインタフェース規約のテスト
- 個々のシステムが独立して作業できるようなインタフェース規約
- ポステルの法則も意識しながら
- 古来よりアーキテクトが持つ役割の一つ
今後の仕事で判断に迷ったときの参考にしようと思う。
Plugging into the Java Compiler [CON4265]
Googleが作ってるValueObject実装のAutoValue、Squireが作ってるDIの実装daggerと、それぞれの技術の基となっているアノテーションプロセッサの話
AutoValue
- イミュータブルなValueObjectのコード記述を簡潔にすることが目的
pom.xmlには以下を追加
<dependency> <groupId>com.google.auto.value</groupId> <artifactId>auto-value</artifactId> <version>1.0-rc1</version> <scope>provided</scope> </dependency>
@AutoValueを付与する
@AuthValue public abstract class Address { public abstract String streetAddress(); public abstract int postCode(); public static Address create (String atreetAddress, int postCode) { return new AutoValue_Address(streetAddress, postCode); } }
ValueObject生成時にはcreateメソッドを実行する
Address a = Address.create("some address", "xxx-xxxx");
lombokの@Value異なり、AutoValueではコンパイラの処理に割り込んでバイトコードを追加したりなんてことはせずに、シンプルにソースコードを生成する。実際にNetBeansで試してみると、以下のようにソースファイルが出てくる。
AutoValueを使うとあくまでソースを生成しているだけなので、仮にAutoValue自体にバグがあってもすぐわかる。lombokで得る効率よりも、バイトコード生成の黒魔術感への不安が勝るプロジェクトで使えそう。
dagger
dagger1.0のコード例についてはマニュアルが詳しい。
Debt and Deprecation [CON6377]
Java Day Tokyo 2014やJJUG CCC 2014 Springでもラムダ式やストリームAPIについて講演されたStuart Marksさんが、Dr.Deprecator(非推奨博士?)として登場。
内容はJavaの『@Deprecated - 非推奨API』に関する振り返りと、現在複数の意味合いを持つDeprecatedを新しい言葉に置き換える提案を紹介するセッション。
今までの非推奨の振り返り
既存の『非推奨』の使い方
非推奨を新しい言葉を使って再カテゴライズする提案
陳腐化(Obsolescence)したAPIは現在の非推奨API以外(例 Vector)にもたくさんある。非推奨と一つに丸めてしまうのではなく、適切な用語を再定義してカテゴライズする。
- Condemned : 将来のリリースで削除や無効化するもの
- Dangerous : バグやデータ損失を招くAPIであるもの
- Superseded : 危険ではなく、削除される予定もないが、新しいコードでは新機能に置き換えた方が良いもの
- Unimplemented : 実装されてないことを示す。UnsupportedOperationExceptionをランタイム例外としていきなり返さずに、ドキュメント上でわかりやすくする
例えば、Superseded(廃止)として現状は非推奨になっていないが、VectorやHashTableなどの古いコレクションクラスや、java.util.Timer/TimerTask(タスクが長時間かすると次の実行がずれるシングルスレッドモデルなので、ScheduledThreadPoolExecutorに置き換えた方が良い)がある。
JavaOne2014 3日目メモ (9/30)
今日も晴れていて、過ごしやすい気候。3回目のJavaOneでも雨に振られたことがないので、サンフランシスコは雨が少ない地域なのだろうか。
Building a Distributed Application for the Cloud with Akka Clustering and Java 8 [TUT6483]
PlayフレームワークとAkkaを組み合わせて、最近話題のリアクティブなシステムを実現しましょうという話。
リアクティブ・マニフェストについて
詳細については原文を参照のこと。
- Responsive (応答性)
- システムは可能な限り最適なタイミングで応答すること。
- Resilient (障害からの回復)
- システムは処理が失敗した場合にも、失敗したことを応答すること。これは高可用性やミッションクリティカルシステムだけに求めるのではない - 処理の失敗時に何も応答できないシステムはResilientではない。
- Elastic (柔軟性)
- システムは大量のリクエスト下においても、応答すること。
Vert.x + WebSocket + Cloud = Awesome Map Tracking [CON1695]
Vert.xでwebsocketを実装して、以下の画面のように常に動くバス情報をブラウザ上の地図画像にアイコンとして表示するデモのセッション。RedHatが提供しているPaaSであるOpenShiftがVert.xに対応しているので、合わせてOpenShiftの紹介も少し。スライドはこちらで公開中。
セッションの冒頭で早速『今までのTomcatやJBossと何が違うの?』という質問が飛ぶ。分散環境でフレキシブルに重点を置いた新しいアーキテクチャと答える。
Going Native: Bringing FFI to the JVM [CON3979]
従来のJNIに代えて、もっと簡易にネイティブコードが呼び出せる仕組み JNR (Java Native Runtime)に関するセッション。スピーカーはJRubyの開発者であるCharles Nutterさん。JNRについてはgithubにて公開中。
JRubyを作っていて困った事
Javaで作られているJRubyを作るにあたって、OSレベルへのアクセス、例えばファイルシステムアクセスや、グラフィック/暗号化などのネイティブライブラリへのアクセスで困っている。しかし既存のJNIは使いにくい面も多い。もっと簡単にネイティブコードが呼び出せる仕組みがあると良い。
JNRのコード例
現在のプロセスIDを取得するlibcのgetpid関数を呼び出す例。とても直感的なコード例になっている。
import jnr.ffi.LibraryLoader; import jnr.ffi.annotations.IgnoreError; public class GetPidJNRExcample { public interface GetPid { @IgnoreError long getpid(); } public static void main(String[] args) { GetPid getpid = LibraryLoader.create(GetPid.class) .load("c"); getpid.getPid(); } }
JNRの構成要素
ユーザレベルの関数だけでなく、色々なネイティブ関数にアクセスできる。例えば以下のようなもの。
- jnr-posix : POSIX準拠の関数をJavaから実行
- jnr-unixsocket : unix socketをJavaから実行
- jnr-x86asm : x86アセンブラをJavaから実行
The Modular Java Platform and Project Jigsaw [CON5435]
前々から検討されているJDKへのモジュールシステム導入 Project Jigsaw に関するセッション。
互換性の維持と新機能の要望により増え続けるJDKのコアAPI実装にモジュール化システムを導入して、使いたいモジュールのみをロードする仕組みを作る。デモではrt.jarがなくなったよとのアピールがあり。
jlinkと呼ばれるツールで依存性を管理するらしいが、詳細は理解できなかった。JDK9のEarly Accessには今のところJavaOneでデモがあったjlinkやrt.jarの削除が盛り込まれていないので、JDK9のEAにマージされるのが待ち遠しい。
Troubleshooting with Serviceability and the New Runtime Monitoring Tool HeapStats [BOF3108]
NTT OSSセンタが開発したJavaトラブル解析支援ツール HeapStats のBOF。NTT OSSセンタはNTTグループ会社向けのOSSのテクニカルサポートを提供しており、頻出トラブルとトラブル解決の迅速化を目的に開発されたHeapStatsの紹介が行われた。
よくあるトラブルについて
OSSセンタに寄せられたサポート依頼では、ヒープ関連のトラブルシュート依頼が特に多かった。
トラブルシュートの課題
情報がない
ヒープのトラブルが多いが、トラブル発生時のヒープダンプが残っていない事も多く、-XX:+HeapDumpOnOutOfmemoryErrorをトラブル発生後に追加してもリークスピードが遅く、再現に数ヶ月かかるケースもあった。
既存ツールは重い
ヒープダンプは取得に時間がかかるためサービス影響が大きく、ヒストグラムではオブジェクト間の参照が見れないため解析情報が不足する。
JavaOne2014 2日目メモ (9/29)
2日目。朝は霧が出ていて少し寒いが、日中になると日差しが出て半袖でも良いくらい暑くなる。今日から本格的にセッションの開始。
Java EE 8 [CON3015]
Java EE8のスペックリードであるLinda DeMichielさんによる、Java EE 8の現状の方針を話すセッション。
Java EE 8の大きなテーマは3つ。
HTML5/Web層の改善
- JSON-Bの導入 : JSON - オブジェクトマッピングを標準化する
- JSON-P 1.1 : JSON Patch、JSON Pointerへの対応
- ServerSentEvent(SSE)への対応 : 既にGlassFishのJAX-RS実装であるJerseyで実装
- アクションベースのMVC
- Servlet4.0によるHTTP2.0対応
Easy of Development / CDI Alignment
Tutorial: JVM Platform as a Service [TUT3525]
スエーデンのCITERUSという企業の技術者が、2012年にJavaが使えるPaaSを使ったプロジェクトを経験談を交えながら、各PaaSプラットフォームの特徴やデモを示すセッション。
なぜPaaS?
- 何よりもtime-to-marketの達成がPaaSを使う一番の目的。
- 過去の事例では、顧客のコアドメインがITと関連が薄く、ITインフラ(サーバとか)を持ってなかったのがPaaS適用を推進した。
dotcloudを使ってみて
- Java、MongoDB、PostgreSQL、RabbitMQが使いたかったため、テクノロジスタックが合った
- 実際に運用してみたら色々問題も出てきた
- ヨーロッパ - アメリカのレイテンシによる性能問題、価格の値上げ改定
- 結果的にjerasticを使ってサービスを提供しているスエーデン国内のPaaSサービスに移行し、各々の問題に対処した。
HTTP 2.0 Comes to Java: What Servlet 4.0 Means to You [CON5989]
HTTP2.0(SPDY)の登場に伴い、ServletやJava SE9のAPIへの機能追加について紹介するセッション。まだ JSR369 Servlet4.0 として検討がはじまったところで、いくつかのコード案が紹介されたが写真取れず。
Java SE 9側でのHTTP2.0クライアントのアイディアについては、以下のようなコード例が紹介された。
HttpRequestGroup group = HttpRequestGroup.create(); HttpRequest req = group.createRequest() .setRequestMethod("POST") .setRequestURI(new URI("http://www.foo.com/a/b")) .setRequestBody("param1=1,param2=2") .onResponseHeader("X-Foo", (request, name, value) -> { System.out.println("receive an X-Foo header") }) .sendRequest() .waitForCompletion();
HTTP2.0では、1つのコネクションが1対1でのリクエスト/レスポンスモデルではなく、複数のリクエストが1コネクションで並行して送受信されるため、リクエストのグループ化(HttpRequestGroup)が導入し、その後のリクエスト送信にもメソッドチェーンや、リクエスト応答のヘッダ処理にラムダ式を書いたり、最近のJavaっぽいAPI案となっている。
Modular Architectures Using Microservices [CON6132]
モジュラアーキテクチャの考え方を、クラウド環境でOSGiを使うためにリモート呼び出しなどをサポートするAmdatuを使って実現する方法を紹介したセッション。
まず、amdatuによる実装を示す前に、ソフトウェアをなるべくモジュール化して連携させるモジュラアーキテクチャとマイクロサービスの考え方を紹介した。
モジュラアーキテクチャとは
原則として以下の2つを要件として紹介した。
マイクロサービスとは
- マーチンファウラ氏のブログの内容を時折引用。
- 分散システム固有の設計には注意する必要
- どれか1つが落ちていても、サービスが縮小継続できるように
- モニタリングに手間が掛かるのは、分散の代償
OSGiについて
Banking on OpenJDK: How Goldman Sachs Is Using and Contributing to OpenJDK [CON5177]
Goldman Sachs社のOpenJDKへの取り組みに関するセッション。
Goldman SachsとJava
- 1998年頃からJavaを技術評価として利用開始
- 2004年から自社コレクションフレームワークを作り始め(githubで公開中)
- 2013年からOCAにサインして、OpenJDKへのコントリビュートを開始した
- 190GB以上のヒープを持つシステム、大量の分岐があって、JITコードキャッシュに影響を与える特殊な環境が特徴的。
なぜOpenJDKに力を入れ始めたのか
- ソースが見れるのが何よりも重要
- 商用でクラッシュしても解析できる
- HotSpotの内部で改善できそうな部分を自分たちで見つけることができる
- パッチを投げることが、自分たちのためにも、コミュニティのためにもなる
どんな風にOpenJDKを使っている
- トラブルシューティング、新規能の研究・検証に使用
- JVMTIでアサーションエラーが発生したバグ解析とパッチ作成の事例を紹介
- 今のところ、プロダクション環境では使っていない
OpenJDKしてのソースが公開により、筆者自身もAPIやHotspotでのトラブル時に大変助かっている。Redhat Enterprise Linuxを使っているシステムではOpenJDKがバンドルされていて気軽に使えるので、もっと使われるところが増えると嬉しい。
JavaOne2014 1日目メモ (9/28)
JavaOne2014の初日はコミュニティが主体のユーザグループフォーラム(UGF)と、キーノートがサンフランシスコのモスコーンセンタにて行われた。カメラとPCを繋ぐケーブルを家に忘れたので、写真は後日追加予定。
以下、荒い部分も数多くあるがセッション参加メモ。
Lambdas and Laughs [UGF9672]
プロジェクトラムダの振り返りに関するセッション。
ラムダ式とは?ストリームAPIとは?Optionalは?など、Java8に入った新機能についてコードを見ながら振り返り、JavaOneでの関連セッションを紹介する。ユーザグループフォーラムのセッションらしく、途中でウケ狙いのスライドがたくさん入っているが、何回もスベる。
内容については様々なJava8特集で既出のため、特記事項なし。
GlassFish Roadmap and Executive Panel [UGF9120]
GlassFishのロードマップと、今後の方針に関するパネルディスカッション。アジェンダについては、GlassFishのホームページにもまとめられている。
ユーザグループフォーラムにも関わらず、オラクルのJava EE関連のエヴァンジェリストReza Rahmanさんや、この後のストラテジキーノートでも講演するCameron Purdyさん、日本でもWebLogicの製品発表関連で見かけるMichael Lehmannさんなど、オラクルとしての方針を話そうな立場の人たちがパネラーに並ぶ。
GlassFish 製品の基本的な戦略 (アナウンス済み内容と同じ)
GlassFish4.1の新機能
Java EE8の今のところの方針
The OpenJDK Project: Your Java. Our Java. [UGF9755]
OpenJDKの今後の方針とコントリビュート方法に関するセッション。JEP(JDK Enhancement Proposals)に挙がっているJDKの改善案の紹介が行われた。いずれもドラフト段階だが興味深い。
紹介されたキーワードを以下のまとめる。
- Shenandoah : 新しいGCストラテジ
- 100GBヒープのような巨大ヒープでも、10ms以下の停止を目指す
List<Integer> list = #[ 1, 2, 3 ];
- Measurement API
- 色々な物事の値を単なるintやdoubleのような数値ではなく、クラスとして定義して抽象化したもの
- githubのコード例により何となくイメージできる。例えば以下は心拍数を示す。
public static void main(String[] args) { HeartRate rate = HeartRateAmount.of(BigDecimal.valueOf(90), BPM); System.out.println(rate); }
- HTTP2.0 Client
- 軽量なJSONパーサ などなど
Strategy keynote / Technical keynote
Strategy Keynote
- キーノートの前日に子供たちにプログラミングを教えるイベントがあったらしく、キーノートは子供たちの成果発表から始まる。
- 子供向けだけではなく、コミュニティやJCPを通じてコミュニケーションを取る姿勢をアピール
Java SE
- Java 8 buzz
- Java8は色々な記事にも取り上げられ、書籍もたくさん出版されて確実に広まっている。
- OpenJDKへのコントリビュート
- オラクル以外のコミュニティによる貢献が引き続き行われている。ダグ・リーさんによるコンカレントAPIへの継続的な貢献など。
- Goldman sachsによるJava8の適用事例
Java ME
- 普段使ってないので聞いてもよくわからず。
Technical Keynote
- 言語仕様やJVMの改善を盛り込むProject Valhalla、ネイティブコード呼び出しを改善するProject Panamaについては時間切れで説明なし
今年のキーノートは過去の振り返りが中心で新しい発表はなく、OpenJDKコミュニティやJCPで流れているJava9やJavaEE8の内容はまだまだ議論の途中でオラクルによる公式な周知はまだない印象を受けました。
HeapStatsをChefでインストールする
HotSpotJVMの監視・解析OSSツールであるHeapStatsをChefでインストールできるようにクックブックを作ってみた。
n-agetsu/chef-heapstats · GitHub
HeapStatsとはなんぞやについては、JJUGナイトセミナーなどのスライドやキャスレー技術ブログ JavaVM監視・解析ツール HeapStatsを使ってみた参照。特に後述のブログには公式のwikiよりも詳しくまとまっている。
簡単にいうと、ヒープダンプのように一気に負荷をかけなくても、FullGC契機に少しずつヒープ情報をロギングしてくれる優れものである。
HeapStatsはアタッチ先のJVMへのオーバーヘッドを抑えるため、対応しているマシンが対応しているCPU命令セット(sse4 or avx or いずれも未対応)に応じてインストールするrpmファイルが異なる。このクックブックを使うと、マシンに合ったrpmをダウンロードしてインストールする。
前提条件
HeapStatsの動作条件は以下の通り。
HeapStatsクックブックの使い方
JDK7、WildFly、HeapStats agentの3つをChefでインストールする例を以下に示す。
vagrantやchef、knife-solo、berkshelfのインストールについては、Web上の記事やChef 実践入門本に詳しく紹介されているので省略。vagrant-berkshelfはハマってうまくいかなかったので、素直にknife-soloでセットアップする。
1. Cookbookの作成
適当な作業ディレクトリにクックブックを生成する。
cd work knife solo init .
2. Berksfileの編集
knife solo init .
の実行により、カレントディレクトリにBerksfileファイルが作成されている。ここにjava/WildFly8/HeapStatsのクックブックへの依存を定義する。
$ vim Berksfile source "https://supermarket.getchef.com" cookbook 'java' cookbook 'heapstats', git: 'git@github.com:n-agetsu/chef-heapstats.git' cookbook 'wildfly', git: 'git@github.com:bdwyertech/chef-wildfly.git' $ berks install
cookbook 'heapstats'で指定している部分が今回作ってみたHeapStatsクックブック。berks install
により、依存先クックブックは./cookbooksにダウンロードされる。
3. Nodeオブジェクトの作成
対象マシンに何をインストールするか定義するnodeファイルを作成する。ファイル名のcentos.jsonのcentosの部分は、マシンのホスト名 or IPアドレスを指定。
run_listと各クックブックのattributeを定義する。作ってみたHeapStatsのクックブックの依存先はjavaのみで、内部的にinclude_recipe 'java'して呼び出している。*1
wildflyクックブックにおいて、HeapStatsの有効化に必要なJava起動オプション-agentlib:heapstats
を追加している。他のAPサーバの場合でも、Java起動オプションに-agentlib:heapstatsを追加できればHeapStatsは有効化される。
heapstatsのfile/heaplogfile/archivefileはHeapStatsが出力する各種ファイルの出力先を指定している。ログが一カ所にまとまるように、wildflyのログディレクトリを指定した。
$ vim nodes/centos.json { "run_list": [ "recipe[heapstats]", "recipe[wildfly]" ], "java": { "install_flavor":"openjdk", "jdk_version":"7", "openjdk_packages":["java-1.7.0-openjdk", "java-1.7.0-openjdk-devel", "java-1.7.0-openjdk-debuginfo"] }, "wildfly": { "jpda": { "enabled":false }, "java_opts": { "other": ["-agentlib:heapstats"] } }, "heapstats": { "file":"/opt/wildfly/standalone/log/heapstats_snapshot.dat", "heaplogfile":"/opt/wildfly/standalone/log/heapstats_log.csv", "archivefile":"/opt/wildfly/standalone/log/heapstats_analyze.zip" } }
HeapStatsクックブックで指定可能な属性についてはREADME.mdに記載している。
4. プロビジョニング
knife solo bootstrap
で、対象サーバへのchefのセットアップknife solo prepareと、クックブックの実行knife solo cookの両方が動く。
$ knife solo bootstrap centos --bootstrap-version 11.12.0
centosの部分は、プロビジョニング対象マシンのホスト名を示す。IPアドレスでも可。
bootstrap-versionの指定がないとエラーになって動かない場合はがある。詳しくはstackoverflowに記載がある。
これでインストールは完了。JVMにHeapStatsがアタッチされた状態のWildFly8が起動している状態となる。
今後の課題
試しに作ってみたものの、以下のような課題があるので今後追加予定。
- HeapStatsの各種出力ファイルへのログローテーション (logrorate.d) 対応
- OpenJDKを使用する場合のdebuginfoインストール漏れのチェック