spring-gateway(一)Reactor编程基础

 基础的api:

1 JDK9 Reactive

  • Publisher: 事件发布者

  • Subscriber: 事件订阅者

  • Processor: 事件流转过程中的处理,可包含多个阶段,同时继承了 Publisher和Subscriber两个接口

  • Subscription: 提供了 requestcancel 两个方法,用于订阅者和发布者之间的通信,Processor中的subscription通过request方法接收publisher(发布者)submit的事件。订阅者通过subscription通过request方法决定是否消费事件,实现背压back pressue,不会因为发布者发布消息过快而把订阅者压垮。

下面的使用JDK9提供的接口演示基础用法:

import java.util.concurrent.Flow;
import java.util.concurrent.Flow.Processor;
import java.util.concurrent.SubmissionPublisher;
​
public class DemoTest {
​
    public static void main(String[] args) throws InterruptedException {
        // #1 创建发布者
        SubmissionPublisher<Integer> publisher = new SubmissionPublisher<>();
​
        // #2 创建处理器
        Processor<Integer, Integer> processor = new MyProcessor();
​
        // #3 发布者和处理器建立关系
        publisher.subscribe(processor);
​
        Flow.Subscriber<Integer> subscriber = new Flow.Subscriber<>() {
            Flow.Subscription subscription;
​
            @Override
            public void onSubscribe(Flow.Subscription subscription) {
                System.out.println(">>> subscriber onSubscribe: " + subscription.toString());
                this.subscription = subscription;
​
                // 请求一个数据
                this.subscription.request(1);
            }
​
            @Override
            public void onNext(Integer item) {
                try {
                    Thread.sleep(30);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(">>> subscriber onNext 接收到数据:" + item);
                this.subscription.request(1); // 处理下一个事件
                // this.subscription.cancel(); // 终止处理
                // throw new RuntimeException(">>> subscriber throw a exception");
            }
​
            @Override
            public void onError(Throwable throwable) {
                System.out.println(">>> subscriber onError");
                throwable.printStackTrace();
            }
​
            @Override
            public void onComplete() {
                System.out.println(">>> subscriber onComplete");
            }
        };
​
        processor.subscribe(subscriber);
​
        for (int i = 0; i < 5; i++) {
            publisher.submit(i);
//            try {
//                Thread.sleep(60);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
        }
        // 发布者调用close后会触发Processor执行 onComplete
        publisher.close();
        // publisher.submit(4); // 发布者已经调用 close,再执行submit 报错 Closed
        Thread.currentThread().join(2000);
    }
​
    static class MyProcessor extends SubmissionPublisher<Integer> implements Processor<Integer, Integer> {
​
        Flow.Subscription subscription;
​
        @Override
        public void onSubscribe(Flow.Subscription subscription) {
            System.out.println(">>> Processor onSubscribe: " + subscription.toString());
            this.subscription = subscription;
​
            // 发起请求数据:发起点
            this.subscription.request(1);
        }
​
        @Override
        public void onNext(Integer item) {
            System.out.println(">>> Processor onNext 接收到数据:" + item);
            Integer result = item * item;
​
            // 发射处理结果(事件结果),会触发订阅者的 onNext 方法
            this.submit(result);
​
            // 接收发布者publish的下一个事件
            this.subscription.request(1);
​
            // 终止任务,不在接收发布者发布的信息,也不会触发 onComplete 方法
            // this.subscription.cancel(); // 终止处理
​
            // 抛出异常,会触发 onError 方法
            // throw new RuntimeException(">>> Processor throw a exception");
        }
​
        @Override
        public void onError(Throwable throwable) {
            System.out.println(">>> Processor onError");
            throwable.printStackTrace();
        }
​
        @Override
        public void onComplete() {
            System.out.println(">>> Processor onComplete");
            // 关闭Processor,将无法再调用 submit:即订阅者不会再收到消息
            this.close();
        }
    }
}

运行结果:

可以看到,程序是异步执行的,发布者发布事件,和观察者消费事件是异步非阻塞的。

2 Spring WebFlux

spring webflux 用的是响应式库是 reactive streams ,它的发布者 Publisher 主要是两个抽象类 MonoFlux

 

从图上可以看出,Flux能发出0~N个数据项,而Mono只能发出零或一个数据项。

1 创建Flux或Mono的简单方法

package com.fmi110.springgatewaylearning;
​
import org.reactivestreams.Subscription;
import reactor.core.publisher.BaseSubscriber;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
​
public class ReactiveDemo {
    public static void main(String[] args) {
​
        Flux<Integer> just = Flux.just(1, 2, 3, 4);
​
        // 创建一个Flux
        Flux<Integer> ints = Flux.range(1, 4)
                .map(i -> {
                    if (i <= 3) return i * i;
                    throw new RuntimeException("Got to 4");
                });
        // 订阅并消费
        ints.subscribe(i -> System.out.println(i), err -> System.out.println(err));
​
        // 创建一个空数据发布者
        Mono<Object> emptyData = Mono.empty();
        Mono<String> data = Mono.just("foo");
​
    }
}

2 基于lambda的订阅

subscribe(); 
​
subscribe(Consumer<? super T> consumer); 
​
subscribe(Consumer<? super T> consumer,
          Consumer<? super Throwable> errorConsumer); 
​
subscribe(Consumer<? super T> consumer,
          Consumer<? super Throwable> errorConsumer,
          Runnable completeConsumer); 
​
subscribe(Consumer<? super T> consumer,
          Consumer<? super Throwable> errorConsumer,
          Runnable completeConsumer,
          Consumer<? super Subscription> subscriptionConsumer); 

1 consumer:正常消费,对应 onNext()

2 errorConsumer:异常时的回调,对应 onError()

3 completeConsumer:执行结束时的回调,对应 onComplete()

4 subscriptionConsumer 为null或者传入一个用于设置消费最大数量的消费者(通过 Subscription#request(long)设置);或者返回一个 Disposable 用于取消订阅

实例代码:

Flux<Integer> ints = Flux.range(1, 4);
ints.subscribe(i -> System.out.println(i),
               error -> System.err.println("Error " + error),
               () -> System.out.println("Done"),
               sub -> sub.request(2));

运行截图:

示例中,虽然发布者发布了四个事件,但是 sub.request(2) 限定的最大消费数,所以消费了两个事件。

3 BaseSubscriber

BaseSubscriber类是一个可用于替换lambda写法的类,内部提供了 hookOnSubscribehookOnNexthookOnCompletehookOnErrorhookOnCancelhookFinally

等钩子

package com.fmi110.springgatewaylearning;
​
import org.reactivestreams.Subscription;
import reactor.core.publisher.BaseSubscriber;
import reactor.core.publisher.Flux;
import reactor.core.publisher.SignalType;
​
public class ReactiveDemo {
    public static void main(String[] args) {
        DemoBaseSubscriber<Integer> ss = new DemoBaseSubscriber();
        Flux<Integer> ints = Flux.range(1, 4);
        ints.subscribe(ss);
    }
​
​
    static class DemoBaseSubscriber<T> extends BaseSubscriber<T> {
        @Override
        public void hookOnSubscribe(Subscription subscription) {
            System.out.println("Subscribed");
            request(1);
        }
        @Override
        public void hookOnNext(T value) {
            System.out.println(">>> hookOnNext: value = "+value);
            request(1);
        }
​
        @Override
        protected void hookOnComplete() {
            super.hookOnComplete();
            System.out.println(">>> hookOnComplete");
        }
​
        @Override
        protected void hookFinally(SignalType type) {
            super.hookFinally(type);
            System.out.println(">>> hookFinally");
            System.out.println("SignalType:"+type);
        }
    }
}

更多详细用法请参考下面的链接。

参考:

Reactor Core Features

外行人都能看懂的WebFlux,错过了血亏

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值