Recommended
PDF
分散トレーシング技術について(Open tracingやjaeger)
PPTX
PDF
オススメのJavaログ管理手法 ~コンテナ編~(Open Source Conference 2022 Online/Spring 発表資料)
PPTX
PDF
PPTX
どうやって決める?kubernetesでのシークレット管理方法(Cloud Native Days 2020 発表資料)
PPTX
ODP
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
PPTX
PPTX
Kubernetesでの性能解析 ~なんとなく遅いからの脱却~(Kubernetes Meetup Tokyo #33 発表資料)
PDF
PDF
At least onceってぶっちゃけ問題の先送りだったよね #kafkajp
PPTX
世界一わかりやすいClean Architecture
PDF
速習!論理レプリケーション ~基礎から最新動向まで~(PostgreSQL Conference Japan 2022 発表資料)
PDF
PDF
PDF
乗っ取れコンテナ!!開発者から見たコンテナセキュリティの考え方(CloudNative Days Tokyo 2021 発表資料)
PDF
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
PPTX
Spring 5に備えるリアクティブプログラミング入門
PDF
PDF
Javaはどのように動くのか~スライドでわかるJVMの仕組み
PDF
ストリーム処理を支えるキューイングシステムの選び方
PDF
PDF
CSI Driverを開発し自社プライベートクラウドにより適した安全なKubernetes Secrets管理を実現した話
PDF
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
PPTX
BuildKitによる高速でセキュアなイメージビルド
PDF
PDF
PPTX
日本 Java ユーザーグループ JJUG CCC 2015 Fall by ソラコム 片山
PPTX
Javaにおけるネイティブコード連携の各種手法の紹介
More Related Content
PDF
分散トレーシング技術について(Open tracingやjaeger)
PPTX
PDF
オススメのJavaログ管理手法 ~コンテナ編~(Open Source Conference 2022 Online/Spring 発表資料)
PPTX
PDF
PPTX
どうやって決める?kubernetesでのシークレット管理方法(Cloud Native Days 2020 発表資料)
PPTX
ODP
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
What's hot
PPTX
PPTX
Kubernetesでの性能解析 ~なんとなく遅いからの脱却~(Kubernetes Meetup Tokyo #33 発表資料)
PDF
PDF
At least onceってぶっちゃけ問題の先送りだったよね #kafkajp
PPTX
世界一わかりやすいClean Architecture
PDF
速習!論理レプリケーション ~基礎から最新動向まで~(PostgreSQL Conference Japan 2022 発表資料)
PDF
PDF
PDF
乗っ取れコンテナ!!開発者から見たコンテナセキュリティの考え方(CloudNative Days Tokyo 2021 発表資料)
PDF
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
PPTX
Spring 5に備えるリアクティブプログラミング入門
PDF
PDF
Javaはどのように動くのか~スライドでわかるJVMの仕組み
PDF
ストリーム処理を支えるキューイングシステムの選び方
PDF
PDF
CSI Driverを開発し自社プライベートクラウドにより適した安全なKubernetes Secrets管理を実現した話
PDF
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
PPTX
BuildKitによる高速でセキュアなイメージビルド
PDF
PDF
Viewers also liked
PPTX
日本 Java ユーザーグループ JJUG CCC 2015 Fall by ソラコム 片山
PPTX
Javaにおけるネイティブコード連携の各種手法の紹介
PDF
よくある業務開発の自動化事情 #jjug_ccc #ccc_cd3
PDF
【こっそり始める】Javaプログラマコーディングマイグレーション
PDF
Java8 Stream APIとApache SparkとAsakusa Frameworkの類似点・相違点
PDF
プログラム初心者がWebサービスをリリースして運営するまで
PDF
Real world machine learning with Java for Fumankaitori.com
PPT
PPTX
Java8移行から始めた技術的負債との戦い(jjug ccc 2015 fall)
PDF
マイクロサービスアーキテクチャ - アーキテクチャ設計の歴史を背景に
PDF
タイムマシン採用:明日のエンタープライズJavaの世界を予想する -Java EE7/クラウド/Docker/etc.-
PDF
PPTX
PDF
Spring Framework 5.0による Reactive Web Application #JavaDayTokyo
PDF
PDF
VMの歩む道。 Dalvik、ART、そしてJava VM
PDF
Jjugccc2017spring-postgres-ccc_m1
PPTX
Kotlin is charming; The reasons Java engineers should start Kotlin.
PDF
Java8移行は怖くない~エンタープライズ案件でのJava8移行事例~
PPTX
U-NEXT学生インターン、過激なJavaの学び方と過激な要求
Similar to Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3
PDF
Reactive Systems と Back Pressure
PDF
SpringOne Platform 2016 報告会「A Lite Rx API for the JVM」/ 井口 貝 @ SmartNews, Inc.
PDF
Typesafe Reactive Platformで作るReactive System
PPTX
PDF
Why Reactive Matters #ScalaMatsuri
PDF
Typesafe Reactive Platformで作るReactive System入門
PDF
なぜリアクティブは重要か #ScalaMatsuri
PDF
PPTX
PDF
SpringOne 2016 報告 Reactive APIの設計・実装・使用
PDF
Reactive Extensionsはじめました
PDF
PDF
PDF
Observable Everywhere - Rxの原則とUniRxにみるデータソースの見つけ方
PPTX
Spring I/O 2019 報告 Spring Frameworkのロードマップと5.2の新機能
PDF
PPTX
ReactiveUI を使った表計算っぽいWPFアプリケーションで Reactiveプログラミング の練習をした話
PDF
IntelliJ IDEAとKotlinで作るSpring 5アプリケーション
PPTX
PDF
FRP - Functional Reactive Programming
More from Toshiaki Maki
PDF
From Spring Boot 2.2 to Spring Boot 2.3 #jsug
PDF
Concourse x Spinnaker #concourse_tokyo
PDF
Serverless with Spring Cloud Function, Knative and riff #SpringOneTour #s1t
PDF
決済システムの内製化への旅 - SpringとPCFで作るクラウドネイティブなシステム開発 #jsug #sf_h1
PDF
Spring Boot Actuator 2.0 & Micrometer #jjug_ccc #ccc_a1
PDF
Spring Boot Actuator 2.0 & Micrometer
PDF
Open Service Broker APIとKubernetes Service Catalog #k8sjp
PDF
Spring Cloud Function & Project riff #jsug
PDF
Introduction to Spring WebFlux #jsug #sf_a1
PDF
BOSH / CF Deployment in modern ways #cf_tokyo
PDF
Why PCF is the best platform for Spring Boot
PDF
Zipkin Components #zipkin_jp
PPTX
マイクロサービスに必要な技術要素はすべてSpring Cloudにある #DO07
PDF
実例で学ぶ、明日から使えるSpring Boot Tips #jsug
PDF
PDF
Event Driven Microservices with Spring Cloud Stream #jjug_ccc #ccc_ab3
PDF
Managing your Docker image continuously with Concourse CI
PDF
Data Microservices with Spring Cloud Stream, Task, and Data Flow #jsug #spri...
PDF
Short Lived Tasks in Cloud Foundry #cfdtokyo
PDF
今すぐ始めるCloud Foundry #hackt #hackt_k
Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. Blocking is evil
• ブロッキングコードは並列化の妨げ
• 2大ブロッキング
• リクエストの受信待ち/レスポンス
の送信待ち
• DBクエリの結果待ち
InputStream
OutputStream
JDBC
14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. データフロー
A
B 2
+ C
A, Bの変更に伴い
Cも変わるhttps://speakerdeck.com/okapies/reactive-streams-ru-men-number-jjug
26. 27. 28. 29. 30. 31. 32. 33. 命令型
int A = 3;
int B = 3;
int C = A + B * 2; // 9
B = 1;
A, Bが変更されても
Cは変わらない
34. JavaFXの場合
@FXML
Spinner<Integer> valueA;
@FXML
Spinner<Integer> valueB;
@FXML
Label valueC;
private void bind() {
IntegerProperty a = new SimpleIntegerProperty(0);
IntegerProperty b = new SimpleIntegerProperty(0);
NumberBinding c = a.add(b.multiply(2)); // c = a + 2 * b
a.bind(this.valueA.valueProperty());
b.bind(this.valueB.valueProperty());
valueC.textProperty().bind(c.asString());
}
http://aoe-tk.hatenablog.com/entry/2015/07/12/173402
37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. public interface Publisher<T> {
public void subscribe(Subscriber<? super T> s);
}
public interface Subscription {
public void request(long n);
public void cancel();
}
public interface Subscriber<T> {
public void onSubscribe(Subscription s);
public void onNext(T t);
public void onError(Throwable t);
public void onComplete();
}
public interface Processor<T, R> extends
Publisher<T>, Subscriber<R> {}
org.reactivestreams
49. public interface Publisher<T> {
public void subscribe(Subscriber<? super T> s);
}
public interface Subscription {
public void request(long n);
public void cancel();
}
public interface Subscriber<T> {
public void onSubscribe(Subscription s);
public void onNext(T t);
public void onError(Throwable t);
public void onComplete();
}
public interface Processor<T, R> extends
Publisher<T>, Subscriber<R> {}
org.reactivestreams
BackPressure
50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 実装例 (Publisher)
public class IntPublisher implements Publisher<Integer> {
@Override
public void subscribe(Subscriber<? super Integer> s) {
s.onSubscribe(new Subscription() {
Iterator<Integer> it = IntStream.range(0, 10)
.boxed().iterator();
@Override
public void request(long n) {
for (int i = 0; i < n; i++) {
if (it.hasNext()) {
s.onNext(it.next());
} else {
s.onComplete();
break;
}}}
@Override
public void cancel() {}
});}}
76. 実装例 (Subscriber)public class IntSubscriber implements Subscriber<Integer> {
Subscription subscription;
int req = 1; // AtomicIntegerにすべき
@Override public void onSubscribe(Subscription s) {
subscription = s; s.request(req);
}
@Override public void onNext(Integer integer) {
System.out.println("Next -> " + integer);
if (--req == 0) {
req = new Random().nextInt(10) + 1;
subscription.request(req);
}
}
@Override public void onError(Throwable t) { /**/ }
@Override public void onComplete() {
System.out.println("Complete!");
}
}
77. 使用例
Publisher<Integer> publisher = new IntPublisher();
Subscriber<Integer> subscriber = new IntSubscriber();
publisher.subscribe(subscriber);
// Next -> 1
// Next -> 2
// Next -> 3
// Next -> 4
// Next -> 5
// Next -> 6
// Next -> 7
// Next -> 8
// Next -> 9
// Next -> 10
// Complete!
78. 使用例
Publisher<Integer> publisher = new IntPublisher();
Subscriber<Integer> subscriber = new IntSubscriber();
publisher.subscribe(subscriber);
// Next -> 1
// Next -> 2
// Next -> 3
// Next -> 4
// Next -> 5
// Next -> 6
// Next -> 7
// Next -> 8
// Next -> 9
// Next -> 10
// Complete!
IntPublisher/IntSubscriberは
インターフェースを実装しているだけ
で、実は仕様を満たしていない
(TCKを通らない)
79. Hot / Cold
• Hot Stream
• ずっと続いていて途中から見はじめるもの
• 株価情報、タイムライン、マウスイベント、タイマー
イベント、WebSocket、Server-Sent Events、メッ
セージキュー
• Cold Stream
• 再現可能で、最初から最後まで見れるもの
• 配列・リスト、ファイル、データベース、計算結果
(Future)
80. 81. 82. 実装データアクセスライブラリ
• MongoDB (公式)
• Apache Kafka
• Rabbit MQ (Scalaのみ)
• Slick3 (Scala)
• CouchDB (RxJava only)
• PostgreSQL (RxJava only、開発中?)
• Spark (検討中? SPARK-10420)
• など
83. 84. MongoDB
MongoClient client = MongoClients.create(
"mongodb://localhost");
MongoDatabase db = client.getDatabase("mydb");
MongoCollection<Document> collection =
db.getCollection("test");
// Insert
Document doc = new Document("message", "Hello!");
Publisher<Success> insert = collection.insertOne(doc);
insert.subscribe(new PrintSubscriber<>("result=%s"));
// Select
Publisher<Document> docs = collection.find();
docs.subscribe(new PrintDocumentSubscriber());
85. MongoDB
// Bulk Operation
PrintSubscriber<BulkWriteResult> subscriber
= new PrintSubscriber<>("Bulk write results: %s");
collection.bulkWrite(Arrays.asList(
new InsertOneModel<>(new Document("_id", 4)),
new InsertOneModel<>(new Document("_id", 5)),
new InsertOneModel<>(new Document("_id", 6)),
new UpdateOneModel<>(new Document("_id", 1),
new Document("$set", new Document("x", 2))),
new DeleteOneModel<>(new Document("_id", 2)),
new ReplaceOneModel<>(new Document("_id", 3),
new Document("_id", 3).append("x",4))))
.subscribe(subscriber);
86. 87. Apache Kafka
ReactiveKafka kafka = new ReactiveKafka();
ActorSystem system =
ActorSystem.create("ReactiveKafka");
Publisher<MessageAndMetadata<byte[], String>> topicA
= kafka.consume(new PropertiesBuilder.Consumer(
broker, zk, "topicA","group", decoder)
.build(), system);
topicA.subscribe(subscriber);
88. 89. PostgreSQL
Db db = new ConnectionPoolBuilder()
.hostname("localhost").port(5432).database("demo")
.username("postgres").password("")
.poolSize(20).build();
// RxJava's Observable
Observable<Row> result =
db.queryRows("select id,value from demo");
result.subscribe(...);
// to Reactive Streams
Publisher<Row> publisher =
RxReactiveStreams.toPublisher(result);
publisher.subscribe(...);
90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. Reactor
• Pivotal社が開発
• LMAX Disruptorの高性能なRing Bufferを使用している
• Spring Frameworkの一部の機能で使用されている
• Reactive Streamsの
Publisher + Composable API → reactor.rx.Stream
Streams.just('a', 'b', 'c')
.take(2)
.map(Character::toUpperCase)
.consume(System.out::print); // AB
105. 106. 107. Reactor Streamsへの変換
import reactor.rx.Stream;
import reactor.rx.Streams;
// Streamの要素を直接指定(Cold)
Stream<String> stream = Streams.just("a", "b");
// T[]やIterable<T>からStream<T>への変換(Cold)
Stream<String> stream = Streams.from(value);
// Publisher<T>からStream<T>へ変換
Stream<String> stream = Streams.wrap(publisher);
108. 109. Reactive Streamsの仕様を
簡単に満たすヘルパー
List<Integer> items = /* ... */;
Publisher<Integer> publisher =
PublisherFactory.forEach((subscriber) -> {
Iterator<Integer> iterator
= subscriber.context();
if (iterator.hasNext()) {
subscriber.onNext(iterator.next());
} else {
subscriber.onComplete();
}
}, subscriber -> items.iterator());
110. 111. Kafka + Reactorで足し算
Publisher<MessageAndMetadata<byte[], String>> topicA =
kafka.consume(new PropertiesBuilder.Consumer(
broker, zk, "a", "group", decoder)
.build(), system);
Publisher<MessageAndMetadata<byte[], String>> topicB =
kafka.consume(new PropertiesBuilder.Consumer(
broker, zk, "b", "group", decoder)
.build(), system);
Publisher<Integer> a = Streams.wrap(topicA)
.map(x -> Integer.valueOf(x.message()));
Publisher<Integer> bx2 = Streams.wrap(topicB)
.map(x -> Integer.valueOf(x.message()))
.map(x -> x * 2);
Streams.combineLatest(a, bx2, tpl -> tpl.getT1()+tpl.getT2())
.consume(c -> {
System.out.println("a + b * 2 = " + c);
});
112. Kafka + Reactorで足し算
$ echo '3' | kafkacat -P -t a -b localhost:9092
$ echo '3' | kafkacat -P -t b -b localhost:9092
$ echo '1' | kafkacat -P -t b -b localhost:9092
a + b * 2 = 5
a + b * 2 = 9
113. Reactorでコナミコマンド
// Create a "Hot" stream
Broadcaster<String> stream
= Broadcaster.create(Environment.get());
stream.filter(x -> x.length() == 1)
.buffer(10, 1) // 10イベント分を1つずらしでまとめる
.map(s ->
"↑".equals(s.get(0)) && "↑".equals(s.get(1)) &&
""".equals(s.get(2)) && """.equals(s.get(3)) &&
"←".equals(s.get(4)) && "#".equals(s.get(5)) &&
"←".equals(s.get(6)) && "#".equals(s.get(7)) &&
"A".equals(s.get(8)) && "B".equals(s.get(9)))
.consume(isKonami -> {
System.out.println(isKonami ? "Konami!" : "NG");
});
114. 115. 外部サービス呼び出し (Blocking)
public interface LinkedInService {
List<String> findUsers(String keyword);
LinkedInProfile getConnection(String id);
}
public interface TwitterService {
TwitterProfile getUserProfile(String id);
}
public interface FacebookService {
FacebookProfile getUserProfile(String id);
}
116. 外部サービス呼び出し (NonBlocking)
public interface LinkedInService {
Stream<String> findUsers(String keyword);
Stream<LinkedInProfile> getConnection(String id);
}
public interface TwitterService {
Stream<TwitterProfile> getUserProfile(String id);
}
public interface FacebookService {
Stream<FacebookProfile> getUserProfile(String id);
}
117. 118. Reactor or RxJava ?
Reactor RxJava
• Reactive Streamsを
Nativeサポート
• Spring連携
• Reactive Extensions
のサブセット
• Reactive Exensionsを
フルセットでサポート
• 他言語対応
• Reactive Streamsはア
ダプター経由
119. 120. Reactive Streamsのメリット
• 非同期サポートライブラリを作りやすい
• async-db-driver
• Publisher/Subscriberのみを使ったコアライブラリ
• async-db-driver-reactor
• ReactorのStreamにラップ
• async-db-driver-rxjava
• RxJavaのObservableにラップ
• ...
https://github.com/ReactiveX/RxJava/wiki/Reactive-Streams#recommended-approach
121. package com.example.db.driver;
import org.reactivestreams.Publisher;
public class Database {
public Publisher getValue(String key) { /* ... */ }
}
package com.example.db.driver.reactor;
public class Database {
public Stream getValue(String key) {
return Streams.wrap(coreDatabase.getValue(key));
}
}
package com.example.db.driver.rxjava;
public class Database {
public Observable getValue(String key) {
return RxReactiveStreams.toObservable(
coreDatabase.getValue(key));
}
}
RxJava用
Reactor用
Core API
122. 123. 124. 125. 126. Spring 5
• Q4 2016
• JDK 9サポート
• Java 8がベースライン
• HTTP 2対応
• Reactive対応
• JUnit5対応
127. Spring 5
• Q4 2016
• JDK 9サポート
• Java 8がベースライン
• HTTP 2対応
• Reactive対応
• JUnit5対応
128. 129. 130. 131. 132. 133. Servlet 3.0
非同期処理サポート
void doGet(req, res) {
OutputStream out = res.getOutputStream();
AsyncContext ctx = req.startAsync();
doAsyncREST(req).thenAccept(json -> {
out.write(json);
ctx.complete();
});
}
http://www.slideshare.net/SimoneBordet/servlet-31-async-io
134. Servlet 3.0
非同期処理サポート
void doGet(req, res) {
OutputStream out = res.getOutputStream();
AsyncContext ctx = req.startAsync();
doAsyncREST(req).thenAccept(json -> {
out.write(json); // Blocking!!
ctx.complete();
});
}
http://www.slideshare.net/SimoneBordet/servlet-31-async-io
135. 136. void doGet(req, res) {
OutputStream out = res.getOutputStream();
AsyncContext ctx = req.startAsync();
out.setWriteListener(new WriteListener() {
void onWritePossible() {
while (on.isReady()) {
// ...
ctx.complete();
}
}
});
}
http://www.slideshare.net/SimoneBordet/servlet-31-async-io
137. Hello Worldサーブレット
@WebServlet(urlPatterns = "/hello"
, asyncSupported = true)
public class HelloServlet extends HttpServlet {
@Override
public void service(HttpServletRequest req,
HttpServletResponse resp) {
AsyncContext ctx = req.startAsync(req, resp);
ServletInputStream input = req.getInputStream();
ReadListener readListener =
new ReadListenerImpl(input, resp, ctx);
input.setReadListener(readListener);
}
138. class ReadListenerImpl implements ReadListener {
// ...
private final StringBuilder sb = new StringBuilder();
public ReadListenerImpl(ServletInputStream input,
HttpServletResponse resp, AsyncContext ctx) {/* ... */}
public void onDataAvailable() throws IOException {
int len = 0; byte b[] = new byte[1024];
while (input.isReady() && !input.isFinished()
&& (len = input.read(b)) != -1) {
sb.append(new String(b, 0, len));
}
}
public void onAllDataRead() throws IOException {
ServletOutputStream output = resp.getOutputStream();
WriteListener writeListener =
new WriteListenerImpl(output, ctx);
output.setWriteListener(writeListener);
}
public void onError(Throwable th) {
ctx.complete(); th.printStackTrace();
}
}
139. class WriteListenerImpl implements WriteListener {
private final ServletOutputStream output;
private final AsyncContext ctx;
public WriteListenerImpl(ServletOutputStream output,
AsyncContext ctx) {
this.output = output;
this.ctx = ctx;
}
public void onWritePossible() throws IOException {
output.print("Hello World!");
output.flush();
ctx.complete();
}
public void onError(Throwable th) {
th.printStackTrace();
}
}
140. 141. 142. 143. 144. Spring Reactive
• Spring 5のReactive対応向け実験プロジェクト
• 開発メンバー
• Rossen Stoyanchev (Spring MVC)
• Stephane Maldini (Reactor, Reactive Streams)
• Arjen Poutsma (MVCのREST対応, Spring WS)
• Sébastien Deleuze (MVCのScriptEngine対応)
• Brian Clozel (MVCの静的リソースハンドリング対応)
https://github.com/spring-projects/spring-reactive
145. 146. 147. Instead of ...
interface ServerHttpRequest extends HttpRequest {
InputStream getBody();
}
interface ServerHttpResponse extends HttpMessage {
OutputStream getBody();
}
148. 149. 150. 151. 152. 153. 154. 155. 156. 157. 158. 159. 160. 161. 162. 163. 164. java.util.concurrent.Flow
• Reactive StreamsがJDK 9に入ります
• Flow.Publisher
• Flow.Subscriber
• Flow.Subscription
• Flow.Processor
• http://openjdk.java.net/jeps/266
• http://gee.cs.oswego.edu/dl/jsr166/dist/docs/java/util/concurrent/Flow.html
@author Doug Lea
165. j.u.c.Flow <-> Reactive Streams
• ブリッジ作成を検討中
• https://github.com/reactive-streams/reactive-streams-jvm/issues/294
import java.util.concurrent.Flow;
import org.reactivestreams.Publisher;
// j.u.c.Flow -> Reactive Streams
Publisher<T> toReactive(Flow.Publisher<>T);
// Reactive Streams -> j.u.c.Flow
Flow.Publisher<T> toFlow(Publisher<T>);
166. Servlet 4
• HTTP2とReactive Streams (Back Pressure)の
連携案
• JDK9にj.u.c.Flowが入ったため、御蔵入りの模様
https://java.net/projects/servlet-spec/lists/jsr369-experts/archive/2015-08/message/1
167. まとめ
• Blocking ==💴な時代がきている
• Non-Blocking化を助けるReactiveなパラダイム
• 非同期ストリーム標準 Reactive Streams
• イベントストリームの変換・合成 Reactive
Extensions
• Reactive Webアプリケーション向けフレームワー
クSpring ReactiveがSpring 5に向けて開発中
168. まとめ
• Blocking ==💴な時代がきている
• Non-Blocking化を助けるReactiveなパラダイム
• 非同期ストリーム標準 Reactive Streams
• イベントストリームの変換・合成 Reactive
Extensions
• Reactive Webアプリケーション向けフレームワー
クSpring ReactiveがSpring 5に向けて開発中
Spring Framework
を使っていきましょう