我目前正在开发一个使用 python 3.7、Django 2.1、Mysql 作为数据库的项目。
我正在谷歌云应用引擎标准环境中部署它,对于数据库,我使用的是云 SQL - MySql 第二代实例。
该应用程序运行良好,但是当我分析日志时,我看到以下错误:
"连接中止 - 读取通信数据包时出错">
在这种情况下,我的应用程序(django)正在关闭连接。如果我将我的应用程序配置为具有持久连接,并将wait_timeout(即 60)放入云 sql 的配置中,则错误为:
"连接中止 - 读取通信数据包超时"。
我刚刚确定这不是sql云的问题,也不是我的应用程序的配置问题,而是应用程序引擎的问题。我得出这个结论
的方式如下:- 如果我通过 Mysql 工作台连接到 sql 云实例,则不会中止任何连接
- 同样,如果我在本地服务器上运行我的应用程序,但连接到云 sql(通过 cloud_sql_proxy),则不会生成错误,并且一切正常。
所以我的结论是,这是应用程序引擎如何连接到云 sql 实例的问题。
为什么会这样?如何解决?
您看到的"连接中止"消息通常在连接关闭不正确或服务器和客户端之间存在网络异常时触发。
-
有时,云 SQL 实例和 GAE 具有长期空闲连接。为了解决此问题,建议将"wait_timeout"标志设置为低于 600 秒 - 因为您已经尝试这样做。
-
另一种可能的解决方案是实现应用程序级保持连接。SQLAlchemy 为此提供了"预 ping"。否则,通过定期发送简单的 SQL 语句(如"SELECT 1;"),至少每 5 分钟发送一次,在所有打开的连接上生成活动。还可以考虑在代码中使用诸如"with db.connect() as conn:"之类的语句来控制连接的生存期。
我相信这是因为从 App Engine 应用程序到 Cloud SQL 的请求受到以下时间和连接限制的约束:
- 对于在 App Engine 标准环境中运行的应用,所有数据库请求都必须在 HTTP 请求计时器(大约 60 秒)内完成。对于在灵活环境中运行的应用,所有数据库请求必须在 60 分钟内完成。
- 像 cron 任务这样的离线请求的时间限制为 10 分钟。
- 对 Cloud SQL 的请求有限制,具体取决于 App Engine 模块的扩展类型以及实例可以在内存中保留的时间(驻留)。
- 在标准环境中运行的每个 App Engine 实例与 Cloud SQL 实例的并发连接数不能超过 60 个。对于用 Java 8 或 Go 1.8 编写的应用程序,限制为 100。
- 连接问题:如果您看到包含"nnnn 到 db 的连接中止:"的错误,这通常表示您的应用程序未正确终止连接。它也可能是由网络问题引起的。此错误并不意味着您的云 SQL 实例存在问题。