reactive webアプリケーション - そしてspring 5へ #jjug_ccc #ccc_ef3

168
Reactive Webアプリケーション - そしてSpring 5へ Toshiaki Maki (@making) JJUG CCC 2015 Fall 2015-11-30 #jjug_ccc #ccc_ef3

Upload: toshiaki-maki

Post on 07-Jan-2017

26.362 views

Category:

Technology


3 download

TRANSCRIPT

Page 1: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Reactive Webアプリケーション - そしてSpring 5へ

Toshiaki Maki (@making) JJUG CCC 2015 Fall

2015-11-30 #jjug_ccc #ccc_ef3

Page 2: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

聞いたことあります?• Reactive Programming? • Reactive Manifest? • Reactive Streams? • Reactive Extensions? • Reactive ... ?

Page 3: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

• Reactiveが重要視されてきた背景 • Reactive Streams • Reactive Extensions • Spring 5

今日話すこと

Page 4: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Reactive Extensions(Rx)

Reactive Programming

Reactive Streams Reactor

RxJava

Spring 5

プロラミング パラダイム 仕様(?)

今日話すこと実装

ライブラリSpring

Framework

Page 5: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

元ネタ

http://www.slideshare.net/SpringCentral/reactive-web-applications-53170985

http://www.slideshare.net/SpringCentral/introduction-to-reactive-programming

Page 6: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Reactiveが重要視されてきた背景

Page 7: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Amdalの法則

https://en.wikipedia.org/wiki/Amdahl%27s_law

Page 8: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Amdalの法則

https://en.wikipedia.org/wiki/Amdahl%27s_law

プログラムの並列化による速度の向上は、 プログラムの逐次処理部分によって制限される

Page 9: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Amdalの法則

https://en.wikipedia.org/wiki/Amdahl%27s_law

プログラムの並列化による速度の向上は、 プログラムの逐次処理部分によって制限される

プログラム中の並列実行可能部分が50%だと、いくら並列度を増やしても2倍の性能向上し

か見込めない

Page 10: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

スケールアウト戦略

• メモリばかり消費してCPUに空き…

✦ 大量のスレッドプール

✦ブロッキングI/O

Page 11: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

ブロッキングコードを 書いていては

ハードにいくら金をかけても性能向上に限界がある

Page 12: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Blocking is evil• ブロッキングコードは並列化の妨げ

• 2大ブロッキング

• リクエストの受信待ち/レスポンスの送信待ち

• DBクエリの結果待ち

Page 13: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Blocking is evil• ブロッキングコードは並列化の妨げ

• 2大ブロッキング

• リクエストの受信待ち/レスポンスの送信待ち

• DBクエリの結果待ち

InputStream OutputStream

JDBC

Page 14: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

• IoT

•マイクロサービス

今後のトレンド

Page 15: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

• IoT

•マイクロサービス

低速で膨大な リクエスト が予想される

今後のトレンド

Page 16: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

• IoT

•マイクロサービス

低速で膨大な リクエスト が予想される

今後のトレンド

Blocking == 💴

Page 17: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Non-Blocking!• 命令型ではなくリスナー/コールバックスタイル

• スレッド数を少なく • →省メモリ • →コンテキストスイッチを減らす • →CPUを有効活用

Page 18: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Reactiveプログラミング• 命令型と異なるプログラミングパラダイム

• 連続的なデータをイベントハンドラで処理する

• データフロー(データ同士の関係性)に着目したイベントドリブンなプログラミング

Page 19: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Reactiveプログラミング• 命令型と異なるプログラミングパラダイム

• 連続的なデータをイベントハンドラで処理する

• データフロー(データ同士の関係性)に着目したイベントドリブンなプログラミング

ノンブロッキングコードを書くのに向いている

Page 20: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

最も身近なReactiveプログラミング?

Page 21: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

最も身近なReactiveプログラミング?

Page 22: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

最も身近なReactiveプログラミング?

Page 23: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

最も身近なReactiveプログラミング?

Page 24: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

最も身近なReactiveプログラミング?

A, Bの変更に伴い Cも変わる

Page 25: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

データフロー

A

B ×2

+ C

A, Bの変更に伴い Cも変わるhttps://speakerdeck.com/okapies/reactive-streams-ru-men-number-jjug

Page 26: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

イベントストリーム

x2

+

1  2      4      3

9    6    8    6    5    9

8      4      2  64      2      1  3

