我有一个小的业余爱好项目,我正在用Linux编写一个'wrapper'-daemon,也就是说,它的目的是启动,监控,发出命令并停止其他程序。守护程序还提供Web界面,用户可以在其中登录和操作正在运行的程序。
现在设置的方式是,只要程序写入其stdout,此输出就会重定向到管道。每当有人通过Web界面访问程序时,Web界面就会通过XMLHttpRequest()开始轮询守护进程,守护进程然后会检查是否有东西写入管道并发回一个响应,其中包含管道中的任何内容。时间。
主要问题是当我有两个(或更多)用户登录并尝试与同一程序进行交互时。由于Web界面有效地轮询管道以查找任何内容,因此每当有多个用户登录并监视同一程序时,该程序的输出将被randomely发送给其中一个用户。这显然很糟糕。
目前我正在考虑解决此问题的一个解决方案是为程序生成的所有输出加时间戳,并将此信息存储在类似数据库的内容中。当Web界面随后使用时间戳轮询守护进程时,守护进程只会收集自此以后写入的所有输出并将其发回。
我认为类似上述解决方案的内容可以解决多用户问题,但我想我会采取措施并查询Stack Overflow社区有关此问题的信息。对这样的问题有更好的解决方案吗? (鉴于我已经设法以一种可以理解的方式描述问题)。
答案 0 :(得分:0)
除非您希望所有返回的用户在下次登录时显示每个给定程序的所有输出,否则我认为不需要将信息存储在数据库中。这听起来有点像昂贵的一面。
您需要的是某种会话实现和标记化系统,用户可以在其中订阅某些输出流。当管道fd上发生select()
或poll()
时,该数据应写入该特定进程的所有订户。
您可以实现这两种方法,即未到达订阅用户的数据将被存储,以便在下次登录时显示。这不一定是复杂的甚至是SQL数据库,简单的密钥=>值对将起作用(例如将其存储在INI文件中:
[process-token]
TIMESTAMP.SEC.(...) = "string"
我最初对你的问题感到困惑,但在再次阅读之后,我意识到我们正在开展几乎相同的项目。我正在将一个简单的串行客户端连接到一个伪造的TTY,它提供与Ajaxterm非常相似的东西。它有助于访问半虚拟化Xen虚拟机的控制台。
答案 1 :(得分:0)
在摘要中,您有一种分叉的队列。主机上的程序产生的输出在头部排队,每个用户都从自己的尾部消耗。 “消费”部分有点搞笑,因为在所有感兴趣的用户都看到之前你不想“忘记”内容。 Tim Post建议每个用户流使用一个简单的队列,生产者入队到所有“订阅”队列。另一种方法是每个生产者的队列,用光标标记用户已经看到的距离。后一种方法是简约的,因为它不会复制任何东西,但会强迫你弄清楚每个人何时看到尾随内容,这样你就可以忘记它了。
我想我会尝试后一种方法,只是忘记了。也就是说,始终永远存储所有输出。这对用户来说也很有吸引力 - 毕竟,终端模拟器没有大尺寸的回滚缓冲区?它的存储空间更大,但这些天的存储空间非常便宜。
我认为使用数据库不一定是个坏主意。例如,您可能希望在生成时将时间戳与输出相关联,或者在内容中执行搜索。跟踪用户已经看到的流在多大程度上最有可能由rowid完成,但用户可能会欣赏“向我显示最后一小时的输出”类型的界面。将每个队列存储为一个表,按时间索引的行将是DB的自然工作负载,在空间和时间上非常有效。但基本的无遗忘队列可以非常简单地作为每个流的文件来完成,用户位置存储为偏移量。
Tim的方法,每个用户流,在生产者的上下文中做了一些工作,这取决于生产者有多个订阅者的频率。如果你的制作人像推特一样是不可行的方法:被数以百万计的用户观看;)但他的每用户流方法也不会打扰垃圾收集,也可能包括数据库和时间戳的想法。