Cloud Functions "Connection Refused" 连接到 Cloud SQL
Cloud Functions "Connection Refused" when connecting to Cloud SQL
我正在尝试按照 example provided by Google 使用 Python 和 MySQL 实例将 Cloud Functions 脚本连接到 Cloud SQL。
我在项目中创建了一个 Cloud SQL 实例,然后创建了一个 Cloud Function,我在其中将整个脚本从 link 粘贴到内联编辑器中。我将环境变量设置为连接到 Cloud SQL 所需的值,但出现错误。
为了完成这项工作,我是否缺少一些明显的东西?
Error: function crashed. Details:
(2003, "Can't connect to MySQL server on 'localhost' ([Errno 111] Connection refused)")
Traceback (most recent call last): File "/env/local/lib/python3.7/site-packages/pymysql/connections.py", line 582, in connect **kwargs) File "/opt/python3.7/lib/python3.7/socket.py", line 727, in create_connection raise err File "/opt/python3.7/lib/python3.7/socket.py", line 716, in create_connection sock.connect(sa) ConnectionRefusedError: [Errno 111] Connection refused During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/user_code/main.py", line 49, in mysql_demo mysql_conn = pymysql.connect(**mysql_config) File "/env/local/lib/python3.7/site-packages/pymysql/init.py", line 94, in Connect return Connection(*args, **kwargs) File "/env/local/lib/python3.7/site-packages/pymysql/connections.py", line 327, in init self.connect() File "/env/local/lib/python3.7/site-packages/pymysql/connections.py", line 629, in connect raise exc pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on 'localhost' ([Errno 111] Connection refused)") During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/env/local/lib/python3.7/site-packages/pymysql/connections.py", line 570, in connect sock.connect(self.unix_socket) ConnectionRefusedError: [Errno 111] Connection refused During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/env/local/lib/python3.7/site-packages/google/cloud/functions_v1beta2/worker.py", line 297, in run_http_function result = _function_handler.invoke_user_function(flask.request) File "/env/local/lib/python3.7/site-packages/google/cloud/functions_v1beta2/worker.py", line 199, in invoke_user_function return call_user_function(request_or_event) File "/env/local/lib/python3.7/site-packages/google/cloud/functions_v1beta2/worker.py", line 192, in call_user_function return self._user_function(request_or_event) File "/user_code/main.py", line 53, in mysql_demo mysql_conn = pymysql.connect(**mysql_config) File "/env/local/lib/python3.7/site-packages/pymysql/init.py", line 94, in Connect return Connection(*args, **kwargs) File "/env/local/lib/python3.7/site-packages/pymysql/connections.py", line 327, in init self.connect() File "/env/local/lib/python3.7/site-packages/pymysql/connections.py", line 629, in connect raise exc pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on 'localhost' ([Errno 111] Connection refused)")
我遇到了同样的问题,在与 Google 反复讨论后,终于为我解决了这个问题。
示例显示以下 try 子句:
if not mysql_conn:
try:
mysql_conn = pymysql.connect(**mysql_config)
except OperationalError:
# If production settings fail, use local development ones
mysql_config['unix_socket'] = f'/cloudsql/{CONNECTION_NAME}'
mysql_conn = pymysql.connect(**mysql_config)
我改成了:
if not mysql_conn:
mysql_config['unix_socket'] = f'/cloudsql/{CONNECTION_NAME}'
mysql_conn = pymysql.connect(**mysql_config)
并使用 (data, context)
作为函数参数而不是 (request)
这是我最终得到的测试函数:
from os import getenv
import pymysql
from pymysql.err import OperationalError
CONNECTION_NAME = getenv(
'INSTANCE_CONNECTION_NAME',
'connection_name')
DB_USER = getenv('MYSQL_USER', 'username')
DB_PASSWORD = getenv('MYSQL_PASSWORD', 'password')
DB_NAME = getenv('MYSQL_DATABASE', 'database')
mysql_config = {
'user': DB_USER,
'password': DB_PASSWORD,
'db': DB_NAME,
'charset': 'utf8mb4',
'cursorclass': pymysql.cursors.DictCursor,
'autocommit': True
}
if getenv('NODE_ENV', '') == 'production':
mysql_config['unix_socket'] = f'/cloudsql/{CONNECTION_NAME}'
# Create SQL connection globally to enable reuse
# PyMySQL does not include support for connection pooling
mysql_conn = None
def __get_cursor():
"""
Helper function to get a cursor
PyMySQL does NOT automatically reconnect,
so we must reconnect explicitly using ping()
"""
try:
return mysql_conn.cursor()
except OperationalError:
mysql_conn.ping(reconnect=True)
return mysql_conn.cursor()
def mysql_demo(data, context):
global mysql_conn
# Initialize connections lazily, in case SQL access isn't needed for this
# GCF instance. Doing so minimizes the number of active SQL connections,
# which helps keep your GCF instances under SQL connection limits.
if not mysql_conn:
mysql_conn = pymysql.connect(**mysql_config)
# Remember to close SQL resources declared while running this function.
# Keep any declared in global scope (e.g. mysql_conn) for later reuse.
with __get_cursor() as cursor:
cursor.execute('SELECT NOW() as now')
results = cursor.fetchone()
return str(results['now'])
非常重要的信息:
在开始之前,您需要前往 GCP IAM 将云 SQL 管理员角色添加到云功能服务帐户。服务账号信息可以在云功能的通用选项卡中找到。完成此操作后,您应该可以开始了。如果没有,请尝试向您的云功能服务帐户添加更多角色,例如项目编辑器。
代码参考,(仅修改部分)
# TODO(developer): specify SQL connection details
CONNECTION_NAME = getenv(
'INSTANCE_CONNECTION_NAME',
'proj-chatbot-og:us-central1:your connection name')
# Please don't change the name on the left like MYSQL_USER
DB_USER = getenv('MYSQL_USER', 'your user name')
DB_PASSWORD = getenv('MYSQL_PASSWORD', 'your password')
DB_NAME = getenv('MYSQL_DATABASE', 'your sql database')
mysql_config = {
'user': DB_USER,
'password': DB_PASSWORD,
'db': DB_NAME,
'charset': 'utf8mb4',
'cursorclass': pymysql.cursors.DictCursor,
'autocommit': True
}
可以在此处找到完整的文档https://cloud.google.com/functions/docs/sql
如果您发现解决方案解决了您的问题,请为解决方案投票。
同样的问题,但是
- 在 App Engine Standard 和 PostgreSQL
- Cloud SQL 运行ning 在一个 不同的 项目 B 中,而不是 运行ning 在项目 A.
潜在问题 看起来与相同。
遵循 the tutorial to the dot (again, this is for Postgres, not MySQL), and thus using sample code from here,使事情几乎立即生效的解决方案(没有注意到配置延迟):
- 在项目 A 的 IAM & Admin 部分查找主要服务帐户的电子邮件地址;它的格式应该是 <您的项目 ID>@appspot.gserviceaccount.com
- 在项目 B 中,在 IAM & Admin 下添加一行,并将此电子邮件地址作为 principal 和角色 云 SQL 客户端
教程讲
If the authorizing service account belongs to a different project than the Cloud SQL instance, the Cloud SQL Admin API and IAM permissions will need to be added for both projects.
我确实将 Cloud SQL API 和 Cloud SQL Admin API 添加到 both 项目,但没有提供项目 A 中的服务帐户任何与云 SQL 相关的权限——如果这就是教程所讨论的内容。
以上意味着如果 Cloud SQL 和应用程序代码 运行 在同一个项目 中,添加 Cloud SQL Client 项目服务帐户的角色应该是所需要的。 (角色 Cloud SQL Admin,正如@Zou Dino 所建议的那样不是必需的,但也应该有效。)
我正在尝试按照 example provided by Google 使用 Python 和 MySQL 实例将 Cloud Functions 脚本连接到 Cloud SQL。
我在项目中创建了一个 Cloud SQL 实例,然后创建了一个 Cloud Function,我在其中将整个脚本从 link 粘贴到内联编辑器中。我将环境变量设置为连接到 Cloud SQL 所需的值,但出现错误。
为了完成这项工作,我是否缺少一些明显的东西?
Error: function crashed. Details: (2003, "Can't connect to MySQL server on 'localhost' ([Errno 111] Connection refused)")
Traceback (most recent call last): File "/env/local/lib/python3.7/site-packages/pymysql/connections.py", line 582, in connect **kwargs) File "/opt/python3.7/lib/python3.7/socket.py", line 727, in create_connection raise err File "/opt/python3.7/lib/python3.7/socket.py", line 716, in create_connection sock.connect(sa) ConnectionRefusedError: [Errno 111] Connection refused During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/user_code/main.py", line 49, in mysql_demo mysql_conn = pymysql.connect(**mysql_config) File "/env/local/lib/python3.7/site-packages/pymysql/init.py", line 94, in Connect return Connection(*args, **kwargs) File "/env/local/lib/python3.7/site-packages/pymysql/connections.py", line 327, in init self.connect() File "/env/local/lib/python3.7/site-packages/pymysql/connections.py", line 629, in connect raise exc pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on 'localhost' ([Errno 111] Connection refused)") During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/env/local/lib/python3.7/site-packages/pymysql/connections.py", line 570, in connect sock.connect(self.unix_socket) ConnectionRefusedError: [Errno 111] Connection refused During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/env/local/lib/python3.7/site-packages/google/cloud/functions_v1beta2/worker.py", line 297, in run_http_function result = _function_handler.invoke_user_function(flask.request) File "/env/local/lib/python3.7/site-packages/google/cloud/functions_v1beta2/worker.py", line 199, in invoke_user_function return call_user_function(request_or_event) File "/env/local/lib/python3.7/site-packages/google/cloud/functions_v1beta2/worker.py", line 192, in call_user_function return self._user_function(request_or_event) File "/user_code/main.py", line 53, in mysql_demo mysql_conn = pymysql.connect(**mysql_config) File "/env/local/lib/python3.7/site-packages/pymysql/init.py", line 94, in Connect return Connection(*args, **kwargs) File "/env/local/lib/python3.7/site-packages/pymysql/connections.py", line 327, in init self.connect() File "/env/local/lib/python3.7/site-packages/pymysql/connections.py", line 629, in connect raise exc pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on 'localhost' ([Errno 111] Connection refused)")
我遇到了同样的问题,在与 Google 反复讨论后,终于为我解决了这个问题。
示例显示以下 try 子句:
if not mysql_conn:
try:
mysql_conn = pymysql.connect(**mysql_config)
except OperationalError:
# If production settings fail, use local development ones
mysql_config['unix_socket'] = f'/cloudsql/{CONNECTION_NAME}'
mysql_conn = pymysql.connect(**mysql_config)
我改成了:
if not mysql_conn:
mysql_config['unix_socket'] = f'/cloudsql/{CONNECTION_NAME}'
mysql_conn = pymysql.connect(**mysql_config)
并使用 (data, context)
作为函数参数而不是 (request)
这是我最终得到的测试函数:
from os import getenv
import pymysql
from pymysql.err import OperationalError
CONNECTION_NAME = getenv(
'INSTANCE_CONNECTION_NAME',
'connection_name')
DB_USER = getenv('MYSQL_USER', 'username')
DB_PASSWORD = getenv('MYSQL_PASSWORD', 'password')
DB_NAME = getenv('MYSQL_DATABASE', 'database')
mysql_config = {
'user': DB_USER,
'password': DB_PASSWORD,
'db': DB_NAME,
'charset': 'utf8mb4',
'cursorclass': pymysql.cursors.DictCursor,
'autocommit': True
}
if getenv('NODE_ENV', '') == 'production':
mysql_config['unix_socket'] = f'/cloudsql/{CONNECTION_NAME}'
# Create SQL connection globally to enable reuse
# PyMySQL does not include support for connection pooling
mysql_conn = None
def __get_cursor():
"""
Helper function to get a cursor
PyMySQL does NOT automatically reconnect,
so we must reconnect explicitly using ping()
"""
try:
return mysql_conn.cursor()
except OperationalError:
mysql_conn.ping(reconnect=True)
return mysql_conn.cursor()
def mysql_demo(data, context):
global mysql_conn
# Initialize connections lazily, in case SQL access isn't needed for this
# GCF instance. Doing so minimizes the number of active SQL connections,
# which helps keep your GCF instances under SQL connection limits.
if not mysql_conn:
mysql_conn = pymysql.connect(**mysql_config)
# Remember to close SQL resources declared while running this function.
# Keep any declared in global scope (e.g. mysql_conn) for later reuse.
with __get_cursor() as cursor:
cursor.execute('SELECT NOW() as now')
results = cursor.fetchone()
return str(results['now'])
非常重要的信息:
在开始之前,您需要前往 GCP IAM 将云 SQL 管理员角色添加到云功能服务帐户。服务账号信息可以在云功能的通用选项卡中找到。完成此操作后,您应该可以开始了。如果没有,请尝试向您的云功能服务帐户添加更多角色,例如项目编辑器。
代码参考,(仅修改部分)
# TODO(developer): specify SQL connection details
CONNECTION_NAME = getenv(
'INSTANCE_CONNECTION_NAME',
'proj-chatbot-og:us-central1:your connection name')
# Please don't change the name on the left like MYSQL_USER
DB_USER = getenv('MYSQL_USER', 'your user name')
DB_PASSWORD = getenv('MYSQL_PASSWORD', 'your password')
DB_NAME = getenv('MYSQL_DATABASE', 'your sql database')
mysql_config = {
'user': DB_USER,
'password': DB_PASSWORD,
'db': DB_NAME,
'charset': 'utf8mb4',
'cursorclass': pymysql.cursors.DictCursor,
'autocommit': True
}
可以在此处找到完整的文档https://cloud.google.com/functions/docs/sql
如果您发现解决方案解决了您的问题,请为解决方案投票。
同样的问题,但是
- 在 App Engine Standard 和 PostgreSQL
- Cloud SQL 运行ning 在一个 不同的 项目 B 中,而不是 运行ning 在项目 A.
潜在问题 看起来与相同。
遵循 the tutorial to the dot (again, this is for Postgres, not MySQL), and thus using sample code from here,使事情几乎立即生效的解决方案(没有注意到配置延迟):
- 在项目 A 的 IAM & Admin 部分查找主要服务帐户的电子邮件地址;它的格式应该是 <您的项目 ID>@appspot.gserviceaccount.com
- 在项目 B 中,在 IAM & Admin 下添加一行,并将此电子邮件地址作为 principal 和角色 云 SQL 客户端
教程讲
If the authorizing service account belongs to a different project than the Cloud SQL instance, the Cloud SQL Admin API and IAM permissions will need to be added for both projects.
我确实将 Cloud SQL API 和 Cloud SQL Admin API 添加到 both 项目,但没有提供项目 A 中的服务帐户任何与云 SQL 相关的权限——如果这就是教程所讨论的内容。
以上意味着如果 Cloud SQL 和应用程序代码 运行 在同一个项目 中,添加 Cloud SQL Client 项目服务帐户的角色应该是所需要的。 (角色 Cloud SQL Admin,正如@Zou Dino 所建议的那样不是必需的,但也应该有效。)