A

B

C

Page 27: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

イベントストリーム

x2

+

1  2      4      3

9    6    8    6    5    9

8      4      2  64      2      1  3

A

B

C

Page 28: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

イベントストリーム

x2

+

1  2      4      3

9    6    8    6    5    9

8      4      2  64      2      1  3

A

B

C

Page 29: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

イベントストリーム

x2

+

1  2      4      3

9    6    8    6    5    9

8      4      2  64      2      1  3

A

B

C

Page 30: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

イベントストリーム

x2

+

1  2      4      3

9    6    8    6    5    9

8      4      2  64      2      1  3

A

B

C

Page 31: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

イベントストリーム

x2

+

1  2      4      3

9    6    8    6    5    9

8      4      2  64      2      1  3

A

B

C

Page 32: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

イベントストリーム

x2

+

1  2      4      3

9    6    8    6    5    9

8      4      2  64      2      1  3

A

B

C

Page 33: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

命令型

int A = 3;int B = 3;int C = A + B * 2; // 9B = 1;

A, Bが変更されても Cは変わらない

Page 34: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

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

Page 35: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3
Page 36: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3
Page 37: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

A, Bの変更に伴い Cも変わる

Page 38: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Reactive Webアプリケーション

Repository

DB

Service

Controller

Page 39: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Reactive Webアプリケーション

Repository

DB

Service

Controller

Page 40: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Reactive Webアプリケーション

Repository

DB

Service

Controller

Blocking Blocking

Page 41: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Reactive Webアプリケーション

Repository

DB

Service

Controller

Blocking BlockingBlocking他サービス呼び出し

Page 42: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Reactive Streams

Page 43: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Reactive Streams

• http://www.reactive-streams.org/

• 非同期ストリームの標準仕様

• BackPressure付き

Page 44: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Reactive Streamsの動機1. 技術面: データを送り側の勢いが受け取り側の処理速度より速い場合に、データが溢れることを防ぎたい(BackPressure)

2. 開発面: 似たような機能(API)を持つ製品群の相互互換性を持たせたい

Page 45: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

関わっている会社• Typesafe • Pivotal • Netflix • RedHat • など

Page 46: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

関わっている会社• Typesafe ... Akka Streams • Pivotal ... Reactor • Netflix ... RxJava • RedHat ... Vert.x • など

Page 47: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Reactive Streamsが提供するもの

• 4つのインターフェース

• 仕様ドキュメント

• TCK (仕様をテストするJUnitの親クラス)

Page 48: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

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

Page 49: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

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

Page 50: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

呼び出し順

onSubscribe onNext* (onError | onComplete)?

Page 51: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Subscription SubscriberPublisher Application

Page 52: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Subscription

subscribe(Subscriber)

SubscriberPublisher Application

Page 53: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Subscription

subscribe(Subscriber)

SubscriberPublisher Application

onSubscribe(Subscription)

Page 54: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Subscription

subscribe(Subscriber)

SubscriberPublisher Application

onSubscribe(Subscription)request(1)

Page 55: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Subscription

subscribe(Subscriber)

SubscriberPublisher Application

onSubscribe(Subscription)request(1)onNext(●)

Page 56: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Subscription

subscribe(Subscriber)

SubscriberPublisher Application

onSubscribe(Subscription)request(1)onNext(●)request(2)

Page 57: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Subscription

subscribe(Subscriber)

SubscriberPublisher Application

onSubscribe(Subscription)request(1)onNext(●)request(2)onNext(●)

Page 58: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Subscription

subscribe(Subscriber)

SubscriberPublisher Application

onSubscribe(Subscription)request(1)onNext(●)request(2)onNext(●)onNext(●)

Page 59: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Subscription

subscribe(Subscriber)

SubscriberPublisher Application

onSubscribe(Subscription)request(1)onNext(●)request(2)onNext(●)onNext(●)request(4)

Page 60: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Subscription

subscribe(Subscriber)

SubscriberPublisher Application

onSubscribe(Subscription)request(1)onNext(●)request(2)onNext(●)onNext(●)request(4)onNext(●)

Page 61: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Subscription

subscribe(Subscriber)

SubscriberPublisher Application

onSubscribe(Subscription)request(1)onNext(●)request(2)onNext(●)onNext(●)request(4)onNext(●)onNext(●)

Page 62: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Subscription

subscribe(Subscriber)

SubscriberPublisher Application

