StreamingHttpResponse:返回数据库连接到池中/关闭它

问题描述 投票:4回答:1

如果您从Django视图返回了StreamingHttpResponse,它何时将任何数据库连接返回到池?如果默认情况下在StreamingHttpResponse完成后执行此操作,是否有办法更早地返回连接?

def my_view(request):
  # Some database queries using the Django ORM
  # ...

  def yield_data():
    # A generator, with no database queries using the Django ORM
    # ...

  return StreamingHttpResponse(
    yield_data(), status=200
  )

[如果有所作为,这是将https://pypi.org/project/django-db-geventpool/与Gunicorn一起使用,并且在使用pytest.mark.django_db进行测试(我认为将测试包装在交易中)时,任何答案也应该有效。

python django postgresql pytest gevent
1个回答
5
投票

如果您查看文档

https://docs.djangoproject.com/en/3.0/ref/databases/

连接管理

Django在首次进行数据库查询时会打开与数据库的连接。它使该连接保持打开状态,并在后续请求中重用它。超过CONN_MAX_AGE定义的最长期限或不再可用时,Django将关闭连接。

详细来说,Django会在需要数据库且尚不存在时自动打开与数据库的连接-要么是因为这是第一个连接,要么是因为上一个连接已关闭。

在每个请求的开始,如果Django已达到其最大使用期限,则会关闭该连接。如果您的数据库在一段时间后终止了空闲连接,则应将CONN_MAX_AGE设置为较低的值,以便Django不会尝试使用已被数据库服务器终止的连接。 (此问题可能只影响流量非常小的站点。)

在每个请求结束时,如果Django已达到其最大使用期限或处于不可恢复的错误状态,它将关闭该连接。如果处理请求时发生任何数据库错误,则Django会检查连接是否仍然有效,如果没有,则将其关闭。因此,数据库错误最多影响一个请求。如果连接不可用,则下一个请求将获得新的连接。

也可以在db/__init__.py源代码中看到django

# For backwards compatibility. Prefer connections['default'] instead.
connection = DefaultConnectionProxy()


# Register an event to reset saved queries when a Django request is started.
def reset_queries(**kwargs):
    for conn in connections.all():
        conn.queries_log.clear()


signals.request_started.connect(reset_queries)


# Register an event to reset transaction state and close connections past
# their lifetime.
def close_old_connections(**kwargs):
    for conn in connections.all():
        conn.close_if_unusable_or_obsolete()


signals.request_started.connect(close_old_connections)
signals.request_finished.connect(close_old_connections)

request_startedrequest_finished信号连接,以使用close_old_connections关闭旧连接。

因此,如果您不愿意等待连接关闭,则可以自己调用此方法。您更新的代码如下所示

from django.db import close_old_connections

def my_view(request):
  # Some database queries using the Django ORM
  # ...
  close_old_connections()

  def yield_data():
    # A generator, with no database queries using the Django ORM
    # ...

  return StreamingHttpResponse(
    yield_data(), status=200
  )
© www.soinside.com 2019 - 2024. All rights reserved.