Python 在Twisted服务器上处理大容量数据包

Python 在Twisted服务器上处理大容量数据包,python,multithreading,tcp,twisted,serve,Python,Multithreading,Tcp,Twisted,Serve,我目前正在构建一个TCP服务器,该服务器将由我的公司使用,因此它必须处于高生产级别 我的要求是: 服务器将是快速的,它可以同时处理大量请求,因为我们的客户端定期发送大型文件,这将造成瓶颈 服务器将易于维护 同时支持尽可能多的用户 服务器将是TCP服务器,因为它接收我们公司开发的协议消息,我需要自己解析它 在检查了选项之后,我选择了PythonTwisted,因为他似乎满足了第一个需求,并且因为他使用Python,所以第二个需求可以自行解决 在阅读Twisted的文档后,我想到了一个问题,我还没有

我目前正在构建一个TCP服务器,该服务器将由我的公司使用,因此它必须处于高生产级别

我的要求是:

服务器将是快速的,它可以同时处理大量请求,因为我们的客户端定期发送大型文件,这将造成瓶颈

服务器将易于维护

同时支持尽可能多的用户

服务器将是TCP服务器,因为它接收我们公司开发的协议消息,我需要自己解析它

在检查了选项之后,我选择了PythonTwisted,因为他似乎满足了第一个需求,并且因为他使用Python,所以第二个需求可以自行解决

在阅读Twisted的文档后,我想到了一个问题,我还没有找到一个完美的答案,我的客户给我发送了相当大的数据包,我根据这些数据包中的子序列做出决策

假设我得到1000个字节,都是零,然后再得到5000个字节,都是0x10,我会发回Hello world,如果我得到2000个字节,都是0x50,我会回答大家好

我使用Twisted的问题是,数据最终会进入协议。协议,它们用dataReceived self,data函数处理,这个瞬间是一次性瞬间,这意味着,如果我第一次只得到一部分字节,第二次得到其余的字节,我就不知道如何保存第一次的数据

我无法将数据保存在protocol.Factory中,因为我将同时与多个客户端对话,然后其中一个客户端将使用另一个客户端的数据,原因与我无法使用全局客户端相同

我很确定我不是第一个遇到这个问题的人,我见过几个在线解决方案,包括重新实现协议。协议,它们真的不优雅

有没有一个简单而优雅的方法来解决这个问题? 这个解决方案必须是优雅的,因为我在它上面添加了多线程,因为我返回给客户机的东西远不止Hello World,而且我不想阻塞服务器

顺便说一下,如果有经验的人能为我推荐一个比Twisted更好的解决方案,我会非常高兴

多谢各位


yoko

听起来您需要在每个连接状态下维护一些。这是您可以存储并仍然使用这种协议的最小数量。您的协议类应该在每个连接上实例化一次,因此您应该能够使用该类上的属性来存储诸如Zero_received和Two S_received之类的内容

一个更简单的解决方案是缓冲来自客户机的数据,然后在连接上超时阻塞,直到收到前6k字节。我会小心过早地优化。你现在假设这将是你的瓶颈,但你的假设往往是错误的。首先使用缓冲读取器实现一个简单的解决方案,然后对速度/内存使用情况进行基准测试,看看实际需要改进什么

def dataReceived(self, data):
    self.data += data

    if len(self.data) >= 6000:
        assert all(lambda b: b == 0x00, self.data[:1000]), 'expected 0x00'
        assert all(lambda b: b == 0x10, self.data[1000:6000]), 'expected 0x10'

        # send hello

谢谢你的回复。我很抱歉,如果我没有正确地解释自己,我正在寻找一个通用的解决方案来维护每个连接状态的问题,而不是一个具体的解决方案,因为我带来的示例只是作为一个示例,它实际上不是我的协议。如果我有一个基于前100K字节的状态机,我不能使用你建议的解决方案,因为如果我实现它,我将完全阻塞我的服务器,并失去同时处理多个客户端的能力。没有通用的解决方案。我试图说明,您可以存储协议的状态,而不必存储前6k字节。我的第一个例子是一个FSM,它只需要存储2个数字就可以处理这样的协议。你不能完全不存储任何状态。但听起来你可能对twisted的工作原理有误解。Twisted使用事件循环。它一次处理多个连接。一个连接不会阻塞另一个连接,因为没有因调用dataReceived而导致的阻塞读取。将内容放在self上正是维护每个连接状态问题的通用解决方案。如果你的协议与问题中描述的不一样,那就意味着你将对数据做不同的处理,并在自己身上放不同的东西。
def dataReceived(self, data):
    self.data += data

    if len(self.data) >= 6000:
        assert all(lambda b: b == 0x00, self.data[:1000]), 'expected 0x00'
        assert all(lambda b: b == 0x10, self.data[1000:6000]), 'expected 0x10'

        # send hello