SlideShare a Scribd company logo
1 of 11
1
Reactive Streams に基づく
非同期処理プログラミング
〜 Reactor を使ってみた
Akihiro Kitada
2018/4/27
2
Reactive Streams とは?
みたいな議論はさておき、
Reactive Streams の実装
の一つである Reactor を
使って、Java で非同期処
理プログラミングをしてみ
たという話。
Reactive Streams に基づく非同期処理考察(1/2)
 処理対象データは、ストリームとして任意の量・タ
イミングで投入される – Reactor で言うところの
“hot-stream” の考え方。
 処理対象データは、I/O レベルの “non-blocking” の
考え方に沿って、システムリソース節約のため、多
くの待機スレッドでデータ待ちをするのではなく、
必要に応じて、できるだけ少ないスレッドで処理す
る。
3
Reactive Streams に基づく非同期処理考察(2/2)
 前段スレッド(Publisher)が処理対象データを生成ないし
受信する。後段スレッド(Subscriber)は 、処理対象データ
のオーバーフローを防ぐため、“back-pressure” の考え方に
基づき、必要な量のデータだけを前段側に要求し逐次処理
する。
4
想定されるアーキテクチャー
5
Publisher
①対象処理データが、
hot-stream として、
non-blocking に投入
される。
Subscriber
②私が処理出来る分
量だけ、データスト
リームのフローコン
トロールしてくださ
い! - back-pressure
③了解!データストリームのフ
ローコントロールしまーす!消費
できる分だけのデータをリクエス
トしてください。 - back-
pressure
④逐次データ処理
実装
6
Publisher Subscriber
ここでは、non-blocking と back-pressure の考え
方に基づく非同期処理を、Reactive Streams の
Java 実装の一つである Ractor を使用して実現
します。
複数データを投入・処理するため
Flux を使用し、非同期処理を行うた
め TopicProcessor を使用します。
オプションで、back-pressure 動作
をカスタマイズするため、
BaseSubscriber を適用します。
7
では実際に、コーディング
してみるよ!
準備 – データ型の定義
8
package quitada;
public class KeyValuePair {
private String key;
private String value;
public KeyValuePair() { }
public KeyValuePair(String key, String value) {
this.key = key;
this.value = value;
}
public String getValue() { return value; }
public String getKey() { return key; }
public void setKey(String key) { this.key = key; }
public void setValue(String value) { this.value = value; }
}
なんでも良いのですが、ここでは
キー・バリュー・ペアなデータ型
を定義してみました。
TopicProcessor<KeyValuePair> hotSource = TopicProcessor.create();
Flux<KeyValuePair> hotFlux = hotSource.publish().autoConnect();
hotFlux.subscribe(keyValuePair -> {
// KeyValuePair 型のデータに対する何かの処理を記述
:
});
for (int i = 1; i <= 1000 ; i++) {
String value = Integer.toString(i);
hotSource.onNext(new KeyValuePair("k" + value, "v" + value));
}
僕のリアクティブな非同期処理実装
9
データ処理を非同期に行うため、
hot-stream なデータソースを
TopicProcessor 使って作成します。
Flux を使って Publisher と
Subscriber を準備します。
受信したデータの処理ロジックを
登録します。
データストリームとして、データ
投入します - Flux#onNext([処理対
象データ])。これにより、データ
投入処理とは非同期に逐次登録し
た処理ロジックが実行されます。
[オプション] back-pressure 動作のカスタマイズ
10
TopicProcessor<KeyValuePair> hotSource = TopicProcessor.create();
Flux<KeyValuePair> hotFlux = hotSource.publish().autoConnect();
BaseSubscriber<KeyValuePair> subscriber = new BaseSubscriber<KeyValuePair>() {
protected void hookOnSubscribe(Subscription subscription) {
request(1);
}
protected void hookOnError(Throwable throwable) {
throwable.printStackTrace();
}
protected void hookOnComplete() { }
protected void hookOnNext(KeyValuePair keyValuePair) {
// KeyValuePair 型データに対する何らかの処理を記述
:
request(1);
}
};
hotFlux.subscribe(subscriber);
for (int i = 1; i <= 1000 ; i++) {
String value = Integer.toString(i);
hotSource.onNext(new KeyValuePair("k" + value, "v" + value));
}
BaseSubscriber を使って、back-
pressure 動作をカスタマイズでき
ます(デフォルトでは、登録した
ロジックが実行し終わったら適宜
要求するような動作)。
BaseSubscriber#request([要求
データ数]) を任意のタイミングで
実行することで、フローコント
ロールを行います。この例では、
ロジック登録時と、ロジック実行
完了時に 1 つデータを要求すると
いう単純なロジックで、デフォル
トの挙動と同じです。データ要求
しないと、当然のことながら処理
が止まります。
11
Reactor を使って、
Reactive Streams に基づ
く非同期処理を実装してみ
ました!
コード量もそんなに多くな
くて、お手軽に実装できま
すね!

