我想从Reactor Flux创建gRPC StreamObserver。只要StreamObserver本身没有实现相应的接口,就需要这样做(参见例如this issue)。
我想出的大致如下:
final StreamObserver<ProtoResponse>[] streamObserverArray = new StreamObserver[1];
Flux<Response> myFlux Flux.create(sink -> streamObserverArray[0] = new StreamObserver<ProtoResponse>() {
@Override
public void onNext(ProtoResponse value) {
final Response response = convertFromProto(value);
sink.next(response);
}
@Override
public void onError(Throwable throwable) {
sink.error(throwable);
}
@Override
public void onCompleted() {
sink.complete();
}
});
myFlux
.doOnError(throwable -> {/* actual logic in here */}) //
.doOnComplete(() -> {/* actual logic in here */}) //
.doOnCancel(() -> {/* actual logic in here */}) //
.parallel() //
.runOn(Schedulers.parallel()) //
.doOnNext(/* actual heavy lifting logic in here */) //
.map(/* ... */) //
.sequential() //
.doOnNext(/* ...*/) //
.subscribe(); // needed to start the actual processing of the events on this Flux
MyGrpcService.newStub(channel).getResponses(protoRequest, streamObserverArray[0]);
我想在这里使用Reactor的主要思想是将“繁重工作”并行分配到多个线程上,而不是在gRPC请求线程上执行。
我发现上述方法存在一些问题:
StreamObserver[]
数组.subscribe()
完成它,那么当gRPC开始通信时,StreamObserver
可能是null
(也就是竞争条件) 所以我的问题是: 从gRPC StreamObserver桥接到Reactor Flux的最佳/首选方法是什么?有没有最好的做法?
答案 0 :(得分:1)
经过一些更多的摆弄并更好地了解整个反应性的东西后,我提出了以下解决方案:
/**
* Bridge the StreamObserver from gRPC to the Publisher from the reactive world.
*/
public class StreamObserverPublisher implements Publisher<Long>, StreamObserver<Long> {
private Subscriber<? super Long> subscriber;
@Override
public void onNext(Long l) {
subscriber.onNext(l);
}
@Override
public void onError(Throwable throwable) {
subscriber.onError(throwable);
}
@Override
public void onCompleted() {
subscriber.onComplete();
}
@Override
public void subscribe(Subscriber<? super Long> subscriber) {
this.subscriber = subscriber;
this.subscriber.onSubscribe(new BaseSubscriber() {});
}
}
// and somewhere else in the code
StreamObserverPublisher streamObserverPublisher = new StreamObserverPublisher();
Flux<Long> longFlux = Flux.from(streamObserverPublisher);
longFlux.subscribe(...); // must be done before executing the gRPC request
MyGrpcService.newStub(channel).getResponses(protoRequest, streamObserverPublisher);
答案 1 :(得分:1)