Flex Gateway新着情報
Governance新着情報
Monitoring API ManagerMule 4 実行エンジンは、リアクティブストリームをベースとしています。つまり、非ブロック操作は最上位でサポートされます。デフォルトではすべての操作はブロック操作となります。すでにお気づきかも知れませんが、これまで見てきた操作例のセマンティクスはすべて継承的にブロック型となり、Runtime がメソッドを呼び出して応答で値を取得します。これは、I/O 負荷よりも CPU 負荷の大きい操作や、JDBC (Database Connector を駆動する API) など、非ブロック型としてはコンシュームできない API をコンシュームする操作では問題ありません。
ブロック型をサポートするプロトコルとしては HTTP などがあります。ゲートウェイプロキシの拡張性を高めるためには、非ブロック HTTP 要求を実行できることが鍵となります。これによって、REST API をコンシュームするすべてのコネクタも恩恵を受けます。
次の簡素化された HTTP 要求の例は、SDK でどのように非ブロック操作を開発できるかを示しています。
public void request(String url, @Connection HttpClient client, @Content String body, (1)
CompletionCallback<InputStream, HttpAttributes> callback ) { (2)
client.send(url, body, new HttpResponseCallback() {
void onResponse(HttpResponse response) {
callback.success(Result.<InputStream, HttpAttributes>builder() (3)
.output(response.getBody())
.attributes(toAttributes(response))
.build());
}
void onError(Exception e) {
callback.error(e); (4)
}
});
}
1 | ブロック操作とは異なり、戻り値のデータ型はメソッドの戻り値のデータ型では指定されません。非ブロック操作は、常に void メソッドで指定する必要があります。 |
2 | CompletionCallback 型の引数を持つ操作は非ブロック型となります。このインターフェースは、汎用型を使用して操作の戻り値のデータ型を指定しています。最初の汎用型は出力ペイロードの型で、2 番目は出力属性の型です。これらの汎用型は必須です。 |
3 | 戻り値は CompletionCallback の success(Result) メソッドを介して渡されます。Result オブジェクトの詳細は、Result オブジェクトについての説明を参照してください。 |
4 | 非ブロック操作は、例外をスローすることはできません。すべてのエラーは、コールバックの error() メソッドでチャネルしてください。 |
この例では、CompletionCallback が HttpResponseCallback の間にコンシュームされています。2 場目のコールバックは、非同期応答をサポートする HttpClient によって提供されています。前述のように、非ブロック操作を実行するためには、それに対応した API をコンシュームする必要があります。
|
このコードの結果は非ブロック操作であり、InputStream
をペイロードとして、HttpAttributes
オブジェクトをメッセージ属性として返します。
void 非ブロック操作を実行することも可能です。ユースケースとしては、ファイルへの書き込みなど、何も返さない I/O 操作があります。
public void write(String path, @Content byte[] bytes, CompletionCallback<Void, Void> callback) {
writeAsync(result -> callback.success());
}
この例からわかるように、Java の Void
型を使用して操作が void であることを示すことができます。
上述のように Mule 4 はリアクティブ実行エンジンを備えています。Mule 3.x では各フローが独自のスレッドプールや SEDA キューなどを持っていましたが、Mule 4 Runtime はいくつかのグローバル実行エンジンによってすべてのタスクを実行しています。
タスクを正しくスケジュールするには、各操作がどのような処理を実行するのかを Runtime が知っておく必要があります。以下の処理種別があります。
CPU_INTENSIVE: 複雑で時間を要する計算や変換など、負荷の大きな処理です。SDK が CPU_INTENSIVE
種別を推定することはありません。「実行種別の指定」を参照してください。
CPU_LITE: メッセージの受け渡し、絞り込み、ルーティング、非ブロック I/O など、スレッドをブロックしたり CPU に負荷をかけたりしない処理です。
BLOCKING: ブロック I/O 操作、Thread.sleep(long)
、Lock.lock()
など、処理中に現在のスレッドをブロックする処理です。この種別には Thread.sleep
が含まれますが、これを使用することは避けた方がよいでしょう。