More Related Content

What's hot

What's hot (20)

Linqの速度測ってみた
Linqの速度測ってみたLinqの速度測ってみた
Linqの速度測ってみた
 
トランザクションをSerializableにする4つの方法
トランザクションをSerializableにする4つの方法トランザクションをSerializableにする4つの方法
トランザクションをSerializableにする4つの方法
 
地理分散DBについて
地理分散DBについて地理分散DBについて
地理分散DBについて
 
Scalar DL Technical Overview
Scalar DL Technical OverviewScalar DL Technical Overview
Scalar DL Technical Overview
 
RL4J で始める深層強化学習
RL4J で始める深層強化学習RL4J で始める深層強化学習
RL4J で始める深層強化学習
 
Ethernetの受信処理
Ethernetの受信処理Ethernetの受信処理
Ethernetの受信処理
 
トランザクション入門
トランザクション入門 トランザクション入門
トランザクション入門
 
MVSR Schedulerを作るための指針
MVSR Schedulerを作るための指針MVSR Schedulerを作るための指針
MVSR Schedulerを作るための指針
 
Spring 5に備えるリアクティブプログラミング入門
Spring 5に備えるリアクティブプログラミング入門Spring 5に備えるリアクティブプログラミング入門
Spring 5に備えるリアクティブプログラミング入門
 
マイクロサービスにおける 非同期アーキテクチャ
マイクロサービスにおける非同期アーキテクチャマイクロサービスにおける非同期アーキテクチャ
マイクロサービスにおける 非同期アーキテクチャ
 
Cognitive Complexity でコードの複雑さを定量的に計測しよう
Cognitive Complexity でコードの複雑さを定量的に計測しようCognitive Complexity でコードの複雑さを定量的に計測しよう
Cognitive Complexity でコードの複雑さを定量的に計測しよう
 
Elmで始めるFunctional Reactive Programming
Elmで始めるFunctional Reactive Programming Elmで始めるFunctional Reactive Programming
Elmで始めるFunctional Reactive Programming
 
GraalVM の概要と、Native Image 化によるSpring Boot 爆速化の夢
GraalVM の概要と、Native Image 化によるSpring Boot 爆速化の夢GraalVM の概要と、Native Image 化によるSpring Boot 爆速化の夢
GraalVM の概要と、Native Image 化によるSpring Boot 爆速化の夢
 
JVMのGCアルゴリズムとチューニング
JVMのGCアルゴリズムとチューニングJVMのGCアルゴリズムとチューニング
JVMのGCアルゴリズムとチューニング
 
MyRocks introduction and production deployment
MyRocks introduction and production deploymentMyRocks introduction and production deployment
MyRocks introduction and production deployment
 
YJTC18 A-1 データセンタネットワークの取り組み
YJTC18 A-1 データセンタネットワークの取り組みYJTC18 A-1 データセンタネットワークの取り組み
YJTC18 A-1 データセンタネットワークの取り組み
 
Apache Hadoop HDFSの最新機能の紹介(2018)#dbts2018
Apache Hadoop HDFSの最新機能の紹介(2018)#dbts2018Apache Hadoop HDFSの最新機能の紹介(2018)#dbts2018
Apache Hadoop HDFSの最新機能の紹介(2018)#dbts2018
 
不揮発性メモリ(PMEM)を利用したストレージエンジンの話 #mysql_jp #myna会 #yahoo #mysql #pmem #不揮発性メモリ
不揮発性メモリ(PMEM)を利用したストレージエンジンの話  #mysql_jp #myna会 #yahoo #mysql #pmem #不揮発性メモリ不揮発性メモリ(PMEM)を利用したストレージエンジンの話  #mysql_jp #myna会 #yahoo #mysql #pmem #不揮発性メモリ
不揮発性メモリ(PMEM)を利用したストレージエンジンの話 #mysql_jp #myna会 #yahoo #mysql #pmem #不揮発性メモリ
 
A critique of ansi sql isolation levels 解説公開用
A critique of ansi sql isolation levels 解説公開用A critique of ansi sql isolation levels 解説公開用
A critique of ansi sql isolation levels 解説公開用
 
