[英]What is proper way to consume inbound stream of ReactorNettyWebSocketClient
我尝试使用 Spring Reactor Webflux 学习反应式编程。 特别是在以下示例中,我尝试弄清楚如何正确组合处理管道,以使用 ReactorNettyWebSocketClient 使用 Websocket 连接的入站 ZF7B44CFFAFD5C52223D5498196C8A2E7BZ。
以下代码段工作正常:
WebSocketClient client = new ReactorNettyWebSocketClient();
client.execute(
URI.create("wss://stream.binance.com:9443/ws/btcusdt@trade"),
session -> {
Flux<String> tradesFlux = session.receive()
.map(WebSocketMessage::getPayloadAsText)
.doOnNext(event -> log.info(event));
return tradesFlux.then();
}
).subscribe();
在上面的片段中,我在入站 stream Flux 上使用doOnNext()
- tradesFlux
来消耗每个传入的事件。它适用于上面的片段,但据我所知, doOnNext()
是一个sideEffect-op,所以我试图做以下事情:
WebSocketClient client = new ReactorNettyWebSocketClient();
client.execute(
URI.create("wss://stream.binance.com:9443/ws/btcusdt@trade"),
session -> {
Flux<String> tradesFlux = session.receive()
.map(WebSocketMessage::getPayloadAsText);
tradesFlux.subscribe(new Subscriber<String>() {
@Override
public void onSubscribe(Subscription s) {
}
@Override
public void onNext(String s) {
log.info("replicate binance trade {}", s);
}
@Override
public void onError(Throwable t) {
}
@Override
public void onComplete() {
}
});
return tradesFlux.then();
}
).subscribe();
在第二个片段中,我尝试通过在入站 stream - tradesFlux
上调用subscribe
来使用Subscriber
者的入站 stream 。 但是有了这个片段,我得到了以下异常:
reactor.core.Exceptions$ErrorCallbackNotImplemented: java.lang.IllegalStateException: Only one connection receive subscriber allowed.
Caused by: java.lang.IllegalStateException: Only one connection receive subscriber allowed.
不知何故,一个人不能通过他自己的Subscriber
消耗入站 stream Flux,所以我想问的问题是:第一个片段是否已经是通过使用ReactorNettyWebSocketClient
-op doOnNext()
或这里有什么?
非常感谢! 董
我发现这个 Websocket 连接不能订阅两次,就像例外说的那样。 对我来说,解决方案是使用map
操作 - 实际上是在入站 stream Flux 上的链,以一对一的方式处理事件。 之后上面的问题听起来很愚蠢,但我发现所有关于使用ReactorNettyWebSocketClient
的示例总是使用doOnNext()
来处理来自入站 stream 的事件,这让我感到非常困惑。
运行代码如下所示:
@Bean
public WebSocketClient binanceTradesWS(Function<String, BinanceTrade> binanceTradeMapper,
Function<BinanceTrade, Trade> binanceTradeReplicator) {
WebSocketClient client = new ReactorNettyWebSocketClient();
client.execute(
URI.create("wss://stream.binance.com:9443/ws/btcusdt@trade"),
session -> {
return session.receive()
.map(WebSocketMessage::getPayloadAsText)
.map(binanceTradeMapper)
.map(binanceTradeReplicator)
.then();
}
).subscribe();
return client;
}
@Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper().registerModule(new KotlinModule());
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
return mapper;
}
@Bean
public Function<String, BinanceTrade> binanceTradeMapper(ObjectMapper objectMapper) {
return (String tradeJSON) -> {
log.info("map binance trade {}", tradeJSON);
try {
return objectMapper.readValue(tradeJSON, BinanceTrade.class);
} catch (JsonProcessingException e) {
e.printStackTrace();
return null;
}
};
}
@Bean
public Function<BinanceTrade, Trade> binanceTradeReplicator() {
return (BinanceTrade binanceTrade) -> {
Trade trade =new Trade(
binanceTrade.getT(),
binanceTrade.getS(),
new BigDecimal(binanceTrade.getQ()),
new BigDecimal(binanceTrade.getP()),
LocalDateTime.ofInstant(Instant.ofEpochMilli(binanceTrade.getTime()), TimeZone.getTimeZone("GMT").toZoneId())
);
log.info("replicated binance trade {}", trade);
return trade;
};
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.