onSubscribe(Subscription)request(1)onNext(●)request(2)onNext(●)onNext(●)request(4)onNext(●)onNext(●)onComplete()

Page 63: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Subscription

subscribe(Subscriber)

SubscriberPublisher Application

onSubscribe(Subscription)request(Long.MAX_VALUE)

Page 64: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Subscription

subscribe(Subscriber)

SubscriberPublisher Application

onSubscribe(Subscription)request(Long.MAX_VALUE)onNext(●)

Page 65: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Subscription

subscribe(Subscriber)

SubscriberPublisher Application

onSubscribe(Subscription)request(Long.MAX_VALUE)onNext(●)onNext(●)

Page 66: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Subscription

subscribe(Subscriber)

SubscriberPublisher Application

onSubscribe(Subscription)request(Long.MAX_VALUE)onNext(●)onNext(●)onNext(●)

Page 67: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Subscription

subscribe(Subscriber)

SubscriberPublisher Application

onSubscribe(Subscription)request(Long.MAX_VALUE)onNext(●)onNext(●)onNext(●)onNext(●)

Page 68: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Subscription

subscribe(Subscriber)

SubscriberPublisher Application

onSubscribe(Subscription)request(Long.MAX_VALUE)onNext(●)onNext(●)onNext(●)onNext(●)onNext(●)

Page 69: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Subscription

subscribe(Subscriber)

SubscriberPublisher Application

onSubscribe(Subscription)request(Long.MAX_VALUE)onNext(●)onNext(●)onNext(●)onNext(●)onNext(●)onComplete()

Page 70: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Subscription

subscribe(Subscriber)

SubscriberPublisher Application

onSubscribe(Subscription)request(1)onNext(●)request(2)onNext(●)onNext(●)request(4)

Page 71: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Subscription

subscribe(Subscriber)

SubscriberPublisher Application

onSubscribe(Subscription)request(1)onNext(●)request(2)onNext(●)onNext(●)request(4)💣💥

Page 72: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Subscription

subscribe(Subscriber)

SubscriberPublisher Application

onSubscribe(Subscription)request(1)onNext(●)request(2)onNext(●)onNext(●)request(4)onError(Throwable)

💣💥

Page 73: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

RxJavaからinspired

RxJava Reactive StreamsObservable<T> Publisher<T>Observer<T> Subscriber<T>Subscription Subscription

Page 74: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Non BlockingなAPI• TやList<T>の代わりにPublisher<T>を返す

Blocking Non BlockingUser

get(String name)Publisher<User>get(String name)

List<User> allFriends(User user)

Publisher<User> allFriends(User user)

Page 75: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

実装例 (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() {} });}}

Page 76: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

実装例 (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!"); } }

Page 77: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

使用例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!

Page 78: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

使用例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を通らない)

Page 79: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Hot / Cold• Hot Stream

• ずっと続いていて途中から見はじめるもの • 株価情報、タイムライン、マウスイベント、タイマーイベント、WebSocket、Server-Sent Events、メッセージキュー

• Cold Stream • 再現可能で、最初から最後まで見れるもの • 配列・リスト、ファイル、データベース、計算結果(Future)

Page 80: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Reactive Streamsの仕様

• Subscriberは非同期でも同期でもよい。ただし、ノンブロッキングでないといけない

Page 81: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

実装プロダクト(フレームワーク)

• Reactor (Pivotal) • RxJava (Netflix) • Akka Streams (Typesafe) • Vert.x (Redhat) • Ratpack • Quasarhttp://www.reactive-streams.org/announce-1.0.0

Page 82: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

実装データアクセスライブラリ• MongoDB (公式) • Apache Kafka • Rabbit MQ (Scalaのみ) • Slick3 (Scala) • CouchDB (RxJava only) • PostgreSQL (RxJava only、開発中?) • Spark (検討中? SPARK-10420) • など

Page 83: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

MongoDB

• http://mongodb.github.io/mongo-java-driver-reactivestreams/

• MongoDB公式でReactive Streams APIがサポートされている

• チュートリアルがあるのでわかりやすい

Page 84: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

MongoDBMongoClient client = MongoClients.create( "mongodb://localhost"); MongoDatabase db = client.getDatabase("mydb"); MongoCollection<Document> collection = db.getCollection("test");// InsertDocument doc = new Document("message", "Hello!"); Publisher<Success> insert = collection.insertOne(doc); insert.subscribe(new PrintSubscriber<>("result=%s"));

