【问题标题】:Implement Server Side Events with Grails使用 Grails 实现服务器端事件
【发布时间】:2016-12-12 15:10:08
【问题描述】:

我想用 grails 实现服务器端事件。我想要的是,只有当数据库发生变化时,我的数据表才应该刷新。我想为此使用 HTML5 服务器端事件。我的第一个问题是,在使用 SSE 时,我观察到客户端不断向服务器发出请求,如果数据可用,它会拉取它。它类似于每 3-4 秒发送一次 Ajax 调用,可以更改,但我真正想要的是,只有且仅当数据库中的数据发生更改时,DataTable 才会刷新。我也想向客户端发送 JSON 数据,但无法以正确的格式发送。下面是我的控制器代码。

def test(){

def action
something.each(){

action = "<a href=\"javascript:fetchDetails('"+it.id+"','comments'"+")\" class='btn btn-primary'><span class='glyphicon glyphicon-upload'></span></a>"

dataArr << [
                            it.Number,
                            it.product,
                            it.description,
                            OrgChart.findByid(it.Owner)?.displayName,
                            OrgChart.findByid(it.Coordinator)?.displayName,
                            startDate,
                            endDate,
                            it.status.status,
                            action
            ]

    }

    println dataArr

        response.setContentType("text/event-stream;charset=UTF-8")
        response << "data: ${dataArr}\n\n"         
        render "Hi" 
}
}

下面是gsp或者客户端代码

console.log("Starting eventSource");
var eventSource = new EventSource("/ops/test");
console.log("Started eventSource");
eventSource.onmessage   = function(event) {

  var data = JSON.stringify(event.data)

  console.log("Message received: " + JSON.parse(data)); 

  changeRequestsTable.clear().rows.add(JSON.parse(event.data)).draw()

};

eventSource.onopen      = function(event) { console.log("Open " + event); };
eventSource.onerror     = function(event) { console.log("Error " + event); };
console.log("eventState: " + eventSource.readyState);
// Stop trying after 10 seconds of errors
setTimeout(function() {eventSource.close();}, 10000);

我知道我距离实现我的意图还有很长的路要走,但任何帮助都将不胜感激

【问题讨论】:

  • 看看 websockets - 通过 gsp 持续检查 db 的变化并不是一个聪明的方法
  • @vahid :感谢您的回复...我通过了 websockets 并且从我掌握的是在 websockets 中有两种方式的通信是可能的......我不想去这种方法是因为我想要的是,当服务器更新时,它应该将数据推送到客户端......但是在尝试放置 SSE 之后,客户端似乎一直在尝试从服务器获取数据...... ...无论如何也想尝试使用 SSE .....或者至少想知道我到底做错了什么......
  • Web 套接字要求每个 wen 页面都有一个到后端侦听器的套接字连接。然后,侦听器可以向与响应相关联的所有会话广播,收到该响应的页面将触发具有脚本以使用响应内容更新页面。如果 wen 页面具有发送消息的功能和具有接收这些客户端请求的方法的侦听器,则可以有两种方式。看看 wschat 观看一些视频
  • 您当前的方法无法知道所有连接的页面,因此即使您可以正常工作。将您的测试乘以 500 个并发用户。每个用户必须每隔几秒钟执行一次 ajax 调用以触发数据库搜索条件以响应每个用户。这就是糟糕的设计导致应用程序缓慢的原因。您需要使用后端事件来触发赢得套接字的调用,可能会告诉它刷新用户页面。一旦广播给所有用户,可能会查找和响应搜索结果。因此,由事件触发 1 次查找并广播给 500 位用户,其中包含完整的页面详细信息与您当前的方式
  • @vahid:你提出的有趣观点......但在我当前的应用程序中将有 2 个角色......说请求者和批准者......这两个对同一件事有不同的看法,这是一个要求。所以我有 2 个不同的页面使用相同的 javascript 文件和相同的控制器文件。所以我想要实现的是,如果请求者更新了一个请求,它应该立即显示给批准者,如果一个批准者更新相同或不同,它应该立即显示给请求者.....你还会说这是一种不正确的做法

标签: javascript html grails groovy server-sent-events


【解决方案1】:

要回答这个问题,因为这将是一个漫长的对话。就目前而言,解决方案过于宽泛,无法给出正确的答案,因为关于你如何做事的角度可能会在如此巨大的范围内变化,从使用events,在记录保存时触发,然后转到client socket在保存点通过应用程序连接到direct socket client connection,这会触发要发送给客户端的内容。这些方法可能都更复杂,更纠缠不清,总之可以以更简单的方式完成。

  1. 随着用户的使用,他们的界面让用户与后端侦听器建立 ws 连接。它可以与没有房间/分隔的相同位置(需要额外的复杂性)。

当他们加入房间时,在您的 websocket listener that collections each session and userId 的顶部声明一个 static concurrent map。我不会以聊天的方式这样做,因为这是通过将其保留为集合而不是 like this 的服务注入的,并将 RunnableFuture 更改为 Websocket 会话,如服务链接示例中所示。

一旦你有了这个,你可以简单地调用一个 broadcast something like this 来获取你的静态并发映射,并且对于每个会话,要么在 json 中广播整个新列表,并且用户使用它来处理 html 更新,或者发送一个触发器来说更新页面然后他们开始进行 ajax 调用来更新列表。

【讨论】:

  • 感谢您回答我的问题...我确实使用 SSE 完成了此操作,并了解了您之前指出的其实现问题.....我现在正在研究 WebSockets。 ...问题是我正在使用 Grails 2.2.1 .....大多数用于 grails 的 websocket 插件都用于 2.5 以上的版本 .... 我确实遇到了适用于我的版本的 websockets 的 atmoshpere 插件使用....我会尝试一下以找出实现它的最佳方法.....无论如何感谢您抽出时间回答我的问题
  • 是的,由于 tomcat 的版本,你需要 2.35+ github.com/vahidhedayati/grails-wschat-plugin/issues/5 来支持 websocket。我还建议您是否会遇到 websocket 问题,因为显然突出显示您仍然可以使用 ajax 并引入 ehcache 并基本上缓存搜索查询。这意味着如果用户正在访问未更改的数据库,则它应该返回缓存结果而不是每次 ajax 调用时都查找新的数据库
【解决方案2】:

有关如何使用 Grails 3 实现服务器发送事件的教程,请参阅以下指南:

http://guides.grails.org/server-sent-events/guide/index.html

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-29
    • 2015-06-16
    • 1970-01-01
    • 1970-01-01
    • 2018-05-19
    • 2017-07-09
    • 1970-01-01
    相关资源
    最近更新 更多