20221226_TITECH_lecture_ishizaki_public.pdf
20221226_TITECH_lecture_ishizaki_public.pdf20221226_TITECH_lecture_ishizaki_public.pdf
20221226_TITECH_lecture_ishizaki_public.pdf
 

More from Akihiro Kitada

More from Akihiro Kitada (13)

How to configure the cluster based on Multi-site (WAN) configuration
How to configure the clusterbased on Multi-site (WAN) configurationHow to configure the clusterbased on Multi-site (WAN) configuration
How to configure the cluster based on Multi-site (WAN) configuration
 
〜僕の初めてのリアクティブプログラミング Reactor を使ってリアクティブに昇龍拳を繰り出してみた!
〜僕の初めてのリアクティブプログラミング Reactor を使ってリアクティブに昇龍拳を繰り出してみた!〜僕の初めてのリアクティブプログラミング Reactor を使ってリアクティブに昇龍拳を繰り出してみた!
〜僕の初めてのリアクティブプログラミング Reactor を使ってリアクティブに昇龍拳を繰り出してみた!
 
【古いスライド】〜僕の初めてのリアクティブプログラミング Reactor を使ってリアクティブに昇龍拳を繰り出してみた!
【古いスライド】〜僕の初めてのリアクティブプログラミング Reactor を使ってリアクティブに昇龍拳を繰り出してみた!【古いスライド】〜僕の初めてのリアクティブプログラミング Reactor を使ってリアクティブに昇龍拳を繰り出してみた!
【古いスライド】〜僕の初めてのリアクティブプログラミング Reactor を使ってリアクティブに昇龍拳を繰り出してみた!
 
Apache Geode の Apache Lucene Integration を試してみた
Apache Geode の Apache Lucene Integration を試してみたApache Geode の Apache Lucene Integration を試してみた
Apache Geode の Apache Lucene Integration を試してみた
 
Apache Calcite の Apache Geode Adapter を弄った
Apache Calcite の Apache Geode Adapter を弄ったApache Calcite の Apache Geode Adapter を弄った
Apache Calcite の Apache Geode Adapter を弄った
 
Grafana を使った Apache Geode クラスター監視
Grafana を使った Apache Geode クラスター監視Grafana を使った Apache Geode クラスター監視
Grafana を使った Apache Geode クラスター監視
 
〜Apache Geode 入門 Multi-site(WAN)構成による クラスター連携
〜Apache Geode 入門 Multi-site(WAN)構成によるクラスター連携〜Apache Geode 入門 Multi-site(WAN)構成によるクラスター連携
〜Apache Geode 入門 Multi-site(WAN)構成による クラスター連携
 
My first reactive programming - To deliver a deathblow “Shoryuken” with using...
My first reactive programming - To deliver a deathblow “Shoryuken” with using...My first reactive programming - To deliver a deathblow “Shoryuken” with using...
My first reactive programming - To deliver a deathblow “Shoryuken” with using...
 
【古いスライド】〜僕の初めてのリアクティブプログラミング Reactor を使ってリアクティブに昇龍拳を繰り出してみた!
【古いスライド】〜僕の初めてのリアクティブプログラミング Reactor を使ってリアクティブに昇龍拳を繰り出してみた!【古いスライド】〜僕の初めてのリアクティブプログラミング Reactor を使ってリアクティブに昇龍拳を繰り出してみた!
【古いスライド】〜僕の初めてのリアクティブプログラミング Reactor を使ってリアクティブに昇龍拳を繰り出してみた!
 
〜Apache Geode 入門 gfsh によるクラスター構築・管理
〜Apache Geode 入門 gfsh によるクラスター構築・管理〜Apache Geode 入門 gfsh によるクラスター構築・管理
〜Apache Geode 入門 gfsh によるクラスター構築・管理
 
はじめての Cloud Foundry: .NET アプリケーションのはじめ方
はじめての Cloud Foundry: .NET アプリケーションのはじめ方はじめての Cloud Foundry: .NET アプリケーションのはじめ方
はじめての Cloud Foundry: .NET アプリケーションのはじめ方
 
Apache Geode で始める Spring Data Gemfire
Apache Geode で始めるSpring Data GemfireApache Geode で始めるSpring Data Gemfire
Apache Geode で始める Spring Data Gemfire
 
Reactor によるデータインジェスチョン
Reactor によるデータインジェスチョンReactor によるデータインジェスチョン
Reactor によるデータインジェスチョン
 

