简体   繁体   English

Spring Boot 响应式和 EventSource 的工作示例

[英]Working example of Spring boot reactive and EventSource

I'm trying to have a working spring boot with reactive mongodb and EventSource.我正在尝试使用反应式 mongodb 和 EventSource 进行有效的 Spring Boot。 However, I'm facing issues with the repetitive reopening of the connection because it's closed by the server.但是,我面临着重复重新打开连接的问题,因为它已被服务器关闭。 I even have some doubt if this could really work since I didn't find any working example with a reactive db and Event source...我什至怀疑这是否真的有效,因为我没有找到任何带有反应式数据库和事件源的工作示例......

Could you please point me to a working example or tell me what's wrong with my code?你能给我指出一个有效的例子或告诉我我的代码有什么问题吗?

Here the main parts of the code:下面是代码的主要部分:

pom.xml pom.xml

<properties>
  <java.version>1.8</java.version>
  <junit-jupiter.version>5.3.2</junit-jupiter.version>
</properties>

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.3.5.RELEASE</version>
</parent>

<dependencies>

<!-- webflux reactive -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

<!-- thymeleaf -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>

<!-- exclude junit 4, prefer junit 5 -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-test</artifactId>
  <scope>test</scope>
  <exclusions>
    <exclusion>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
    </exclusion>
  </exclusions>
</dependency>

<!-- junit 5 -->
<dependency>
  <groupId>org.junit.jupiter</groupId>
  <artifactId>junit-jupiter-engine</artifactId>
  <version>${junit-jupiter.version}</version>
  <scope>test</scope>
</dependency>

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-devtools</artifactId>
  <optional>true</optional>
</dependency>

<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
</dependency>

</dependencies>

As you see in the pom, I'm using the embedded tomcat (I already tried with Netty, the default spring boot server...).正如你在 pom 中看到的,我使用的是嵌入式 tomcat(我已经尝试过 Netty,默认的 spring 引导服务器......)。 Also, I'm deploying the app to any remote server but just trying on my local (windows 10).此外,我正在将应用程序部署到任何远程服务器,但只是在我的本地(Windows 10)上进行尝试。

Web:网站:

    let source = new EventSource("/comment/stream");

    source.addEventListener("message", function (event) {
        // These events are JSON, so parsing and DOM fiddling are needed
        var comment = JSON.parse(event.data);
        console.log(comment ); 
    });

    source.addEventListener("error", function (event) {
      console.log("error", event);
      this.close();
    });

RestController:休息控制器:

@RestController
public class CommentController {

  @Autowired
  private CommentRepository commentRepository;

  @PostMapping(path = "/comment")
  public Mono<Comment> comment(@RequestBody Comment comment) {
    return this.commentRepository.save(comment);
  }

  @GetMapping(path = "/comment/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
  public Flux<Comment> feed() {
    return this.commentRepository.findAll();
  }

}

DB Repository:数据库存储库:

@Repository
public interface CommentRepository extends ReactiveSortingRepository<Comment, String> {

 Flux<Comment> findAll();
}

Again, the web client that uses EventSource, keeps reconnecting every second because the connection is closed by the server.同样,使用 EventSource 的 Web 客户端每秒都会重新连接,因为连接已被服务器关闭。

Thank you!谢谢!

Im not really sure, you are giving us too little information as to why your connection is closing.我不太确定,关于您的连接关闭的原因,您提供给我们的信息太少。 No logs, and you are not disclosing anything about where it being deployed.没有日志,并且您没有透露有关其部署位置的任何信息。

i will only answer this question based on personal experience.我只会根据个人经验回答这个问题。 I deployed an application to heroku that uses event streams and they have a proxy/loadbalancer infront of every application that will kill any connection that does not send anything after up to 60 sec.我将一个应用程序部署到使用事件流的 heroku,并且它们在每个应用程序前面都有一个代理/负载均衡器,该应用程序将终止任何在 60 秒后不发送任何内容的连接。

As mentioned here Why are event sources closed after 30-60 sec it confirmes what i have been noticing.正如这里提到的为什么事件源在 30-60 秒后关闭它证实了我一直在注意的事情。

To work around this you can if using websockets implement ping/pong messages or if using ServerSentEvents as i did, i implemented keep alive messages.为了解决这个问题,如果使用 websockets 实现 ping/pong 消息,或者如果像我一样使用ServerSentEvents ,我实现了保持活动消息。

    .GET("", accept(TEXT_EVENT_STREAM), request -> ok()
        .contentType(TEXT_EVENT_STREAM)
        .header("Cache-Control", "no-transform")
        .body(Flux.merge(myHandler.getEvents()), 
                  Flux.interval(Duration.ofSeconds(15))
                          .map(aLong -> ServerSentEvent.builder()
                                                       .comment("keep alive")
                                                       .build())),
        new ParameterizedTypeReference<List<MyClass>>() {}))

I have taken this code snippet from one of my projects.我从我的一个项目中获取了这段代码片段。 Here you can see that i merge with my current stream a flux that at given intervals (15 sec) will emit a ServerSentEvent with only a keep alive comment.在这里你可以看到我与我当前的流合并了一个通量,在给定的时间间隔(15 秒)将发出一个ServerSentEvent ,只有一个保持活动的评论。 Since it is a comment it will get ignored by the client.由于它是注释,因此客户端将忽略它。

Just need to mention, the regular stream myHandler.getEvents returns data wrapped in ServerSentEvent s.只需要提到,常规流myHandler.getEvents返回包装在ServerSentEvent s 中的数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Spring Boot Reactive Mongo 在启动时挂起 - Spring Boot Reactive Mongo Hangs on startup WebFlux Spring Boot @Transactional 与反应式 MongoDB - WebFlux Spring Boot @Transactional with reactive MongoDB 使用 ElasticSearch Reactive Streams 的 Spring Boot 应用程序架构 - Architecture of a Spring Boot Application with ElasticSearch Reactive Streams 审核(@CreatedDate)不适用于带有反应式 MongoDB 的 WebFlux Spring Boot - Auditing (@CreatedDate) does not work for WebFlux Spring Boot with reactive MongoDB Spring 启动带反应式 MongoDB 抛出打开套接字异常 - Spring Boot with Reactive MongoDB throwing opening socket Exception Spring 启动反应和 mongodb '命令插入需要身份验证' - Spring boot reactive and mongodb 'command insert requires authentication' 如何在春季启动时在反应式mongodb客户端中启用ssl? - How to enable ssl in reactive mongodb client in spring boot? Spring Boot 2配置反应式Mongo数据库存储库而无需EmbeddedMongo - Spring boot 2 configure reactive mongo db repository WITHOUT EmbeddedMongo Spring Boot反应式Mongo运行状况检查没有显示(反应式Mongo) - spring boot reactive mongo health check doe not show up (reactive mongo) 分层架构/项目结构如何? - 在 Spring Boot Reactive 之上的 Vaadin 与 MongoDB 反应 - How could be the layered architecture / project structure? - Vaadin on top of Spring Boot Reactive with MongoDB reactive
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM