打开twisted socket客户机的Django命令会留下空闲的数据库连接

2024-09-29 19:21:01 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用twisted连接到一个socket服务器,并使用django命令运行twisted:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import json

from twisted.internet import reactor, task
from twisted.internet.protocol import ReconnectingClientFactory
from twisted.protocols.basic import LineReceiver

from django.core.management.base import BaseCommand, CommandError

from django.conf import settings


class SocketClientProtocol(LineReceiver):

    MAX_LENGTH = 64*1024*1024

    def __init__(self):
        self.setLineMode()

    def connectionMade(self):
        print "CONNECTION ESTABLISHED"

    def connectionLost(self, reason):
        print "CONNECTION LOST"
        print reason.getErrorMessage()

    def lengthLimitExceeded(self, length):
        print "EXCEED"
        print length

    def lineReceived(self, msg):
        data = json.loads(msg)
        #do sth with the data from the socket server
        handle_message(data["type"], data["data"])


class SocketClientFactory(ReconnectingClientFactory):

    def startedConnecting(self, connector):
        print 'Started to connect.'

    def buildProtocol(self, addr):
        print 'Connected'
        self.resetDelay()
        return SocketClientProtocol()

    def clientConnectionLost(self, connector, reason):
        print 'Lost connection.  Reason:', reason
        ReconnectingClientFactory.clientConnectionLost(self, connector, reason)

    def clientConnectionFailed(self, connector, reason):
        print 'Connection failed. Reason:', reason
        ReconnectingClientFactory.clientConnectionFailed(self, connector, reason)

class Command(BaseCommand):

    def handle(self, *args, **options):
        client_factory = SocketClientFactory()
        reactor.connectUNIX(settings.UNIX_OUT_SOCKET, client_factory)
        reactor.run()

我通过python manage.py connect启动这个命令,然后让进程在Apache后面的wsgi web服务器旁边运行。这很好地工作,但是我遇到了一个问题:在这个socket客户机中启动的数据库连接通常不会正确关闭,而只是作为开放和空闲连接堆积起来。在

select * from pg_stat_activity where datname = 'lt';的输出:

^{pr2}$

在某些情况下,这会导致以下错误:

OperationalError: FATAL:  remaining connection slots are reserved for non-replication superuser connections

上面列出的查询由此函数生成:

def get_audio_stream(audiostream_id):
    try:
        return AudioStream.objects.get(id=audiostream_id)
    except AudioStream.DoesNotExist:
        return None

所以我只是想通过对象的id来获取一个对象。据我所知,Django应该在之后关闭连接,但它没有。Is不是唯一一个不时挂起的查询,其他查询也是如此。但这次是最常见的一次。在

我使用的是最新的django(9.6)、twisted 15.5和postgresql9.3。我已经尝试过将CONN_MAX_AGE设置为不同的值,但没有成功。在

那么这个问题的原因是什么呢?是因为我在这个扭曲的引擎后面运行吗?我怎样才能修好它?在


Tags: djangofromimportselfiddataconnectordef
1条回答
网友
1楼 · 发布于 2024-09-29 19:21:01

在您上面发布的代码中似乎没有创建到postgres的连接的代码。问题出在其他地方,也许上面代码连接到的服务器代码在客户端断开连接时没有关闭数据库连接。在

编辑:如果在非WSGI应用程序中使用Django-ORM调用,则数据库连接不会自动关闭。自动连接管理只在WSGI请求的上下文中完成。它通过signals.request_finished信号来实现这一点。在

您可以使用以下代码手动管理连接并在不需要时关闭它们:

from django import db

# Use this to close all configured db connections after your query code.
# Note that Django ORM performs lazy queries, i.e. only executing SQL if
# you access the Model object properties retrieved from DB. So you should
# do this after you have finished ORM object tasks.
db.connections.close_all()

# or use this
db.connection.close()

# or for more control over which connection:
db.connections['default'].close()  # closes the default DB connection

如果您要手动管理连接,您还需要手动管理事务。在

相关问题 更多 >

    热门问题