Monthly Archives: 11月 2014

JDBCでResultSet.nextを使って逐次処理しているからといって安心しない。setFetchSizeを忘れずに!

JDBCを直接使っている人向けの話。いねえよとか言わない!おれがいる!

try (ResultSet result = statement.executeQuery();) {// このクエリは数百万件とかすごい量のデータを返すとする

とかしたとして、ブロックの中で

while (result.next()) {
    // ここで順次的に処理をする
}

とか書いて置いて、ほらちゃんとresult.nextで順次的に処理してるし、try with resourceでcloseもバッチリ!といっても、俺偉いとか思わない。executeQueryを実行した直後のヒープダンプがコレ。

ResultSetのインスタンスが60%以上取っている

まだresult.next()していない。そんな!ResultSetはデータそのものじゃなくて、接続の管理クラスみたいなやつだから、実際はnextして順次的にDBから値をもらうんだって教わった。なのにどうもメモリを食ってる。

ヒープダンプの中身を解析してみる。

rowsというVectorに全部のデータが格納されている

rowsというVectorがデカイ。

_人人人人人_
> Vector <
 ̄Y^Y^Y^Y ̄

WeakReferenceでもSoftReferenceでもないタダのVectorなので、メモリにガッツリ確保しております。そう、ResultSetはパフォーマンスのために、結果のうち数行をキャッシュするのだ!

そのキャッシュのサイズを制御するのがこのメソッド

https://docs.oracle.com/javase/6/docs/api/java/sql/Statement.html#setFetchSize(int)

setFetchSize

void setFetchSize(int rows)
                  throws SQLException
Gives the JDBC driver a hint as to the number of rows that should be fetched from the database when more rows are needed for ResultSet objects genrated by this Statement. If the value specified is zero, then the hint is ignored. The default value is zero.

なるほど。フェッチする行サイズを(あくまでヒントとして)指定できるらしい。デフォルトでは0、すなわち無指定状態のようだ。

じゃあ、ヒント無しの場合はどうなるのだろう。

http://grepcode.com/file/repo1.maven.org/maven2/postgresql/postgresql/8.4-702.jdbc3/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java#AbstractJdbc2ResultSet.next%28%29

row_offset += rows.size(); // We are discarding some data.
//
// 省略
//
int fetchRows = fetchSize;
if (maxRows != 0)
{
    if (fetchRows == 0 || row_offset + fetchRows > maxRows) // Fetch would exceed maxRows, limit it.
        fetchRows = maxRows - row_offset;
}

rowsが件のVectorであるので、つまり全部のデータをfetchRowsしようと試みてるってこと??

なので、大きめのクエリを流そうとしている場合は、setFetchSizeはほぼ確実に呼び出すべき。ただ、大きめにするとメモリを食うし、小さめだとパフォーマンスが不利になるのでその辺りは統計を取って最適値を模索するしかないかと。

あと、あくまで行のキャッシュであるので、一行にtext型を格納したドデカイカラムがあったりするとやばそうです。

JJUG CCC 2014 Fall ( #jjug_ccc )に参加して来ました

昨日開催された日本Javaユーザーグループ主催のIT勉強会 JJUG CCC 2014 Fall に参加してきました。

参加したセッションと感想

K-1 基調講演1 : これからのJavaエンジニアの生きる道

概要:これからのエンジニアの生きる道はグローバル化(英語)や人工知能(数学)などの専門性の高さなど険しくなる上に、「心の時代」と言われ、幅広い視野が必要となる。そこでJJUGなどのコミュニティを利用して欲しい。コミュニティと熱い心があれば大丈夫と締めくくっています。

ご本人が「はっしーさんって熱いかたなんですね」と言われたとFBでコメントしていましたが、僕も思いました。熱かったです!

公開されたスライドを読み返してみると、最初のセッションにして、全体を締めくくっているような内容だと思いました。このスライドを読み返してから、もう一度、その他のセッションの公開されているスライドを読んでみると、まさに、高い専門性と幅広い視野、熱い心、そしてその「場」であるコミュニティというインフラがあるんだと思いました。

コミュニティの存在への感謝と、熱意を忘れずに今後も、技術者として生きて行きたい。このスライドは永久保存してくじけそうになったときに読み返したいと思います。

K-2 Java 2014 将来に向かって

米Oracleのエバンジェリストの方の英語と、通訳の方の日本語を交互に流す形式の発表でした。Javaの今後のロードマップが丁寧に説明されていて、JavaはSE, EE, MEあらゆる方面で今後も発展して行くことが紹介されていました。

H-1 Javaが見るニュータイプの夢 ~これからJavaはどう変わるか~

  • Project Valhara

    • value class: C#で言うところに構造体
    • Specialization: ArrayListのようにプリミティブを指定できるGenerics
    • ClassDynamic: 動的なクラスリンク
  • Project Panama

    • Foreign Function Interface (FFI): ネイティブコード呼び出しの改善
    • Object Layout: オブジェクトの配置
    • Arrays2.0: 配列の改善(配列の配列ではない2次元配列の実現など)

要するに、JavaもC#の良いところを取り入れようというプロジェクトをOpenJDKプロジェクトの一部でOracleが進めているようです。特にC#がオープンソースでマルチプラットフォーム対応になった今、対応が急がれると締めくくっていました。

R1-2 Spring Boot + Doma + AngularJSで作るERP(統合基幹業務システム)

ざっくり言うと、S2Dao + Teedaベースで作られた2000年代のシステムを一旦JavaEE6に置き換えたが、しっくり来ずに、Spring Boot + Doma + AngularJSの構成にしたらしっくり来たということらしいです。

今度、新規でJavaでアプリを作るときの選択肢として参考にしようと思います。

R1-3 実例Javaトラブルシューティング! 稼働中のシステムを立て直した半年間の軌跡

ECサイトのトラブルシューティングは、職務上色々、ピンとくるところがあり、

「いやー、さすがにうちはそこまでひどくないwww」

というのではなく、きちんと襟を正して、悪いところは反面教師として、良いところは参考にしようと思います。実務に役立つ大変すばらしいセッションでした。

以下感想ですが、実際のサービスの現場ではここまで絶望的でなくても、あきらめたくなるようなひどい状況に陥ることはあると思います。しかし、そんな場合でも適切にアプローチすると、ある一カ所の改善で実質大部分の問題が解消するようなこともあり、システムのトラブルシューティングが可能であるという個人的な実感と一致します。

なお、僕の品位の低い言葉でこれを言い直すと「クソみたいなシステムでも1割のクソを取り除くだけで使い物になることがある。」「きれいなシステムでもたった一個のクリティカルなクソによって死ぬことがある」です。

H-4 Javaエンジニアのためのアーキテクト講座

ITテクノロジーのアウトプットがアプリケーション開発から、サービスの運営へのシフトした結果、今までと比べてステークホルダー・プロセスが複雑となった。そんな中で、各ステークホルダー間の調整をし、サービスの観点でシステムを設計することがアーキテクトの役割を述べています。

扱う範囲が広範囲にわたっていて、テクノロジーも幅広く理解理解する必要があり、はっきり言ってこの通りにできる人はいないと思いますが、求められているスキルと言えば、そうなのだと思います。

個人的な話で恐縮かつ、スライドの内容とは異なるのですが、僕は小さい組織がサービスを開発しサービスとともに組織が成長していく過程で、技術サイドでいろいろ意見を述べさせてもらう立ち場を経験させてもらいました。小さい組織では、エンジニアがフルスタック的に振る舞う必要があり、その中ではステークホルダー=俺、になる状況が多いので「調整」という面では楽です。しかし、提供しなければいけない価値は大人数であろうと小人数であろうと同じです。なので、一度サービスを一人で開発・運用・できれば営業できれば、結果的には脳内に多数のステークホルダーが存在することと同義になります。そうした脳内の会話は、専門の人が考えるよりもずっと幼稚な物だと思いますが、必要なことは何かを意識する最適な方法だと思います。

そう考えると、難しい言葉はいらないと思います。テクノロジーよりメンタルの問題なのではないかと思います。

しかし、鈴木氏のスライドを見ると「ムズカシイ」言葉だらけになって「俺には無理ダーー」感満載にな気がします。一緒に発表を聞いていた大学生が、そういう反応をしていたのを見て、むしろ若い子たちにこそ、こういうことの必要性を訴えたいのに、なんとかならないものかと思いました。

内容は大変すばらしかったです。一度現場を経験している僕自身は、自分の至らなさを反省するとともに、言葉にできなかったことを言葉にされていて、大変参考になりました。

以上をふまえて、アンケートは厳しめに評価を付けさせて頂きましたが、僕自身としては今回最も参考になったセッションでした。

R2-5 Javaだからこそできる、ビズリーチの攻めのDB変更

DB変更というのでてっきり、MySQLのシステムをPostgreSQLに移行した話だと思ったのですが、そうではなく、テーブル構造をシームレスに変更するDBFluteの話でした。

久保さんの話は面白かったのですが、それならば、もう一つの発表も気になっていたので、途中退出しました。

2014/11/19追記

後日公開されたスライドを読みましたが、非常に内容同意できました。僕の現在の業務でも、週一でシステムを更新し、その際、テーブル定義変更はほぼ確実に発生していますが、社内メンバーで知恵を絞った結果ほぼ同様の運用をとっていると思います。違いといえばツールがExcelとマクロであって、DBFluteほどカッコよくないということです。

R1-5 JavaでやってみるThe Twelve-Factor App / nabedge

途中から聞いたので全体を聞けていませんが、非常に現場の経験に基づいた開発指針なのだと思いました。
というのも、過去に自分がやらかしてしまって、改善をして行った記憶と一致するところが多いと思いました。

意外と開発当初はおざなりになってしまう、デプロイフローやパッケージ管理について、これからアプリを作るときはこういった指針に基づいた設計を心がけることにして運用時の罠にはまらないようにしたいと思います。

2014/11/19追記

スライドが公開されたので、じっくり見てみました。

VII ポートバインディング

組み込みと言ったらJettyでしたが、Spring BootでTomcat組み込みが最近流行っているのですね。EclipseのServersの設定は開発者間でトラブルの元になるのでコード化するのは良いことだと思います。

IX ログ

Fluentd + BigQueryや、Elasticsearchなどが一般的になってきているので、標準出力に流すというのは良い考えだと思います。今後の参考にしたいです。

III 設定は環境変数に

自分も設定をSVNにコミットして、環境ごとに呼び先のフォルダーを切り替えるなどで結構苦労しています。環境変数はライトな考えで良いですね。ただ、どの設定が必要なのかは、別途管理しなければならないかなと思いました。ChefやPuppetを使う前提なら良いわけですね。

あるいは必ずant経由で実行するとか、そういうライトなツールなら作ったことあります。ああ、antとか古いのかなあ。

II 依存関係, V ビルド・リリース・実行

ある程度の規模になるとMavenすら使うのが億劫なのですよね。セントラルにアクセスすると遅いし。でも、Sonatype NEXUSでリポジトリを管理できると便利かもしれません。NEXUSは知りませんでした。NEXUSとか、単体ではSEO悪すぎw "Sonatype"社名付けてくれなかったら検索しづらかったと思います。

バイナリをリポジトリサーバーにデプロイして、依存関係管理、なんてすばらしいマイクロサービス!全部ソースで依存関係やっていたので、ビルドが日に日に遅く。。。なんてことがないですね。

VI ステートレス

僕の見解では、セッション窓から捨てたい。スライドの趣旨と異なりますが、言いたいので言います。ほんともう、セッション排除せよ!です。

非同期リクエストが多い現在、Stickyセッションはデータの不整合の温床です(処理の途中で別リクエストがセッション変数を書き換えたりする)、Stickyを使わずシリアライズ・デシリアライズする方法はバージョン不整合(非同期リクエスト間で読み込んだ瞬間のセッション変数値が異なることで不可解な結果を得たりします。しかもテスト環境では再現しなかったりたまたまその時ネットワークが遅かったとか言う時にだけ発生するので非常にタチが悪いです。

では、何を使うべきなのかというと、僕自身答えが出ていませんが、一時的な状態はローカルストレージなどクライアントに持たせて、CSRF対策用のTokenなどセキュリティ上の要件だけセッションを使用するというのがいいような気がします。WebアプリをRestfulに設計すると自ずとそういう形になるのではないかと思います。そういうこともあって、JSFなどのコンポーネントベースのフレームワークって苦手なんですがどうなんでしょうね。

セッション使うなら、Ajaxを使わないレガシー画面遷移、右クリックを禁止、戻るボタン禁止、IE限定(笑)これくらいしないとならないかなと思ってしまいます。w

ちなみにmemcached-session-managerは痛い目にあいました。おすすめしません。

R1-6 Concurrent Mark-Sweep Garbage Collection 再入門

CMS-GCとは名前は聞きますが、並列実行できてStop the worldがおきにくいJavaの標準GCアルゴリズムだよという理解でしかありませんでした。

ステップ別の説明や、ログの読み方が非常に参考になりました。今後GCのトラブルがあった際は参考にしたいと思いました。

初めて聞いた(またはよく理解していかった)キーワード

Spring Boot

@makingさんのスライドによると

フレームワークというよりプラットフォーム
簡単に言うと、Spring Framework でアプリケーションを簡単に作る ための仕組み

とのこと。開発環境みたいな物かと思ったらそれでもないらしい。アノテーションとか使って、依存関係をいい感じに解決しつつ、設定も自動化していてサクサクと開発できる仕組みのようだ。

良いという意見を複数聞いたので、機会があったら検討してみたい。

Doma

  • Seasar傘下のO/Rマッパーとその開発支援ツール
  • 現在もメンテナンスされている
  • Java6以上で動作。

聞いた感じだと、モダンなS2Dao、ごりごりSQL書く人向けのツールのようだ。

Elasticsearch

  • AWSのサービスの一つではないらしい(勘違いしていた)
  • Restfulな検索・解析サーバーソフト
    検索エンジン用途だけでなく、R1-3ではトラブルシューティング時のログの解析にも使用したようだ

kibana

  • 可視化ツール
  • Elastic Searchの結果をグラフとかにして可視化するのに使う

Fluentd

  • 最近ログの文脈でよく聞くお前は何ものか?
  • 既存のシステムログをどうにかするのではなく、システムのイベントベースにあらゆるデータを収集して、任意の方法で記録・アウトプットできるツールらしい
  • Fluentdで出力したログをBigQueryで解析するのがトレンド?
  • そうか、お前はいわゆる「ログファイル」とは別物だったのだな!

ENdoSnipe

  • アクロクエスト社の製品
  • 「FindBugsの動的版」とのこと
  • システムを動作させながら状態を分析するツール
  • シーケンス図を出力するArrowVisionは無償でダウンロードできる
    システムを動作させながら分析できるツールを探していたので興味がある

第三の時代

  • 米ガートナー社によると、現在のITは「第三の時代」に到来していると言われている。
  • 第一: 業務の自動化
  • 第二: ITプロセスの工業化(これまで10年)、社内のプロセス改善
  • 第三: あらゆる先進テクノロジーを取り込み、ビジネスを創出する

参考: IT部門の主導権を奪う新時代が到来 : 日経BizGate

マイクロサービス

  • 誤:マーチンファウラー氏が提唱
  • 正:James Lewisが提唱
  • システムを独立した複数のサービスの集合として構成する

ITシステム版モノリシック・マイクロ論争ということかと思う。

2014/11/19追記

Sonatype NEXUS

  • Mavenプライベートリポジトリの管理ツール
  • OSS版、有償版がある
  • リポジトリの追加し、WEB-DAV経由でアーティファクトのデプロイが可能
  • リポジトリの内容を閲覧したり検索したりできる