1

環境

巨大な PL/SQL システムを Java に移行するためのソリューションを作成中です。最初のステップは、次のような ETL ジョブを移行することです。

  1. 複数の ftp / sftp ソースから CSV、XML、(XLS、これは新しい要件です)、および位置ファイルを読み取ります
  2. データベースに保存されているルールに従ってファイルを処理し、結果をデータベース テーブルに書き込みます。

現在、これはいくつかのストア プロシージャとジョブによって行われています。

私の会社は提案を受け付けています (GlassFish 4 で実行でき、ロギングと接続プールのメカニズム、および管理コンソールを共有できる場合、それはプラスです)。

少し調べてみたところ、次のオプションが目に留まりました。

  1. Java EE 7 Batch Processingはシンプルに聞こえ、GlassFish 4 に特に適しています。
  2. Spring Batchはやや成熟しており、Java EE 7 標準 (おそらくそれに基づいていた) に非常に似ています。
  3. Apache Camelは強力に聞こえ、Apache POI などのライブラリをいじる必要がなくなりますが、やや複雑に見えます。また、それが仕事(巨大なファイルに対するETL)に最適かどうかもわかりません。
  4. 自分ですべてを調理します。Quartz / Spring Scheduler または EJB タイマーを実行するアプリケーション クライアントを作成できます。

私はまだ提案を受け入れていますが (推奨は素晴らしいでしょう)、これまでのところ、Java EE 7 バッチ処理が最適なようです。

もう 1 つ、インフラストラクチャ チームには、すべての ftp ソースからローカル ディレクトリにファイルを移動するソリューションがあるため、FTP は実際には問題になりません。

問題

私は Java EE バッチ処理に関するいくつかのチュートリアルを読みましたが、そのすべてで、ある種のServletまたはEJBタイマーがジョブの開始を担当しています。

JobOperator jobOperator = BatchRuntime.getJobOperator(); 
jobOperator.start("job", properties);

Web / EJB プロジェクトを簡単にアップロードして、変更をプールし続けることができました。しかし、私はプッシュモデルについて考えていました:

  1. アプリケーション クライアントコンソール アプリケーション
  2. メインクラスは新しいファイルのディレクトリを監視します
  3. 新しいファイルがあると、新しいジョブが開始されます。

私の疑問は次のとおりです。

  1. この戦略は可能/推奨されますか?
  2. 中間に JMS キューまたはある種のプロデューサー/コンシューマー戦略が必要ですか、それともjobOperator.startすべてのファイルを呼び出してバッチ処理レイヤーを信頼してアプリケーション リソースを管理する必要がありますか? 言い換えれば、一度に 1000 個のファイルがフォルダーに配信されjobOperator.start、1000 回呼び出した場合、GlassFish 4 はある種のスマートなエンキューを行うのでしょうか、nそれともジョブが同時に実行されないように何らかのゲートを作成する必要がありますか?
4

2 に答える 2

3

Wildfly (Jboss AS) でバッチ処理を使用するプロジェクトを既に実装しています。Glassfish の構成の詳細については詳しくありません (エンタープライズ サポートが終了したため、もう使用していません) が、私の経験に基づいて、いくつかの洞察とガイドラインを提供できます。また、Spring と Batch 仕様にも注意してください。EE 7 では非常に似ており、どちらのテクノロジを使用するかの決定は、バッチ処理以外にアプリケーションで達成したい「その他」に依存する必要があります。簡単に維持できる Web インターフェイスが必要ですか? REST API を開発しますか? など

あなたが説明している ETL ジョブは、EE 7 仕様のステップおよびチャンク モデルに完全に適合するため、すでにいくつかのテストを開発しようとした場合は、それぞれのファイル リーダーとマッパーをコーディングする必要があることに気付いたかもしれません。ファイル仕様。読み取りソースは非常に標準的であり、それらを読み取り/ストリーミングしてデータを処理するためのライブラリを簡単に見つけることができます。