// SelectPublisher<Document> docs = collection.find(); docs.subscribe(new PrintDocumentSubscriber());

Page 85: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

MongoDB// Bulk OperationPrintSubscriber<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);

Page 86: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Apache Kafka

• https://github.com/softwaremill/reactive-kafka

• Scalaで実装されている。Java用APIも用意されている。

Page 87: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Apache KafkaReactiveKafka 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);

Page 88: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

PostgreSQL

• https://github.com/alaisi/postgres-async-driver

• https://github.com/mauricio/postgresql-async

Page 89: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

PostgreSQLDb db = new ConnectionPoolBuilder().hostname("localhost").port(5432).database("demo").username("postgres").password("").poolSize(20).build();// RxJava's ObservableObservable<Row> result = db.queryRows("select id,value from demo");result.subscribe(...);// to Reactive StreamsPublisher<Row> publisher = RxReactiveStreams.toPublisher(result);publisher.subscribe(...);

Page 90: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Publisher単体だと使いにくい• Publisherはただのコールバック

• map、flatMap、merge、filer、take、zipといっった合成(compose)や変換(transform)のためのAPIがない → コールバック地獄に

• Publisherはインターフェースでしかないので実装ライブラリ側で便利なAPIを提供可能。

Page 91: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

コールバック地獄

• もっと命令的に書きたい

• ComposableなAPIが欲しい(Reactive Streamsの範疇外)

Page 92: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Reactive Extensions

Page 93: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Reactive Extensions(Rx)

• 元々はMicrosoftのでErik Meijerによって.NET(LINQ)向け開発されたライブラリ

• Observerパターンでイベントストリームを扱う • イベントストリームを操作(変換、フィルタ、合成など)する豊富なAPI群

• 多言語対応(Java, JavaScript, .NET, Swiftなど)

http://reactivex.io/

Page 94: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

map

Page 95: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

flatMap

Page 96: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

filter

Page 97: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

take

Page 98: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

merge

Page 99: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

zip

Page 100: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

combileLatest

Page 101: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

buffer

Page 102: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

RxJava• Netflix社が開発したRxのJava版 • Observable/Observer • Observableに対して豊富なOperation APIを提供

Observable.just('a', 'b', 'c') .take(2) .map(Character::toUpperCase) .consume(System.out::print); // AB

Page 103: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

RxJava• バージョン1.0ではReactive Streamsをnativeサポートしていない。Publisher <-> Observableアダプターが必要

• バージョン2.0でReactive Streams対応予定

// Publisher <-> ObservablePublisher<String> publisher = RxReactiveStreams.toPublisher(observable);Observable<String> observable = RxReactiveStreams.toObservable(publisher);

Page 104: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

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

Page 105: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Reactor Projectshttp://projectreactor.io/docs/reference/#_about_the_project

Page 106: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Reactive StreamsとReactor Streamsの関係

BroadCaster

Action

Stream

Processor

Subscriber Publisher

Consumer

ClassInterface

extends implements

Reactive Streams

Reactor

Promise

Page 107: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

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);

Page 108: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

// Subscription.request(Long.MAX_VALUE)相当// consumeに渡すラムダ式がonNextで実行されるstream.consume(s -> System.out.println(s));

// Subscription.request(2)を繰り返すstream.capacity(2) .consume(s -> System.out.println(s));

// デバッグログ出力stream.log() .consume(s -> System.out.println(s));

Page 109: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

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());

Page 110: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

reactor.rx.Streamを使うことで Reactive Streamsを Reactive Extensionsで操作できる

Page 111: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

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); });

Page 112: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

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

Page 113: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Reactorでコナミコマンド// Create a "Hot" streamBroadcaster<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"); });

Page 114: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Reactorでコナミコマンドstream.onNext("A"); stream.onNext("↑"); stream.onNext("↑"); stream.onNext("""); stream.onNext("""); stream.onNext("←"); stream.onNext("#"); stream.onNext("←"); stream.onNext("#"); stream.onNext("A"); stream.onNext("B"); stream.onNext("←");

NGKonami!NG

コナミコマンド

HotStreamをエミュレート

Page 115: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

外部サービス呼び出し (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);

}

Page 116: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

外部サービス呼び出し (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);

}

Page 117: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

