【问题标题】:Implementing a single thread server/daemon (Python)实现单线程服务器/守护进程(Python)
【发布时间】:2016-09-20 15:24:46
【问题描述】:

我正在开发一个服务器(守护进程)。

服务器有一个“工作线程”。工作线程运行命令队列。当队列为空时,工作线程会暂停(但不会退出,因为它应该在内存中保留某些状态)。要在内存中准确地保存一份状态副本,我需要一直运行一个(不是多个也不是零个)工作线程。

当客户端连接到 Unix 套接字并发送命令时,请求被添加到此队列的末尾。

命令发出后,加入到工作线程的命令队列中。将其添加到队列后,服务器会回复“OK”之类的内容。服务器收到命令和它“OK”回复之间不应该有很长时间的停顿。但是,在队列中运行命令可能需要一些时间。

工作线程的主要“工作”被分成小块(花费相对较少的时间)。在块之间,工作线程检查(“吃”并清空)队列并根据从队列中提取的数据继续工作。

如何在 Python 中实现这个服务器/守护进程?

【问题讨论】:

  • 请问为什么需要单线程?如果您有一个线程可以监听来自套接字的消息并立即向客户端回复“ok”,那将会发生什么问题。然后,您将在侦听器和工作人员之间建立一个队列,并且侦听器只会将消息发送到该队列。它们将按到达的顺序进行处理,并且工作线程应该保留其“内存中的状态”,并且不会被任何其他线程或进程弄乱。
  • @Hannu 我坚持我需要单个 worker 线程。有另一个线程监听套接字是可以的。
  • 不应该一个套接字监听线程和一个队列然后解决你的问题吗?您的套接字将始终接受新消息,它们会立即得到响应,工作人员会保留其状态,并且请求将按照到达的顺序进行处理?然后,您的工作人员可以根据需要从队列中“吃掉”任务。
  • @Hannu 感谢您的想法。我会研究它(也许明天)。您能否详细介绍一下您的想法?

标签: python sockets server daemon


【解决方案1】:

这是一个带有互联网套接字的示例代码,可以很容易地替换为 unix 域套接字。它将您写入套接字的任何内容,将其作为“命令”传递给工作人员,一旦将命令排入队列,就会响应 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()

【讨论】:

  • 非常感谢,但您的代码似乎不允许工作人员在任务中间检查队列。 (我提醒一下,在我的(已编辑)问题中,工作人员的工作被分成小块,在它们之间检查队列。)
  • 或者容易吗?我还没有仔细阅读,因为我还有另一份工作
  • 我已经修改了代码以包括在“工作”时检查队列。如果队列为空,get(False) 不会阻塞,它只会引发 Queue.Empty,它会立即被忽略。
  • 经过深思熟虑后,我得出结论,在请求中我不应该只打印“OK”,而是首先进行一些快速计算(在此回复之后,OK 或 ERROR)并且这些计算应该在工作线程(或与工作线程同步),以便它们不会与工作线程中的另一个操作同时运行,而是按顺序运行。我想看修改后的代码(但不要删除你已经写的!)对不起,你为我做的工作,但我想看修改后的代码(在旧版本的代码中)不应删除)
  • 请注意,在前面的评论中,我假设响应请求的计算应该在工作线程的当前“小块”完成之前开始
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-15
  • 2011-07-13
  • 2011-08-19
  • 1970-01-01
相关资源
最近更新 更多