私が実装したプロジェクトは非常に単純です。顧客は、データ ウェアハウスにフィードするために処理する必要があるファイルをアップロードします。このサービスは「クラウド」上にあります。ファイルには仕様が定義されており、CSV 形式である必要があります。ほとんどの処理結果は、次元の「アップサート」と事実「挿入前の消去」です。ユーザーには、ファイルとバッチ処理のメタデータ (処理状態、日付、拒否されたアイテムなど) を表示する必要がある Web インターフェイスがあります。これはクラウド サービスであるため、ファイルは (S3 を使用して) 各サーバーにローカルに存在してはなりません。

したがって、最初に設計するのはチャンク ステップです。ファイル仕様ごとに実装する必要はありませんでした。そのため、ファイルに含まれるメタデータとジョブ構成自体に従ってファイルを処理する「すべてのケースに適合する」実装を設計しました。これは簡単な部分です。次に考えるべきことは、処理とメタデータの管理です。ここでは、REST API とそれを使用する Web インターフェイスを開発しました。結局のところ、それはスケーリングしますか?Wilfly にはバッチ処理用のスレッド構成パラメーターがあり、JobOperator のスレッドの可用性を増減できます。使用可能なスレッドが十分にない場合、ジョブはサブミットされません。それで、それらの要求はどうなりますか?それらはメモリ上に常駐でき、バックアップされたステートフル セッションを開発できます。キューに入れられた処理要求の MQ リスナーを確実に実装できます。私がしたことはもっと簡単でした。会社にはクラスターを維持するためのリソースがないため、CPU 消費量と要求量に応じて拡張する柔軟な構成を行いました。これまでのところ、アプリケーションは 15 人の顧客からの 10 TB のデータを処理しており、最大要求/処理ピーク時には 3 つのエラスティック インスタンスが起動しました。

ファイル リスナーは興味深いアイデアです。ディレクトリをリッスンし、処理要求をキューまたはすぐに BatchRuntime にドロップできます。どのようにスケーリングするか、必要な応答時間、利用可能なリソースなどによって異なります。

お気軽に何でもお尋ねください。

よろしく。

編集:言及するのを忘れました。組織に何かを展開していない限り、アプリケーション クライアントの使用はあまりお勧めしません。最近のセキュリティ上の制約と Java SE の更新メカニズムにより、この種のデプロイメントを維持するのは非常に困難になっています。ウェブを考えてみてください。

于 2014-06-09T21:41:52.970 に答える
2

私はこのようにアプローチします。

このユース ケースのハンマーは、Java Watch Service、サーブレット、JMS キュー、およびバッチ サービスです。

まず、Watch サービスは、ファイル システムの監視を処理する Java 7 の移行先です。

Watch Service の実装を作成し、それをスレッドで実行します。

あなたが尋ねるスレッドはどこで実行されますか?

公式には、おそらくこれには JCA を使用する必要があります。しかし、JCA は非常に扱いにくく、十分に活用されていないため、文書化も不十分です。確かな例はありますが、Java EE スタックの一般的なテクノロジではありません。

もう 1 つの場所は、非同期のセッション Bean 呼び出しです。これらが長命の呼び出しではないことを示唆するものは何もありません。@Startup を使用して @Singleton セッション Bean を立ち上げ、@PostConstruct メソッドから async メソッドを呼び出して、放すことができます。次に、@PreDestroy で長時間実行されているメソッドを停止するように通知し、完全にシャットダウンできるようにします。Hoyle によれば、これはすべて仕様どおりで、移植可能である必要があります。

3 番目は ServletContextListener です。これは、Java EE 6 より前に、コードをアプリケーションのライフサイクルに結び付けるための場所です。ここでは、contextInitialized メソッドで自分でスレッドを作成し、contextDestroyed メソッドで破棄します。

ここでスレッドを作成することは「あまり定義されていません」ですが、私は何年もそれを行ってきましたが、問題は一度もありませんでした.

サービスを実行するようになったので、サービス (IMHO) は 2 つのことを行います。

1)新しいファイルがディレクトリに到着したことを感知し、到着すると、ファイルを並列の「処理」ディレクトリに移動(mv、名前変更)します。これは、ファイルが受信から処理に移行したこと、ファイルが進行中の作業であることを示しているためです。バックエンドが何をしていると考えているかに関係なく、ディレクトリのリストから明らかです。システムはファイルの途中でダウンする可能性があることに注意してください。