flatMaplinkedInService.findUsers("JJUG") .take(5) .flatMap(userName -> linkedInService.getConnections(userName) .take(3) .flatMap(connection -> { String twitterId = connection.getTwitterId(); Publisher<TwitterProfile> twitterProfile = twitterService.getUserProfile(twitterId); String facebookId = connection.getFacebookId(); Publisher<FacebookProfile> facebookProfile = facebookService.getUserProfile(facebookId); return Streams.zip(twitterProfile, facebookProfile, (tp, fp) -> new UserConnectionInfo( userName, connection, tp, fp)); }) ) .subscribe(System.out::println);

http://www.slideshare.net/SpringCentral/introduction-to-reactive-programming/60

Page 118: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Reactor or RxJava ?Reactor RxJava

• Reactive StreamsをNativeサポート

• Spring連携 • Reactive Extensionsのサブセット

•Reactive Exensionsをフルセットでサポート

•他言語対応 • Reactive Streamsはアダプター経由

Page 119: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Reactive Streamsのメリット• 非同期サポートライブラリを作りやすい

Page 120: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

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

Page 121: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

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

Page 122: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

すべてがPublisherで繋がる

Repository

DB

Service

Controller

Publisher Publisher Publisher

PublisherPublisherPublisher

Page 123: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

すべてがPublisherで繋がる

Repository

DB

Service

Controller

Publisher Publisher Publisher

PublisherPublisherPublisher

Page 124: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

すべてがPublisherで繋がる

Repository

DB

Service

Controller

Publisher Publisher Publisher

PublisherPublisherPublisher

ここは?

Page 125: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Spring 5

Page 126: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Spring 5• Q4 2016 • JDK 9サポート • Java 8がベースライン • HTTP 2対応 • Reactive対応 • JUnit5対応

Page 127: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Spring 5• Q4 2016 • JDK 9サポート • Java 8がベースライン • HTTP 2対応 • Reactive対応 • JUnit5対応

Page 128: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Java WebアプリケーションのReactive対応?

• Servlet APIは至るところでBlocking • InputStream/OutputStream • getParameters/getParts • sendError• ...

Page 129: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

昨今のNoBlocking対応 フレームワーク

• Play Framework • Vert.x • Ratpack • Reactor Net • RxNetty

脱Servlet API組 ↓

Netty利用

Page 130: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Servletはダメな子なのか

Page 131: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Servletはダメな子なのか

• Servlet 3.0 … 非同期処理サポート

Page 132: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Servletはダメな子なのか

• Servlet 3.0 … 非同期処理サポート

• Servlet 3.1 … Non-Blocking APIサポート

Page 133: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

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

Page 134: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

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

Page 135: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Servlet 3.1 Non-Blocking APIサポート

• リクエストの読み込み/レスポンスの書き込みをNon-Blockingに行うためのAPIが追加された

• 以下のシーンで効果的 • ファイルアップロード/ダウンロード • 低速ネットワークからの大量アクセス(モバイル、IoT)

Page 136: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

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

Page 137: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

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);}

Page 138: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

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(); }}

Page 139: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

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(); }}

Page 140: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Block

Servlet

Page 141: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Servlet

ReadListener

WriteListener

Page 142: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Servlet

ReadListener

WriteListener

Page 143: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

書くのが辛い

• Non-Blockingの方が5倍コード量が多い

• isReady, isFinishedの制御が難しい

• ついgetParameterするとBlock...

http://www.slideshare.net/SimoneBordet/servlet-31-async-io

Page 144: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

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

Page 145: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Servlet31HttpHandlerAdapter

• HttpServlet実装

• ReadListener/WriteListenerをObserverパターンで実装

• Reactive Streams(Publisher/Subscriber)を使用

Page 146: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

• ReadListener→Publisher

• WriteListener→Subscriber

Servlet31HttpHandlerAdapter

https://github.com/spring-projects/spring-reactive/tree/master/src/main/java/org/springframework/http/server/servlet31

Page 147: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Instead of ...

interface ServerHttpRequest extends HttpRequest { InputStream getBody();}

interface ServerHttpResponse extends HttpMessage { OutputStream getBody();}

Page 148: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Use Publisher

interface ReactiveServerHttpRequest extends HttpRequest { Publisher<ByteBuffer> getBody();}

interface ReactiveServerHttpResponse extends HttpMessage { Publisher<Void> setBody(Publisher<ByteBuffer> pub);}

Page 149: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Spring MVCのアーキテクチャ

DispatcherServlet

