我有一个Google App Engine应用程序,它使用Google Cloud SQL实例来存储数据。我需要我的实例能够通过restful调用一次为数百个客户端提供服务,每个调用都会导致一个或几个DB查询。我已经包装了需要DB访问的方法,并将DB连接的句柄存储在os.environ中。关于我是如何做到这一点的,请参阅this SO问题/答案。
然而,只要有几百个客户端连接到我的应用程序并触发数据库调用,我就开始在Google app Engine错误日志中收到这些错误(当然,我的应用程序返回500 ):
could not connect: ApplicationError: 1033 Instance has too many concurrent requests: 100 Traceback (most recent call last): File "/base/python27_run有经验的Google App Engine和Google Cloud SQL用户有什么建议吗?提前谢谢。
下面是我在需要DB连接的方法周围使用的装饰器的代码:
def with_db_cursor(do_commit = False):
""" Decorator for managing DB connection by wrapping around web calls.
Stores connections and open connection count in the os.environ dictionary
between calls. Sets a cursor variable in the wrapped function. Optionally
does a commit. Closes the cursor when wrapped method returns, and closes
the DB connection if there are no outstanding cursors.
If the wrapped method has a keyword argument 'existing_cursor', whose value
is non-False, this wrapper is bypassed, as it is assumed another cursor is
already in force because of an alternate call stack.
Based mostly on post by : Shay Erlichmen
At: https://stackoverflow.com/a/10162674/379037
"""
def method_wrap(method):
def wrap(*args, **kwargs):
if kwargs.get('existing_cursor', False):
#Bypass everything if method called with existing open cursor
vdbg('Shortcircuiting db wrapper due to exisiting_cursor')
return method(None, *args, **kwargs)
conn = os.environ.get("__data_conn")
# Recycling connection for the current request
# For some reason threading.local() didn't work
# and yes os.environ is supposed to be thread safe
if not conn:
conn = _db_connect()
os.environ["__data_conn"] = conn
os.environ["__data_conn_ref"] = 1
dbg('Opening first DB connection via wrapper.')
else:
os.environ["__data_conn_ref"] = (os.environ["__data_conn_ref"] + 1)
vdbg('Reusing existing DB connection. Count using is now: {0}',
os.environ["__data_conn_ref"])
try:
cursor = conn.cursor()
try:
result = method(cursor, *args, **kwargs)
if do_commit or os.environ.get("__data_conn_commit"):
os.environ["__data_conn_commit"] = False
dbg('Wrapper executing DB commit.')
conn.commit()
return result
finally:
cursor.close()
finally:
os.environ["__data_conn_ref"] = (os.environ["__data_conn_ref"] -
1)
vdbg('One less user of DB connection. Count using is now: {0}',
os.environ["__data_conn_ref"])
if os.environ["__data_conn_ref"] == 0:
dbg("No more users of this DB connection. Closing.")
os.environ["__data_conn"] = None
db_close(conn)
return wrap
return method_wrap
def db_close(db_conn):
if db_conn:
try:
db_conn.close()
except:
err('Unable to close the DB connection.', )
raise
else:
err('Tried to close a non-connected DB handle.')发布于 2012-05-04 01:09:18
简而言之:您的查询可能太慢,mysql服务器没有足够的线程来处理您试图发送给它的所有请求。
长长的答案:
作为背景,云SQL有两个限制,这里有两个相关的限制:
这听起来不像是连接限制在影响你,但我想提一下以防万一。
对于并发请求,增加限制可能会有所帮助,但这通常会使问题变得更糟。我们过去看到过两种情况:
您应该使用EXPLAIN和SHOW ENGINE INNODB STATUS来查看这两个问题中的哪一个。
当然,也有可能你只是在你的实例上驱动了大量的流量,而没有足够的线程。在这种情况下,您可能无论如何都会耗尽实例的cpu,因此添加更多的线程也无济于事。
发布于 2014-09-01 12:02:05
我阅读了文档,注意到有12个连接/实例的限制:
查找“每个App Engine实例到Google Cloud SQL实例的并发连接不能超过12个”。在https://developers.google.com/appengine/docs/python/cloud-sql/中
https://stackoverflow.com/questions/10424442
复制相似问题