JJC*_*JJC 9 python mysql google-app-engine wsgi google-cloud-sql
我有一个Google App Engine应用程序,它使用Google Cloud SQL实例存储数据.我需要我的实例能够通过休息调用一次为数百个客户端提供服务,每个客户端都会产生一个或几个数据库查询.我已经包装了需要DB访问的方法,并将句柄存储到os.environ中的DB连接.看看这个问题/答案基本上我是怎么做的.
但是,只要有几百个客户端连接到我的应用程序并触发数据库调用,我就会在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
Run Code Online (Sandbox Code Playgroud)
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.')
Run Code Online (Sandbox Code Playgroud)
小智 14
简短回答:您的查询可能太慢,并且mysql服务器没有足够的线程来处理您尝试发送它的所有请求.
答案很长:
作为背景,Cloud SQL有两个与此相关的限制:
这听起来并不像连接限制对你有影响,但我想提一下以防万一.
当谈到并发请求时,增加限制可能有所帮助,但它通常会使问题变得更糟.我们过去见过两种情况:
您应该使用EXPLAIN和SHOW ENGINE INNODB STATUS来查看正在进行的两个问题中的哪一个.
当然,您也可能只是在您的实例上驱动了大量的流量,并且没有足够的线程.在这种情况下,你可能无论如何都要最大化实例的cpu,所以添加更多线程无济于事.
我阅读文档并注意到有 12 个连接/实例限制:
查找“每个 App Engine 实例与 Google Cloud SQL 实例的并发连接不能超过 12 个”。在https://developers.google.com/appengine/docs/python/cloud-sql/
| 归档时间: |
|
| 查看次数: |
6076 次 |
| 最近记录: |