<<IF>> HandlerAdapter

<<IF>> HandlerMapping

Handler (Object)

フレームワーク アプリケーション

org.springframework.web.servletパッケージ

これまでの

Page 150: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Spring MVCのアーキテクチャ

DispatcherServlet

RequestMappingHandlerAdapter

RequestMappingHandlerMapping

@RequestMapping

HttpMessageConverter

org.springframework.web.servlet.mvc.method.annotationパッケージ

これまでの

Page 151: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Spring MVCのアーキテクチャ

DispatcherServlet

RequestMappingHandlerAdapter

RequestMappingHandlerMapping

@RequestMapping

HttpMessageConverter

org.springframework.web.servlet.mvc.method.annotationパッケージ

所謂、 Controllerクラス

これまでの

Page 152: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Spring Reactiveのアーキテクチャ

<<IF>> HandlerAdapter

<<IF>> HandlerMapping

Handler (Object)

フレームワーク アプリケーション

org.springframework.web.reactiveパッケージ

Servlet31HttpHandlerAdapter

<<IF>> Reactive

HttpHandeler

Page 153: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Servlet31HttpHandlerAdapter RequestMapping

HandlerAdapter

RequestMappingHandlerMapping

@RequsetMapping

Encoder/Decoder

Spring Reactiveのアーキテクチャorg.springframework.web.reactive.method.annotationパッケージ

DispatcherHandler

Page 154: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

RequestMappingHandlerAdapter

RequestMappingHandlerMapping

@RequsetMapping

Encoder/Decoder

Spring Reactiveのアーキテクチャorg.springframework.web.reactive.method.annotationパッケージ

Servlet31HttpHandlerAdapter

DispatcherHandler

Spring MVCと同じプログラミングモデルで アプリケーションを記述できる

Page 155: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Spring Reactiveのアプローチ

Reactor Net ReactorHttpHanderAdapter

RxNetty RxNettyHttpHandlerAdapter

Undertow UndertowHttpHandlerAdapter

Servlet31HttpHandlerAdapter

Reactive Streams

@Controller

Jetty

Tomcat Publisher

ReactiveHttpHandeler

Page 156: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Spring Reactiveのアプローチ

Reactor Net ReactorHttpHanderAdapter

RxNetty RxNettyHttpHandlerAdapter

Undertow UndertowHttpHandlerAdapter

Servlet31HttpHandlerAdapter

Reactive Streams

@Controller

Jetty

Tomcat Publisher

ReactiveHttpHandeler

Servletコンテナ以外の選択肢もある

Page 157: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Spring MVCのController

@RequestMapping("/")@ResponseBodyPerson hello(@RequestBody Person req) { // ...}

これまでの

Page 158: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Spring ReactiveのController

@RequestMapping("/")@ResponseBodyPublisher<Person> hello( @RequestBody Publisher<Person> req) { // ...}

Page 159: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Reactive Webアプリケーション

Repository

DB

Service

Controller

Publisher Publisher Publisher

PublisherPublisherPublisher

Page 160: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Reactive Webアプリケーション

Repository

DB

Service

Controller

Publisher Publisher Publisher

PublisherPublisherPublisher

Spring Reactive

Reactive Extensions

Reactive Streams

Page 161: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

絶賛開発中

• Reactive Clientの実装

• Filter相当の実装

• Progressive HTML renderingの検討

Page 162: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

Springは Java EEの代替ではありません

Page 163: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

落穂拾い

Page 164: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

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

Page 165: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

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 StreamsPublisher<T> toReactive(Flow.Publisher<>T);// Reactive Streams -> j.u.c.FlowFlow.Publisher<T> toFlow(Publisher<T>);

Page 166: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

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

Page 167: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

まとめ• Blocking ==💴な時代がきている • Non-Blocking化を助けるReactiveなパラダイム • 非同期ストリーム標準 Reactive Streams • イベントストリームの変換・合成 Reactive Extensions

• Reactive Webアプリケーション向けフレームワークSpring ReactiveがSpring 5に向けて開発中

Page 168: Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3

まとめ• Blocking ==💴な時代がきている • Non-Blocking化を助けるReactiveなパラダイム • 非同期ストリーム標準 Reactive Streams • イベントストリームの変換・合成 Reactive Extensions

• Reactive Webアプリケーション向けフレームワークSpring ReactiveがSpring 5に向けて開発中

Spring Framework を使っていきましょう