2016-09-20 5 views
-1

私はサーバー(デーモン)を開発中です。シングルスレッドサーバー/デーモン(Python)の実装

サーバーには1つの「ワーカースレッド」があります。ワーカースレッドはコマンドキューを実行します。キューが空の場合、ワーカースレッドは一時停止します(ただし、メモリ内の特定の状態を保持するため、終了しません)。メモリに状態のコピーを1つだけ入れるには、常に1つの(ゼロではなく数ではなく)ワーカースレッドを実行する必要があります。

クライアントがUnixソケットに接続してコマンドを送信すると、このキューの最後に要求が追加されます。

コマンドが発行されると、ワーカースレッドのコマンドキューに追加されます。それがキューに追加されると、サーバーは「OK」のような応答を返します。サーバーがコマンドを受信して​​から「OK」と応答するまでの間に長い休止時間はないはずです。ただし、キュー内でコマンドを実行するには時間がかかることがあります。

ワーカースレッドの主な「仕事」は、小さな(比較的短い時間で)チャンクに分割されます。チャンクの間では、ワーカースレッドはキューを検査( "食べ"、空にする)し、キューから抽出されたデータに基づいて作業を続けます。

このサーバー/デーモンをPythonで実装する方法は?

+0

私はなぜそれが単一のスレッドである必要があるのか​​尋ねることはできますか? ソケットからのメッセージをリッスンし、すぐにクライアントに返信するスレッドがあった場合、何が壊れますか。その後、リスナーとワーカーの間にキューがあり、リスナーはメッセージをこのキューにディスパッチします。それらは到着順に処理され、ワー​​カースレッドは「メモリ内の状態」が保持され、他のスレッドまたはプロセスによって混乱しないようにする必要があります。 – Hannu

+0

@ハヌー私は一人の労働者**のスレッドが必要だと主張します。ソケットリスンのための別のスレッドを持つことはOKです。 – porton

+2

ソケットリスナーのスレッドとキューで問題を解決するべきではありませんか? あなたのソケットは常に新しいメッセージを受け取ります。すぐに応答され、ワー​​カーはその状態を保存し、リクエストは到着順に処理されますか?作業者は、キューに収まるようにタスクをキューから「食べる」ことができます。 – Hannu

答えて

1

これはインターネットソケットを使用したサンプルコードで、簡単にunixドメインソケットに置き換えられています。あなたがソケットに書き込んだものを取り込み、それをworkerに「コマンド」として渡し、コマンドをキューに入れたらすぐにOKに応答します。一人の作業者は、sleep(30)で長いタスクをシミュレートします。必要な数のタスクをキューに入れ、すぐにOKを30秒ごとに受信すると、ワーカーはキューからコマンドを出力します。

import Queue, threading, socket 
from time import sleep 

class worker(threading.Thread): 
    def __init__(self,q): 
     super(worker,self).__init__() 
     self.qu = q 

    def run(self): 
     while True: 
      new_task=self.qu.get(True) 
      print new_task 
      i=0 
      while i < 10: 
       print "working ..." 
       sleep(1) 
       i += 1 
       try: 
        another_task=self.qu.get(False) 
        print another_task 
       except Queue.Empty: 
        pass   

task_queue = Queue.Queue() 
w = worker(task_queue) 
w.daemon = True 
w.start() 

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
sock.bind(('localhost', 4200)) 
sock.listen(1) 
try: 
    while True: 
     conn, addr = sock.accept() 
     data = conn.recv(32) 
     task_queue.put(data) 
     conn.sendall("OK") 
     conn.close() 
except: 
    sock.close() 
+0

ありがとうございますが、あなたのコードでは作業の途中でキューを検査することができないようです。 (私は私の(編集された)質問で、作業員の作業はキューを検査する小さな塊に分割されることを思い起こさせる) – porton

+0

それは簡単ですか?まだ別の仕事があるので、私はそれを非常に慎重に読んでいません。 – porton

+1

「作業中」のキューをチェックするコードを修正しました。キューが空であればget(False)はブロックされず、すぐに無視されるQueue.Emptyが発生します。 – Hannu