webflux的一點學習感悟
首先 我想說的是 這個東西 寫起來 真的很優雅 很舒服 看著也清晰 感覺程式碼就應該這麼寫
其次 我想說 如果只是用於資料的展示 (不提交資料 或者只是將資料取出來 然後處理)這個用起來 是非常棒的 但是要是處理業務的話 最好還是用原生的Java程式碼
說一下和原生的servlet的區別
我們之前用的東西(servlet) 都是將結果 處理處理好 然後 返回 一層一層的返回 就是說 在mapping到合適的方法後 這個方法執行完後 瀏覽器所期望的資料 已經生成了 然後 就是一層 一層的往外走 最後直接給瀏覽器 因而 如果請求很多的話 因為這個方法 要把 結果處理出來 才返回 所以 請量很大的時候 吞吐量就上不去了 (這裡暫時想不到合適的例子)
webflux就不一樣了 我之前 有疑惑但是明白這一點後 也就意識到為什麼要這麼做了
先說下結論 webflux 在mapping的方法裡面 並不是返回結果 而是返回 資料與函式的組合(Mono Flux) 所以在mapping的方法中 不會花費很多時間 所以同等情況下 要比servlet的吞吐量大
@GetMapping(path = "/applications", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public Flux<ServerSentEvent<Application>> applicationsStream() { return Flux.from(eventPublisher) .flatMap(event -> registry.getInstance(event.getInstance())) .map(this::getApplicationForInstance) .flatMap(group -> toApplication(group.getT1(), group.getT2())) .map(application -> ServerSentEvent.builder(application).build()) .mergeWith(ping()); }
如上圖程式碼 返回的是一個flux物件 裡面包含了資料 與處理的方法 但是並不執行 只有在真正需要的時候 才去執行裡面的方法 並放回最終的結果(和spark裡的rdd處理 如出一轍) 一直說的非同步io 關鍵點就在這裡
至於後面的資料提取 最終返回 就要看裡面的原始碼了
這裡說下我之前的疑惑 Mono和Flux的都實現了 Publisher 裡面有個subscribe方法
public abstract class Flux<T> implements Publisher<T> { .....} public abstract class Mono<T> implements Publisher<T> { ....} public interface Publisher<T> { /** * Request {@link Publisher} to start streaming data. * <p> * This is a "factory method" and can be called multiple times, each time starting a new {@link Subscription}. * <p> * Each {@link Subscription} will work for only a single {@link Subscriber}. * <p> * A {@link Subscriber} should only subscribe once to a single {@link Publisher}. * <p> * If the {@link Publisher} rejects the subscription attempt or otherwise fails it will * signal the error via {@link Subscriber#onError}. * * @param s the {@link Subscriber} that will consume signals from this {@link Publisher} */ public void subscribe(Subscriber<? super T> s); }
資料的處理函式 貌似都是寫到這個方法裡面 最後在進行呼叫 當時我不明白的事 這個不是直接返回結果嗎 幹嘛還在這裡面 寫個類似訂閱的方法
知道了上面的後 就說清楚了 結果不是立刻返回 而是在最後使用結果的時候 在呼叫具體的方法(這裡其實是函式)然後獲取結果
感覺這個和scala有點接近了