【问题标题】:python socket + multiprocessingpython套接字+多处理
【发布时间】:2012-08-17 18:46:08
【问题描述】:

我目前正在研究允许在同一个监听套接字上进行多处理的 websocket 实现。 我能够在四核机器上通过 4 个进程实现惊人的性能。

当我上层时,比如 8 个进程,在 4 个请求之后,epoll.poll 不再触发任何事件。有趣的是,我尝试运行相同的程序,在 2 个不同的端口上有 2 个侦听器。每个侦听器有 4 个进程,它在每个套接字 2 个请求后阻塞。每个侦听器有 2 个进程,我都可以顺利通过它。

有什么想法吗?

ma​​in.py(提取)

#create the WSServer
wsserver = WSServer(s.bind_ip, s.bind_port, s.max_connections)
# specify on how many process we'll run
wsserver.num_process = s.num_process
Process(target=wsserver.run,args=()).start()

wsserver.py(提取)

def serve_forever_epoll(wsserver):
    log(current_process())
    epoll = select.epoll()
    epoll.register(wsserver.socket.fileno(), select.EPOLLIN)
    try:
        client_map = {}
        while wsserver.run:
            events = epoll.poll(1)
            for fileno, event in events:
                if fileno == wsserver.socket.fileno():
                    channel, details = wsserver.socket.accept()
                    channel.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
                    aclient = wsclient.WSClient(channel, wsserver, process_server.client_manager)
                    client_map[channel.fileno()] = aclient
                    epoll.register(channel.fileno(), select.EPOLLIN )
                    log('Accepting client on %s' % current_process())
                    aclient.do_handshake()

                elif event & select.EPOLLIN:
                        aclient = client_map[fileno]
                        threading.Thread(target=aclient.interact).start()

    except Exception, e:
        log(e)
    finally:
        epoll.unregister(wsserver.socket.fileno())
        epoll.close()
        wsserver.socket.close()

class WSServer():

    def __init__(self, address, port, connections):
        self.address = address
        self.port = port
        self.connections = connections
        self.onopen = onopen
        self.onclose = onclose
        log('server init')
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
        self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        #self.socket.setblocking(0)
        self.socket.bind((self.address, int(self.port)))
        self.socket.listen(self.connections)

    def run(self, *args):
        multiprocessing.log_to_stderr(logging.DEBUG)
        log("Run server")
        try:

            log("Starting Server")
            self.run = True
            serve_forever = serve_forever_epoll
            for i in range(self.num_process-1):
                log('Starting Process')
                Process(target=serve_forever,args=(self,)).start()
            serve_forever(self)

        except Exception as e:
            log("Exception-- %s " % e)
            pass

【问题讨论】:

  • 只是好奇你为什么不使用任何现有的 Python websocket 实现? Python 以其对并行性的较差支持而闻名(我的意思是它的性能)。
  • 因为现有的实现不能正确扩展。这里的目标是提供一个可扩展的实现,它可以在多个服务器、多个进程上产生......案例研究是在 python 中,如果我们真的无法正确扩展,可能会在路线图上重写 C......跨度>
  • 我可以知道您测试了哪些以及您是否在某处发布了比较结果(可能是博客文章)?这些信息可能很方便。
  • 目前的私人信息......对此感到抱歉...... pyws 实现的主要问题是它们主要依赖于背后的“真实”网络服务器,这对我们不起作用。 .. Tornado 还不错,但并不理想,因为它是有限的多处理/线程术语
  • 也许有点跑题了,但是你有没有尝试过python2和python3?他们的行为是否相似?

标签: python sockets websocket multiprocessing epoll


【解决方案1】:

好的,所以最后这个奇怪的案例是由我正在使用的另一个模块引起的。 我使用 Pyro4 作为管理器来跟踪哪个进程拥有哪个客户端。这极大地简化了 IPC,还允许我根据一些 user_data 进行一些客户端过滤。

问题是 Pyro4 守护进程在 MainProcess 上运行,但不在主线程上!... 只要我的进程少于 4 个,一切都很好(不要问我为什么)。 在主进程 + 线程事件循环中移动 Pyro,它工作得很好! 所以现在,我能够为同一个监听端口实现 8、16 或 32 个进程,以及生成新配置来复制它或为 websocket 服务器公开一个新端点!

感谢您的贡献,抱歉耽误您的时间......

【讨论】:

    猜你喜欢
    • 2018-11-20
    • 2017-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-14
    • 1970-01-01
    • 1970-01-01
    • 2014-05-31
    相关资源
    最近更新 更多