我正在使用Spring WebFlux发布/接收服务器已发送事件。在发布方面,代码如下。然后,在一个测试用例中,我循环10次以调用“发布”以发送消息。
public ValidationEventPublisher() {
this.processor = DirectProcessor.<ExternalEvent>create().serialize();
this.sink = processor.sink();
}
@RequestMapping(value = "/ssp/common/v1/eventstream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<ServerSentEvent<ExternalEvent>> sse() {
return processor.map(e -> ServerSentEvent.builder(e).id(String.valueOf(msgId.incrementAndGet())).build())
.onBackpressureBuffer();
}
public void publish(ValidationEvent validationEvent)
{
log.info("Published Validation event...");
sink.next(validationEvent);
}
在接收方,代码是:
final Flux<Object> stream = WebClient.builder()
.baseUrl(sspUrl + "/ssp/common/v1/eventstream")
.defaultHeader(HttpHeaders.AUTHORIZATION, "Basic " + Base64Utils.encodeToString((username + ":" + password).getBytes(UTF_8)))
.build()
.get()
.retrieve()
.bodyToFlux(ServerSentEvent.class)
.filter(e -> e.id() != null)
.flatMap(e -> Mono.just(e.data()))
.doOnError(e -> handleServerDown(e))
.repeat();
stream.subscribe(e -> processEvent(e));
所以,问题是我只能收到第一条消息,此后总是出现异常。
- Published Validation event...
- Received validation event: {"messageId":"867b5ced-...}
- Published Validation event...
- Published Validation event...
2018-09-05 11:07:43,596 ERROR [reactor-http-nio-6] [] []
[org.springframework.web.server.adapter.HttpWebHandlerAdapter:213] -
Unhandled failure: An established connection was aborted by the software in
your host machine, response already set (status=null)
2018-09-05 11:07:43,597 WARN [reactor-http-nio-6] [] []
[org.springframework.http.server.reactive.ReactorHttpHandlerAdapter:76] -
Handling completed with error: An established connection was aborted by the
software in your host machine
...
我花了很长时间进行一些研究,但找不到相关信息。 请注意,我在一个测试用例中运行双方,这意味着它们在同一进程和JVM中。我认为这并不重要,但以防万一。
我发现原因是“取消”被发送出去了。但为什么?例如,如果我在接收方添加“ doOnCancel”,则可以看到它被称为。
答案 0 :(得分:0)
使用spring-boot-starter-parent 2.1.0.RELEASE我遇到了类似的问题。 尝试在端口8080和8081的客户端上运行以下服务
@SpringBootApplication
public class ServiceApplication {
@Bean
RouterFunction<ServerResponse> routes(Handler handler) {
return route(GET("/there").and(accept(MediaType.TEXT_EVENT_STREAM)), handler::all);
}
public static void main(String[] args) {
SpringApplication.run(ServiceApplication.class, args);
}
@Component
class Handler {
public Mono<ServerResponse> all(ServerRequest request) {
Flux<String> aFlux = Flux.range(0, 1000).map(i -> UUID.randomUUID().toString());
return ok().contentType(MediaType.TEXT_EVENT_STREAM).body(aFlux, String.class);
}
}
}
@SpringBootApplication
public class ClientApplication {
@Bean
RouterFunction<ServerResponse> routes(Handler handler) {
return route(GET("/here").and(accept(MediaType.TEXT_EVENT_STREAM)), handler::all);
}
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
@Component
class Handler {
public Mono<ServerResponse> all(ServerRequest request) {
Flux<String> resp = WebClient.create("http://localhost:8080")
.get()
.uri("/there")
.accept(MediaType.TEXT_EVENT_STREAM)
.retrieve()
.bodyToFlux(String.class);
return ok().contentType(MediaType.TEXT_EVENT_STREAM).body(resp, String.class);
}
}
}
现在多次执行curl -H“ Accept:text / event-stream”“ http://localhost:8081/here”,该服务有时会出错:
oswsadapter.HttpWebHandlerAdapter:[f903e4b6]错误[java.io.IOException:您的主机计算机中的软件中止了已建立的连接],用于HTTP GET“ / there”,但ServerHttpResponse已经提交(200 OK)>
答案 1 :(得分:0)
问题发布已经有一段时间了。现在我认为问题是在我处理消息时引起的一些异常,例如NPE在processEvent中。如果在processEvent中添加一个野生try ... catch,则很容易证明这一点。