不好意思在这提了个issue 因为没有找到网上可用的解决方案
接到一个需求,web端和server端建立一个socket,然后第三方通过一个接口发出一条设备的告警信息,server端需要通过
socket实时把告警返回到web
参考egg的教材使用了socket.io之后,socket建立成功。但是没办法在接口的处理函数里面,访问到之前建立的socket
控制台打印ctx.socket.id为undefined,不知道有什么办法可以调起之前建立好的socket
ctx.socket.emit('chat', 'hi 后端信息有调整 麻烦更新下');
[eggjs/egg]egg socket 处理第三方请求如何实时返回数据
回答
这个需求往复杂里说会非常复杂。这得看你的 web 端到底要和 server 建立多少的连接,通知时是通知所有 socket 还是某个指定的 socket。
假设我们就只建立一个 socket,接收警告信息的 controller 需要想办法找到具体维护这个 socket 的进程,并告知这个进程你需要向 socket 发送的消息。你可以通过广播的方式向所有进程广播这条消息,维护 socket 的进程收到这条消息后就把消息推给前端。
往复杂里说,多人连接、集群就要麻烦得多,你还得考虑负载均衡等问题,我在知乎有个 IM 场景的文章可以作为参考: https://zhuanlan.zhihu.com/p/25600864
好的,我先参考下您的回复,试试广播这个方案
其实这个问题,我感觉是题主用错了, 你在取 socket.id 是在 第三方通过接口发送警告信息的请求中吗? 你可以把 web 端和 server 端建立的socket 连接保存下来(其实就是 socket id), 后面可以取出对应的 id 然后在触发。
@jjeejj 你的意思是,全局维护一个数组(或者其他数据结构)把所有建立连接的socket id 保存下来,然后有告警的时候,去使用对应id触发socket更新吗?
单进程可以这么玩,但多进程模型下,接收警告消息的和维护 socket 连接的很有可能不是同一个进程,所以还是需要通过进程间通讯来让维护 socket 的进程发消息。
不过我说的是一个普适模型,具体如果是 egg-socket 还得看用法,我没用过 egg-socket 不了解它是否本身有另外开进程做维护之类的。
在保存 Socket 的时候, 可以把这个 Socket 建立的进程 id 的对应关系也保存下来。然后在回复消息的可以指定用哪个worker进程的。
也是,把 pid 也存下来就好了,这样就不用广播,向指定进程发消息即可。
两位大佬,我最后实现的方式是在global里面记录每次发送的socket,然后数据更新的时候使用app.messenger.broadcast把数据广播出去,在接收端遍历自己进程的global.socketArray 然后发送数据。但是现在遇见一个很奇怪的问题,本地测试OK。部署到服务器上就失效了,我特意在启动脚本里面加了workers=1 还是不行。 而且前端可以看到socket建立成功。这有什么可能的原因呢
这个一般都是环境的问题, 可以检查你 node 的版本,启动脚本参数, 或者 对应的配置文件