python套接字+;多处理
我目前正在开发一个websocket实现,它允许在同一个侦听套接字上进行多处理。 我能够在四核机器上实现4个进程的惊人性能 当我向上移动时,比如8个进程,在4个请求之后,epoll.poll不再触发任何事件。有趣的是,我尝试运行相同的程序,在两个不同的端口上运行两个侦听器。每个侦听器有4个进程,每个套接字在2个请求后阻塞。每个监听器有2个进程,il都能顺利完成 有什么想法吗 main.py(摘录) wsserver.py(摘录)python套接字+;多处理,python,sockets,websocket,multiprocessing,epoll,Python,Sockets,Websocket,Multiprocessing,Epoll,我目前正在开发一个websocket实现,它允许在同一个侦听套接字上进行多处理。 我能够在四核机器上实现4个进程的惊人性能 当我向上移动时,比如8个进程,在4个请求之后,epoll.poll不再触发任何事件。有趣的是,我尝试运行相同的程序,在两个不同的端口上运行两个侦听器。每个侦听器有4个进程,每个套接字在2个请求后阻塞。每个监听器有2个进程,il都能顺利完成 有什么想法吗 main.py(摘录) wsserver.py(摘录) 好的,最后这个奇怪的案例是由我使用的另一个模块引起的。 我使用Py
好的,最后这个奇怪的案例是由我使用的另一个模块引起的。 我使用Pyro4作为管理器来跟踪哪个流程包含哪个客户机。这大大简化了IPC,还允许我根据一些用户数据进行一些客户端过滤 问题是Pyro4守护进程正在主进程上运行,但没有在主线程上运行!。。。 只要我的进程少于4个,一切都可以(不要问我为什么)。 在主进程+线程事件循环中移动Pyro,它工作得非常好! 现在,我可以为同一个侦听端口实现8个、16个或32个进程,并生成新的配置来复制它或为websocket服务器公开新的端点
感谢您的贡献,也很抱歉占用您的时间……只是好奇为什么不使用任何现有的Python websocket实现?Python以其对并行性的较差支持(我指的是它的性能)而闻名,因为现有的实现不能正确扩展。这里的目标是提供一个可扩展的实现,它可以在多个服务器、多个进程上生成。。。案例研究是用python编写的,如果我们真的不能正确扩展,C重写可能会出现在路线图上……我可以知道您测试了哪些,以及您是否在某处发布了比较结果(可能是一篇博客文章)?这些信息可能很方便。目前的私人信息。。。很抱歉。。。pyws实现的主要问题是,它们主要依赖于背后的“真正的”web服务器,这对我们不起作用。。。Tornado不错,但并不理想,因为它是多处理/线程的有限术语,可能有点离题,但是,您是否同时尝试过python2和python3?他们的行为相似吗?
#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()
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