2011-09-16 6 views
2

this exampleに基づいて、ツイストベースのハートビート・クライアント/サーバー・コンボを実装しています。それは私の最初のTwistedプロジェクトです。サービス情報を取得するために、既存のツイスト・サービスを別のソケット/ TCP/RPCサービスで拡張する

基本的には、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 

だから私は、追加のサーバー(ソケット、TCP、RPCのいくつかの種類を追加する必要がある - それは重要ではありません主なポイントは、私は、クライアントスクリプトを構築することができるよということです。上記の動作)をDetectorServiceに送信します。DetectorServiceは外部からの接続を可能にします。それはちょうど要求に応答する必要があります。

このサーバーは、実行中のdetectorserviceインスタンスの内部変数にアクセスする必要があります。そのため、私はDetectorServiceをある種のadditionalalserviceで拡張する必要があります。

検出器サービスをいくつかの他のサービスと組み合わせようとしてから数時間をかけても、その動作を実現するための最良の方法が何であるかはまだ分かりません。だから、誰かがこの問題を解決するためにどのように始めるべきかについての基本的なヒントを少なくとも私に与えてくれることを願っています。 事前に感謝!

答えて

3

あなたはすでにReceiverDetectorServiceの間のやりとりにそれを適用しているので、ここでは解決策の一般的なアイデアがあると思います。このアイデアは、オブジェクトが他のオブジェクトへの参照を持つことで、必要な処理を実行できるようにすることです。

だから、beatsデータに基づく結果と要求に応答するWebサービスを考えてみます。

from twisted.web.resource import Resource 

class BeatsResource(Resource): 
    # It has no children, let it respond to the/URL for brevity. 
    isLeaf = True 

    def __init__(self, detector): 
     Resource.__init__(self) 
     # This is the idea - BeatsResource has a reference to the detector, 
     # which has the data needed to compute responses. 
     self._detector = detector 

    def render_GET(self, request): 
     limit = time.time() - CHECK_TIMEOUT 
     # Here, use that data. 
     beats = self._detector.beats 
     silent = [ip for (ip, ipTime) in beats.items() if ipTime < limit] 
     request.setHeader('content-type', 'text/plain') 
     return "%d silent clients" % (len(silent),) 

# Integrate this into the existing application 
application = service.Application('Heartbeat') 
detectorSvc = DetectorService() 
detectorSvc.setServiceParent(application) 
. 
. 
. 
from twisted.web.server import Site 
from twisted.application.internet import TCPServer 

# The other half of the idea - make sure to give the resource that reference 
# it needs. 
root = BeatsResource(detectorSvc) 
TCPServer(8080, Site(root)).setServiceParent(application) 
+0

おかげで、私は私の問題を解決することができました。しかし、 'TCPServer(8080、Site(root)).setServiceParent(application)'は動作しません(このクラスはTwisted内になく、Python内のTCPServerは 'setServiceParent'を持たないので、' reactor.listenTCP – ifischer

+0

@ifischer: 'taiTCPServer'クラス(動的に生成されます)があります。http://twistedmatrix.com/documents/current/api/twisted.application .internet.html – jfs

関連する問題