Reactive Streams に基づく非同期処理プログラミング 〜 Reactor を使ってみた

  • 1. 1 Reactive Streams に基づく 非同期処理プログラミング 〜 Reactor を使ってみた Akihiro Kitada 2018/4/27
  • 2. 2 Reactive Streams とは? みたいな議論はさておき、 Reactive Streams の実装 の一つである Reactor を 使って、Java で非同期処 理プログラミングをしてみ たという話。
  • 3. Reactive Streams に基づく非同期処理考察(1/2)  処理対象データは、ストリームとして任意の量・タ イミングで投入される – Reactor で言うところの “hot-stream” の考え方。  処理対象データは、I/O レベルの “non-blocking” の 考え方に沿って、システムリソース節約のため、多 くの待機スレッドでデータ待ちをするのではなく、 必要に応じて、できるだけ少ないスレッドで処理す る。 3
  • 4. Reactive Streams に基づく非同期処理考察(2/2)  前段スレッド(Publisher)が処理対象データを生成ないし 受信する。後段スレッド(Subscriber)は 、処理対象データ のオーバーフローを防ぐため、“back-pressure” の考え方に 基づき、必要な量のデータだけを前段側に要求し逐次処理 する。 4
  • 5. 想定されるアーキテクチャー 5 Publisher ①対象処理データが、 hot-stream として、 non-blocking に投入 される。 Subscriber ②私が処理出来る分 量だけ、データスト リームのフローコン トロールしてくださ い! - back-pressure ③了解!データストリームのフ ローコントロールしまーす!消費 できる分だけのデータをリクエス トしてください。 - back- pressure ④逐次データ処理
  • 6. 実装 6 Publisher Subscriber ここでは、non-blocking と back-pressure の考え 方に基づく非同期処理を、Reactive Streams の Java 実装の一つである Ractor を使用して実現 します。 複数データを投入・処理するため Flux を使用し、非同期処理を行うた め TopicProcessor を使用します。 オプションで、back-pressure 動作 をカスタマイズするため、 BaseSubscriber を適用します。
  • 8. 準備 – データ型の定義 8 package quitada; public class KeyValuePair { private String key; private String value; public KeyValuePair() { } public KeyValuePair(String key, String value) { this.key = key; this.value = value; } public String getValue() { return value; } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public void setValue(String value) { this.value = value; } } なんでも良いのですが、ここでは キー・バリュー・ペアなデータ型 を定義してみました。
  • 9. TopicProcessor<KeyValuePair> hotSource = TopicProcessor.create(); Flux<KeyValuePair> hotFlux = hotSource.publish().autoConnect(); hotFlux.subscribe(keyValuePair -> { // KeyValuePair 型のデータに対する何かの処理を記述 : }); for (int i = 1; i <= 1000 ; i++) { String value = Integer.toString(i); hotSource.onNext(new KeyValuePair("k" + value, "v" + value)); } 僕のリアクティブな非同期処理実装 9 データ処理を非同期に行うため、 hot-stream なデータソースを TopicProcessor 使って作成します。 Flux を使って Publisher と Subscriber を準備します。 受信したデータの処理ロジックを 登録します。 データストリームとして、データ 投入します - Flux#onNext([処理対 象データ])。これにより、データ 投入処理とは非同期に逐次登録し た処理ロジックが実行されます。
  • 10. [オプション] back-pressure 動作のカスタマイズ 10 TopicProcessor<KeyValuePair> hotSource = TopicProcessor.create(); Flux<KeyValuePair> hotFlux = hotSource.publish().autoConnect(); BaseSubscriber<KeyValuePair> subscriber = new BaseSubscriber<KeyValuePair>() { protected void hookOnSubscribe(Subscription subscription) { request(1); } protected void hookOnError(Throwable throwable) { throwable.printStackTrace(); } protected void hookOnComplete() { } protected void hookOnNext(KeyValuePair keyValuePair) { // KeyValuePair 型データに対する何らかの処理を記述 : request(1); } }; hotFlux.subscribe(subscriber); for (int i = 1; i <= 1000 ; i++) { String value = Integer.toString(i); hotSource.onNext(new KeyValuePair("k" + value, "v" + value)); } BaseSubscriber を使って、back- pressure 動作をカスタマイズでき ます(デフォルトでは、登録した ロジックが実行し終わったら適宜 要求するような動作)。 BaseSubscriber#request([要求 データ数]) を任意のタイミングで 実行することで、フローコント ロールを行います。この例では、 ロジック登録時と、ロジック実行 完了時に 1 つデータを要求すると いう単純なロジックで、デフォル トの挙動と同じです。データ要求 しないと、当然のことながら処理 が止まります。
  • 11. 11 Reactor を使って、 Reactive Streams に基づ く非同期処理を実装してみ ました! コード量もそんなに多くな くて、お手軽に実装できま すね!