Java 是否建议使用服务器发送的事件通过连续查询数据库来推送通知?
我希望通过不断查询数据库,将实时通知(登录用户的DTO对象)推送到客户端。我使用服务器端事件来实现同样的目的。然而,在实现这一目标方面,我面临的问题很少。我正在javascript中使用EventSourceAPIJava 是否建议使用服务器发送的事件通过连续查询数据库来推送通知?,java,spring-boot,websocket,push-notification,server-sent-events,Java,Spring Boot,Websocket,Push Notification,Server Sent Events,我希望通过不断查询数据库,将实时通知(登录用户的DTO对象)推送到客户端。我使用服务器端事件来实现同样的目的。然而,在实现这一目标方面,我面临的问题很少。我正在javascript中使用EventSourceAPI 在无限循环中轮询 因为我的数据在数据库中,所以我经常需要运行查询来获取最新的条目,并使用executor.execute(()->{while(true){emitter.send(data)}}Thread.sleep(5000)),直到用户注销。(a) 在无限循环中查询数据库和(
executor.execute(()->{while(true){emitter.send(data)}}Thread.sleep(5000))
,直到用户注销。(a) 在无限循环中查询数据库和(b)创建新的ExecutorService对象会导致JDBC池耗尽异常,并最终冻结应用程序
SpringContextHolder.getAuthentication
在@Scheduled annotated方法中获取该id,因为此Cron不是由用户启动的请帮助/指导我。如果您想将事件推送到您的客户机,最好在后端也有事件概念,而不是轮询。如果您想轮询数据库,最好让客户机来做。SSE或websocket在该决定中并不重要 CDI活动可能是适合您需要的解决方案
- 创建一个
事件类李>EntityForLoggedInUsersChanged
- 在您的服务中插入一个
,该事件改变与loggedin用户相关的实体。当他们这样做时触发事件李>事件
- 创建一个服务,该服务将观察这些事件,构建您想要推送的dto,获得相关用户的频道,然后推送它
- 令人惊讶的是,这是一个有效的模式
与让数据库发送推送通知相比,每5秒轮询一次可能会占用更少的总体资源(即使假设数据库支持这一点)
与让客户端每5秒进行一次AJAX调用(每次都需要设置一个DB连接)相比,它可能更高效(代价是保持SSE套接字始终打开)
创建新的ExecutorService对象会导致JDBC池耗尽异常,并最终冻结应用程序
池耗尽是因为只有一个用户,每5秒轮询一次吗?还是因为有很多用户,每个用户都保持数据库连接打开
如果是后者,请使池足够大,以支持您希望允许的最大数量的同时连接的用户
如果是前者,您要么在轮询后释放资源,然后再进行5000ms睡眠,要么在循环外部打开资源一次,然后找到一种方法在无限循环内重新运行查询
(很抱歉,我不熟悉
ExecutorService
或Spring
;这可能是查询数据库的抽象层次太高,需要使用较低层次的函数?)
顺便说一句,SSE和Web套接字在这里没有什么区别。Web套接字为您提供了一个更复杂的协议,作为交换,它是一个双向连接,而不是单向连接,但其他一切基本相同。也就是说,在客户端和web服务之间仍然有一个专用套接字,并且仍然有一个无限循环轮询数据库。与上面的一点相矛盾的是,对于websocket,我不需要继续循环我的数据库。无论何时发生事件(比如创建注释/通知),在我的应用程序代码中,我都可以通过专用websocket频道广播消息。EventSource没有通道的概念。@VipulKumar如果您可以在websocket服务器中发生事件时收到通知(然后广播),那么您也可以为EventSource执行此操作。(顺便说一句,您可以指定
事件
标题来获取通道的概念,但我通常建议不要使用它,而是在一个消息处理程序中处理所有内容。例如,查看此人得出相同结论的地方。)Darren Cook感谢您的输入。但是,我们仍然必须不断循环/轮询数据库。