Linux上的一对多进程通信

3

我有一个“服务器”进程,会产生一些日志。我希望用户(或其他服务)能够查看该日志流(类似于tail -f),但我不想将这些日志写入文件系统。在Linux上我可以这样做吗?

  1. My first attempt was to use UDP, on the loopback interface. The server sends packets to localhost on port 12345, and clients can bind to that port to receive them. Doesn't work. Because only one client can bind to the same socket. Ah! But you might say use SO_REUSE_ADDR, that lets two clients bind to one port, but only one receives the messages.

  2. Next up, I tried UDP multicast on the loopback interface. That one didn't get so far, as my kernel doesn't support multicast on the loopback interface. According to ifconfig:

    lo        Link encap:Local Loopback  
              inet addr:127.0.0.1  Mask:255.0.0.0
              UP LOOPBACK RUNNING  MTU:65536  Metric:1
              RX packets:186 errors:0 dropped:0 overruns:0 frame:0
              TX packets:186 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:0 
              RX bytes:11904 (11.6 KiB)  TX bytes:11904 (11.6 KiB)
    

    Note the lack of MULTICAST (or BROADCAST, indeed), above.

请问有什么想法吗?我可以使用命名管道或Unix域套接字来解决这个问题吗?

我希望避免任何可能会影响特权服务器的非特权侦听器的东西。例如,我宁愿放弃日志而不是阻止服务器。

如果有的话,我正在使用Python进行所有操作。


你的第一个段落中提出了一个问题:如果只能实时读取日志,那么记录日志有什么用呢?为什么不将它放入文件中呢? - Jason Hu
基本上需要一个轮询循环(selectpollepoll)来连接客户端,维护活动客户端列表,并在生成最新日志时立即将其发送给它们。可能更好的方法是使用管道将日志从主服务器传递到辅助 TCP/UDP 服务器,并在那里进行循环。 - Jason Hu
3个回答

3
你可以看一下ZeroMQ。你所描述的是需要发布者/订阅者模式,这恰好是ZeroMQ非常优雅地完成的事情。它还具有在底层使用哪种传输方式非常灵活的额外优势;IPC、TCP等。这使得将程序的各个部分放置在网络上变得非常简单。使用ZeroMQ,你最终会得到非常简单的源代码,所有复杂性都隐藏在zmq库中。你可以从这个指南的这一部分开始。
你也可以考虑NanoMSG(更好的ZeroMQ),但我不确定它是否已经有Python绑定了。

这看起来是一个不错的解决方案。我一直错误地认为ZeroMQ使用代理进程!而PUB套接字类型不会阻塞。我会进一步调查... - joerick
@joerick,没错,无代理是很好的。值得一提的是,数据分发服务也是无代理的。RabbitMQ有一个代理,当它出现问题时,人们会想知道会发生什么。在ZeroMQ中,后台运行着执行所有工作的线程,但最终结果是它们中没有一个对整个系统的操作至关重要。如果其中一个出现问题,其他所有东西都会继续运行,希望如此。重新启动出问题的部分,一切都会像平常一样继续进行。 - bazza

2
我可以想到两种通用方法。
1)使用POSIX共享内存对象。
请参阅shm_open(3)手册页以获取更多信息。
您的应用程序将创建一个共享内存对象,其中它将写入其日志消息,任何客户端应用程序都可以打开一个共享内存对象并读取它。尽管POSIX共享内存API看起来像基于文件系统的API,但实际上并不是。
现在,请记住,您将获得一块内存,某个您请求的大小。您需要想出如何以一些有意义的方式构造和管理此块内存,以便您的客户端应用程序可以解析并轮询更改的内容。
2)
您的应用程序承担打开并侦听本地主机套接字或文件系统域套接字的负担,任何客户端都可以连接到该套接字,并且您的应用程序将简单地将其日志消息写入当前存在的所有客户端连接。
这有点棘手。您的应用程序将需要能够不断地接受来自客户端的新连接,每当它们进入时,向所有并发连接写入消息,检测某些客户端是否被卡住,没有从其套接字末端读取数据,因此使本地套接字的内部缓冲区已满,因此阻塞写入将阻塞和挂起主应用程序;因此,所有写入必须是非阻塞的,应用程序将自动关闭任何变满的套接字等等。

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接