Django:与TCP服务器通信(带有扭曲?)

时间:2015-03-11 10:48:48

标签: python django tcp twisted

我有一个django应用程序,需要与远程TCP服务器通信。该服务器将发送包,并根据包的内容,我需要向数据库添加条目并通知应用程序的其他部分。我还需要主动向TCP服务器发送请求,例如当用户导航到某个页面时,我想订阅TCP服务器上的某个流。因此,双向沟通需要发挥作用。

到目前为止,我使用以下解决方案:

我写了一个自定义的Django命令,我可以从

开始
python manage.py listen

此命令将启动带有reactor.connectTCP(IP, PORT, factory)的扭曲套接字服务器,因为它是一个django命令,我将可以访问数据库和我的应用程序的所有其他部分。

但是因为我也希望能够通过某个django视图触发向TCP服务器发送内容,所以我有一个额外的套接字服务器,它在reactor.listenTCP(PORT, server_factory)的扭曲应用程序中启动。

在这个服务器上,我将直接在我的django应用程序中连接一个新线程:

class MSocket:

    def __init__(self):
        self.stopped = False
        self.socket = None
        self.queue = []
        self.process = start_new_thread(self.__connect__, ())
        atexit.register(self.terminate)


    def terminate(self):
        self.stopped = True
        try:
            self.socket.close()
        except:
            pass

    def __connect__(self):
        if self.stopped:
            return
        attempts = 0
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        while True and not self.stopped:
            try:
                print "Connecting to Socket Server..."
                self.socket.connect(("127.0.0.1", settings.SOCKET_PORT))
                print "Connection Successful!"
                for msg in self.queue:
                    self.socket.send(msg)
                self.queue = []
                break
            except:
                pause = min(int(round(1.2**attempts)), 30)
                print "Connection Failed! Try again in " + str(pause) + " seconds."
                sleep(pause)
                attempts += 1

        self.__loop__()

    def __loop__(self):
        if self.stopped:
            return
        while True and not self.stopped:
            try:
                data = self.socket.recv(1024)
            except:
                try:
                    self.socket.close()
                except:
                    pass
                break
            if not data:
                break
        self.__connect__()

    def send(self, msg):
        try:
            self.socket.send(msg)
            return True
        except:
            self.queue.append(msg)
            return False


m_socket = MSocket()

m_socket将由主urls.py导入,以便以django开头。

所以我的设置看起来很友善:

发送到TCP服务器:

Django (connect:8001) ------->  (listen:8001) Twisted (connect:4444) ------> (listen:4444) TCP-Server

从TCP服务器接收

TCP-Server (listen:4444) ------> (connect:4444) Twisted ---(direct access)---> Django

这一切似乎都是这样,但我担心这不是一个非常好的解决方案,因为我必须打开这个额外的TCP连接。所以我现在的问题是,如果可以优化设置(我确信它可以)以及如何完成设置。

3 个答案:

答案 0 :(得分:3)

除非你修补Django(如@pss所述),否则这不会起作用 我有类似的情况,所以这就是我做的。

  1. 另外一个扭曲的守护神。
  2. 要从Django通信到Twisted,请使用Unix套接字。本地扭曲的服务器可以侦听Unix套接字(AF_UNIX),Django可以简单地连接到该套接字。这将避免通过TCP堆栈
  3. 要从Twisted通信到Django,您有多种选择, a)用数据调用Django url b)启动脚本(Django管理命令) c)使用celery启动上面的Django命令 d)使用队列(zeromq或rabbit)并让您的Django管理命令侦听队列(首选)
  4. 使用最后一个选项,您可以获得更好的吞吐量,耐用性并且可以很好地扩展。

答案 1 :(得分:2)

答案 2 :(得分:1)

据我所知,问题是如何将Twisted集成到Django应用程序中。这似乎不是一个好主意,因为Twisted的事件循环阻止了这个过程。

您可以尝试使用gunicorn在非阻塞环境中运行Django,并使用gevent实现所需的所有通信。 如果那是不可能的 - 有一个answer建议standalone Django app作为在Django中使用Twisted的方法(或者更确切地说是在Twisted中的Django位)。

就个人而言,我会选择gevent。使用Twisted大约2年之后,它似乎功能强大但又老旧,沉重,难以学习且难以调试工具。