2) 移動したら、ファイル名とその他のメタデータを JMS キューにポストし、MDB にバッチ ジョブをツールアップさせます。

JMS キューを追加する理由 パーティーにいくつかの機能をもたらします。まず、EJB が好むハッピー トランザクション コンテキストの「外側」から内側へのものを取得するための優れた方法です。第二に、それはトランザクションです。ETL のユース ケースによっては、MDB でジョブを直接処理することができます。そうすることで、処理が完了するまで (そしてファイルが削除されるか、「処理中」ディレクトリから移動されるまで)、キューからのメッセージを確認しないだけです。理想的な世界では、メッセージ キューには、処理ディレクトリ内のファイルと一致するメッセージがあります。処理が完了すると、メソッドが返され、メッセージ フェッチが「コミット」され、完了です。システムがクラッシュした場合、これは自動的に最初からやり直されます (メッセージはまだキューにあり、削除されていないため)。

MDB は、そのインスタンスを構成することにより、同時ジョブの数も制御できます。10 個のインスタンスを構成します。同時に処理できるのは 10 個のファイルのみです。しかし、これは少し単純すぎたり、粗すぎたりする可能性があります。たとえば、優先順位はありません (先着順)。しかし、それはあなたのために働くかもしれません。

いずれにせよ、MDB はシステムへの優れたゲートウェイです。それぞれが独自の小さなトランザクション コンテキストから始まるからです。長時間実行されるサーブレット スレッドや長時間実行される非同期スレッドとは異なります。サーブレット スレッドのトランザクション ステータスが疑わしい (存在する場合) 場合、実行時間の長いスレッドは @Startup メソッドからその状態を継承し、存続期間中保持します。MDB は毎回新しいものを取得します。これの多くは、新しいトランザクションでメソッドを呼び出すことでごまかすことができます。

しかし、私はMDBの境界が好きです。ファイル名のバッチ エントリを作成することがすべてのタスクである場合でも、MDB は優れたゲートキーパーです。

そして、それはほとんどそれです。

重要な部分は、善良な市民であり、アプリケーションのライフサイクルに適切に結び付けられたスレッドを分解し、さまざまなコンポーネントでのトランザクションの状態を理解し、すべての可動部分がどのように組み合わされるかを理解することです。

@Startup 手法を使用する場合は、必ずセッション Bean の別のインスタンスを注入して非同期メソッドを呼び出してください。それ以外の場合、呼び出しは非同期ではなくローカル呼び出しになります。サーバーがハングアップして起動しない理由を不思議に思うでしょう。すべての EJB アノテーションは、注入されたプロキシまたは検索されたプロキシを介して呼び出された場合にのみ機能します。

楽しんで、共有して、楽しんでください。

質問への補遺:

外部プロセスに監視サービスを管理させることには、実際には何の価値もありません。サーバーのライフサイクルに結び付けられたものは、保守が容易です。2つのことが思い浮かびます。サーバーがダウンした場合、ファイルはサーバーが再起動されるまでファイル システムに蓄積されるため、データが失われることはありません。外部サービスがある場合は、メッセージをデッド サーバーに送信するか、アプリケーション サーバーとは別に JMS サーバーをステージングおよび管理する必要があります。その場合、アプリ サーバーだけでなく、監視サービス、JMS サーバー、およびアプリ サーバーの 3 つのプロセスを管理する必要があります。

とにかく外部サービスを使用することに決めた場合、サーバー上のJAX-RS RESTサービスに単純なメッセージを投稿する単純なJava SEアプリ、または単純なサーブレットでさえ、はるかに維持しやすいという他のポスターに同意します、アプリ クライアントよりもステージングして展開します。そのようにすれば、監視サービスをまったく別のものに書くことができます。

しかし、サーバーは (表向きは) ファイルを使用してファイル システムに直接アクセスできるため、このサービスをコンテナーの外で中断する動機は実際にはありません。キット全体を EAR に入れて使用します。フラットにするだけで管理が楽になります。

于 2014-06-10T00:28:55.470 に答える