繁体   English   中英

客户端连接后使用100%CPU的python asyncore

[英]python asyncore using 100% CPU after client connects

我正在使用asyncore来实现发布订阅。 我理解使用twisted或ZMQ可能是一个更好的解决方案,但在这种情况下它需要是纯python。 等待连接时,CPU使用率约为1%,一旦客户端连接CPU使用率跳转写入高达100%。 即使客户端断开连接,它也不会降回。

我的服务器类:

class Host(asyncore.dispatcher):

    log = logging.getLogger('Host')

    def __init__(self, port=7655):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.set_reuse_addr()
        self.bind(('0.0.0.0', port,))
        self.listen(5)
        self.clients = []

    def handle_accept(self):
        socket, addr = self.accept()
        self.log.info("Aceepted client at {0}:{1}".format(addr[0], addr[1]))
        self.clients.append(RemoteClient(self, socket, addr))

    def broadcast(self, message):
        self.log.info("Broadcasting message: {0}".format(message))
        for client in self.clients:
            client.message(message)

我的经纪人:

class RemoteClient(asyncore.dispatcher):

    log = logging.getLogger('Host')

    def __init__(self, host, socket, address):
        asyncore.dispatcher.__init__(self, socket)
        self.host = host
        self.outbox = collections.deque()

    def message(self, message):
        self.outbox.append(message)

    def handle_write(self):
        if not self.outbox:
            return
        message = self.outbox.popleft()
        if len(message) > MAX_MESSAGE_LENGTH:
            raise ValueError('Message too long')
        self.send(message)

    def handle_close(self):
        self.host.clients.remove(self)
        self.log.info("Client removed from list")
        self.close()

    def handle_error(self):
        self.log.error("Socket error")

我曾尝试寻求解决方案,但似乎无法解决发生的事情。 任何帮助赞赏!

说明

您的问题是您没有覆盖方法asyncore.dispatcher.writeable ,默认实现:

def writable(self):
    return True

这导致asyncore.pollwhile True循环中运行(因此使用100%CPU):

def poll(timeout=0.0, map=None):
    if map is None:
        map = socket_map
    if map:
        r = []; w = []; e = []
        for fd, obj in map.items():
            is_r = obj.readable()
            is_w = obj.writable() # This is always true
            if is_r:
                r.append(fd)
            if is_w:
                w.append(fd)
            if is_r or is_w:
                e.append(fd) # This always happens
        if [] == r == w == e:
            time.sleep(timeout) # This never happens
            return

        try:
            # Here, having w (as function parameter) set to non-empty value
            # causes select to immediately return without waiting with w set
            # just to your client
            r, w, e = select.select(r, w, e, timeout) 

我认为真正干净的解决方案是重新实现asyncore与某种threading.Event机制,强制等待可写对象,但到目前为止,这对我有用:

# Add to RemoteClient
def writable(self):
    ''' It has point to call handle_write only when there's something in outbox
        Having this method always returning true will cause 100% CPU usage
    '''
    return bool(self.outbox)

# When you start loop
asyncore.loop(timeout=5.0) 

您还可以在官方文档中的示例中看到writable()被覆盖。

我只是希望能够比30秒后更快地等待。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM