谷歌应用引擎和云SQL:在“读取初始通信数据包”时与MySQL服务器断开连接

12

我在Google App Engine上有一个Django应用程序,连接到Google Cloud SQL,使用App Engine身份验证

大多数时候一切正常,但是偶尔会出现以下异常:

OperationalError: (2013, "Lost connection to MySQL server at 'reading initial communication packet', system error: 38")

根据文档,发生此错误的原因可能是:

如果Google Cloud SQL拒绝连接,例如因为您的客户端连接的IP地址未被授权。

在我的情况下,这并不太合理,因为身份验证是由App Engine服务器完成的。

什么可能会导致这些零星的错误?


你的应用程序已经部署到云端了吗?你不是在本地运行吧? - Gwell
是的,它在GAE云上。 - Tzach
我无法找到关于错误38的确切信息。但是,大多数关于“在读取初始命令时失去与MySQL服务器的连接等”错误都与SQL设置有关,特别是超时和授权,但这些都是本地主机问题。请查看此文档:https://developers.google.com/cloud-sql/docs/admin-api/v1beta1/instances/update,并查看您的Cloud SQL实例中是否有任何设置可以解决此问题。 - Gwell
你是否将你的应用程序设置为仅在欧盟服务器上运行? - Gwell
@Gwell 谢谢。我找不到任何与我的问题相关的设置。大多数情况下,一切都运行良好,所以除非我知道它能解决我的问题,否则我不想更改生产环境中的任何内容。我没有将我的应用程序限制在欧盟范围内。 - Tzach
1
我偶尔也会遇到同样的问题。我在AppEngine上使用CloudSQL运行Django 1.5,有时会出现完全相同的错误。 - Aaron
4个回答

16
我也经历了类似的问题,最后联系谷歌寻求帮助。他们解释说,当需要重新启动或移动一个实例时,会出现这种情况。如果客户端实例重新启动或移动到另一台主机服务器(各种版本都有可能),IP地址将不匹配并引发该错误。他们提到服务器可能因补丁、错误和减速而重新启动,导致类似的行为(无论是同样的错误还是相似的错误)。服务器也会移动,以尽量靠近实例来增加响应时间。如果你在移动期间发送请求,会出现错误。
他们告诉我,我需要编写重试捕获代码以防此类情况发生,就像处理数据存储超时的方式一样。记住要构建退避机制,过于频繁地在重新启动后发送请求可能会导致崩溃。
这种情况发生的频率有多高?

2
https://developers.google.com/cloud-sql/faq#maintenancerestart https://developers.google.com/appengine/articles/handling_datastore_errors http://en.wikipedia.org/wiki/Exponential_backoff - Ryan
谢谢,听到Google的回应很有趣。我们的代码确实有重试和指数退避,但也许重试次数太少了。你们的代码重试多少次,使用什么退避策略?重试解决了问题吗? - Tzach
对我来说,如果尝试3次仍然失败,我会将其发送到任务队列。根据实例的全局超时时间,您可以选择更高的重试次数。我的任务队列很少被触发,但我曾经见过一两次。您等待多长时间?这种情况每个月是否发生超过几次? - Ryan
这种情况发生的频率不止两个月两次。重试5次,每次间隔5秒,并采用x2退避策略。这是一个基本的扩展实例,因此没有全局超时。 - Tzach
那比我之前得到的要多得多。如果新的回退有帮助,请告诉我。 - Ryan
显示剩余3条评论

3
在我们的情况下,我们在代码中错误地重命名了实例。当我们改回正确的名称后,一切正常。请确保您的Cloud SQL实例在Google Cloud Console内外以及用于访问它的代码内都被正确命名,并确保您的Cloud SQL实例允许您的Google App Engine实例连接到它的Access control

这与原问题无关。99%的时间它都能正常工作。 - glmvrml

1
在我的情况下,问题是由于CloudSQL实例上的服务器SSL证书过期引起的。奇怪的是,在Google Cloud控制台中没有显示它,只有在下载证书并使用openssl进行解码后才发现它(openssl x509 -in server-ca.pem -text -noout)。
尝试使用cloud_sql_proxy连接后,我能够找出问题的原因;幸运的是,它给出了更有意义的错误消息couldn't connect to "...": x509: certificate has expired or is not yet valid
从AppEngine标准应用程序连接立即开始工作,仅需从Google Cloud控制台重置SSL配置即可。我注意到,在重置后,有效日期会显示在控制台上。

1
重置 SSL 对我有帮助,即使已下载的证书仍然有效。 - Kirill Cherepanov

-1
我也遇到了这个问题,使用Django 1.10和GAE。应用程序在本地运行良好(通过cloud_sql_proxy连接云sql),但是在使用应用程序的GAE实例时会出现38错误。
我的问题最终是我的数据库用户。该用户中有一个连字符。一旦我创建了一个没有连字符的新用户并更改了我的应用程序以使用新用户,则应用程序的GAE实例就可以正常工作。

这与原问题无关。99%的时间它都能正常工作。 - glmvrml

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接