使用另一个 Socket/TCP/RPC 服务扩展现有的 Twisted 服务以获取服务信息
我正在实现一个基于 Twisted 的 Heartbeat 客户端/服务器组合,基于 这个例子。这是我的第一个 Twisted 项目。
基本上它由一个 UDP 侦听器 (Receiver
) 组成,它在接收包时调用侦听器方法 (DetectorService.update
)。 DetectorService 始终保存当前活动/非活动客户端的列表(我对示例进行了很多扩展,但核心仍然相同),从而可以对在指定超时时间内似乎已断开连接的客户端做出反应。
这是从网站获取的来源:
UDP_PORT = 43278; CHECK_PERIOD = 20; CHECK_TIMEOUT = 15
import time
from twisted.application import internet, service
from twisted.internet import protocol
from twisted.python import log
class Receiver(protocol.DatagramProtocol):
"""Receive UDP packets and log them in the clients dictionary"""
def datagramReceived(self, data, (ip, port)):
if data == 'PyHB':
self.callback(ip)
class DetectorService(internet.TimerService):
"""Detect clients not sending heartbeats for too long"""
def __init__(self):
internet.TimerService.__init__(self, CHECK_PERIOD, self.detect)
self.beats = {}
def update(self, ip):
self.beats[ip] = time.time()
def detect(self):
"""Log a list of clients with heartbeat older than CHECK_TIMEOUT"""
limit = time.time() - CHECK_TIMEOUT
silent = [ip for (ip, ipTime) in self.beats.items() if ipTime < limit]
log.msg('Silent clients: %s' % silent)
application = service.Application('Heartbeat')
# define and link the silent clients' detector service
detectorSvc = DetectorService()
detectorSvc.setServiceParent(application)
# create an instance of the Receiver protocol, and give it the callback
receiver = Receiver()
receiver.callback = detectorSvc.update
# define and link the UDP server service, passing the receiver in
udpServer = internet.UDPServer(UDP_PORT, receiver)
udpServer.setServiceParent(application)
# each service is started automatically by Twisted at launch time
log.msg('Asynchronous heartbeat server listening on port %d\n'
'press Ctrl-C to stop\n' % UDP_PORT)
此心跳服务器在后台作为守护进程运行。
现在我的问题:
我需要能够“外部”运行一个脚本来在控制台上打印接收器在其生命周期中收集的离线/在线客户端的数量(self.beats )。像这样:
$ pyhb showactiveclients
3 clients online
$ pyhb showofflineclients
1 client offline
所以我需要向我的 DetectorService 添加某种额外的服务器(Socket、Tcp、RPC - 这并不重要。要点是我能够构建具有上述行为的客户端脚本),它允许从外部连接到它。它应该只是对请求做出响应。
该服务器需要访问正在运行的 detectorservice 实例的内部变量,所以我的猜测是我必须使用某种附加服务来扩展 DetectorService。
经过几个小时的尝试将检测器服务与其他几个服务结合起来后,我仍然不知道实现该行为的最佳方法是什么。所以我希望有人至少能给我基本的提示如何开始解决这个问题。 提前致谢!!!
I'm implementing a Twisted-based Heartbeat Client/Server combo, based on this example. It is my first Twisted project.
Basically it consists of a UDP Listener (Receiver
), who calls a listener method (DetectorService.update
) on receiving packages. The DetectorService always holds a list of currently active/inactive clients (I extended the example a lot, but the core is still the same), making it possible to react on clients which seem disconnected for a specified timeout.
This is the source taken from the site:
UDP_PORT = 43278; CHECK_PERIOD = 20; CHECK_TIMEOUT = 15
import time
from twisted.application import internet, service
from twisted.internet import protocol
from twisted.python import log
class Receiver(protocol.DatagramProtocol):
"""Receive UDP packets and log them in the clients dictionary"""
def datagramReceived(self, data, (ip, port)):
if data == 'PyHB':
self.callback(ip)
class DetectorService(internet.TimerService):
"""Detect clients not sending heartbeats for too long"""
def __init__(self):
internet.TimerService.__init__(self, CHECK_PERIOD, self.detect)
self.beats = {}
def update(self, ip):
self.beats[ip] = time.time()
def detect(self):
"""Log a list of clients with heartbeat older than CHECK_TIMEOUT"""
limit = time.time() - CHECK_TIMEOUT
silent = [ip for (ip, ipTime) in self.beats.items() if ipTime < limit]
log.msg('Silent clients: %s' % silent)
application = service.Application('Heartbeat')
# define and link the silent clients' detector service
detectorSvc = DetectorService()
detectorSvc.setServiceParent(application)
# create an instance of the Receiver protocol, and give it the callback
receiver = Receiver()
receiver.callback = detectorSvc.update
# define and link the UDP server service, passing the receiver in
udpServer = internet.UDPServer(UDP_PORT, receiver)
udpServer.setServiceParent(application)
# each service is started automatically by Twisted at launch time
log.msg('Asynchronous heartbeat server listening on port %d\n'
'press Ctrl-C to stop\n' % UDP_PORT)
This heartbeat server runs as a daemon in background.
Now my Problem:
I need to be able to run a script "externally" to print the number of offline/online clients on the console, which the Receiver gathers during his lifetime (self.beats
). Like this:
$ pyhb showactiveclients
3 clients online
$ pyhb showofflineclients
1 client offline
So I need to add some kind of additional server (Socket, Tcp, RPC - it doesn't matter. the main point is that i'm able to build a client-script with the above behavior) to my DetectorService, which allows to connect to it from outside. It should just give a response to a request.
This server needs to have access to the internal variables of the running detectorservice instance, so my guess is that I have to extend the DetectorService with some kind of additionalservice.
After some hours of trying to combine the detectorservice with several other services, I still don't have an idea what's the best way to realize that behavior. So I hope that somebody can give me at least the essential hint how to start to solve this problem.
Thanks in advance!!!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
![扫码二维码加入Web技术交流群](/public/img/jiaqun_03.jpg)
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为您已经对这里的解决方案有了大致的了解,因为您已经将其应用于 Receiver 和 DetectorService 之间的交互。这个想法是让你的对象引用其他对象,让它们做他们需要做的事情。
因此,考虑一个基于
beats
数据响应请求的 Web 服务:I think you already have the general idea of the solution here, since you already applied it to an interaction between
Receiver
andDetectorService
. The idea is for your objects to have references to other objects which let them do what they need to do.So, consider a web service that responds to requests with a result based on the
beats
data: