【问题标题】:First Datastore query always slow第一个数据存储区查询总是很慢
【发布时间】:2019-10-04 06:37:59
【问题描述】:

我有一个 Python 3.7 项目,它使用 google.cloud.ndb 库与 Datastore 进行通信。

我注意到,启动实例时的第一个请求总是比后续请求慢一个数量级(几秒)。即使使用模拟数据存储在本地运行也是如此。我已经确认延迟是由于第一个运行的ndb.Key(...).get() 造成的。大概数据存储连接需要一些时间来设置?

有没有人找到减少这种延迟的方法?

代码示例:

from flask import Flask
from google.cloud import ndb

import time

client = ndb.Client()

def ndb_wsgi_middleware(wsgi_app):
    def middleware(environ, start_response):
      with client.context():
        return wsgi_app(environ, start_response)
    return middleware

app = Flask(__name__)
app.wsgi_app = ndb_wsgi_middleware(app.wsgi_app)

@app.route('/main')
def main():
  now_ts = time.time()
  org = ndb.Key(Org, 1).get()
  print('Finished get in %f' % (time.time() - now_ts))
  return 'Does not exist' if org is None else 'Exists'

class Org(ndb.Model):
  pass

if __name__ == '__main__':
  app.run(host='0.0.0.0', port=8080, debug=True)

从浏览器获取 2 次 localhost:8080/main 后的输出(使用命令 gcloud beta emulators datastore start 启动的本地数据存储模拟器):

Finished get in 2.043116
127.0.0.1 - - [09/Oct/2019 22:41:49] "GET /main HTTP/1.1" 200 -
Finished get in 0.001995
127.0.0.1 - - [09/Oct/2019 22:41:56] "GET /main HTTP/1.1" 200 -

【问题讨论】:

  • 我有一个用 go 编写的应用程序,对模拟器的第一次查询发生在 300 毫秒内。当然,如果您将模拟器与应用程序一起启动,模拟器本身需要时间(几秒钟)才能启动。
  • 有趣,我的第一个模拟器查询似乎总是需要几秒钟...

标签: google-app-engine google-cloud-datastore google-app-engine-python


【解决方案1】:

您遇到此行为的原因是,除非另有配置,否则所有 App Engine 应用程序都会在空闲时关闭其实例。这意味着如果他们收到新请求,他们必须花时间重新启动和响应,从而导致响应时间比其他情况下更长。这是为了避免占用资源和产生不必要的费用,因为实例在运行时按分钟计费。

您可以使用warm-up requests 避免这种情况,这是一种特殊类型的加载请求,可在发出实时请求之前准备实例。

其他选项是使用模块在您的应用程序上设置Automatic scaling,并为最小空闲实例设置一个值。这意味着,如果您设置它,至少有一个实例将始终运行,从而防止需要任何和所有加载请求。但是,由于这些实例一直处于运行状态,因此会产生额外费用。

【讨论】:

  • 我不相信大部分延迟是由 App Engine 实例启动引起的。正如我所提到的,我在本地看到了相同的延迟,并且良好的旧 printf 调试已确认主要原因是第一个数据存储查询异常长。
  • 好的,您能否与我们分享您的设置的最小可重现示例,以帮助您减少延迟?请分享您的 App Engine 设置、yaml 配置文件、数据库结构、查询示例。
  • 我已更新帖子以包含代码示例。我的 app.yaml 文件是琐碎的 runtime: python37,而 requirements.txt 包含 Flask==1.1.1google-cloud-ndb
  • 您好,由于您尚未共享您的 app.yaml,因此我无法查看您是否正在为数据库的属性编制索引。请问可以分享yaml配置文件和数据库结构吗?你能解释一下你的代码中的 ndb.Key.get 是什么意思吗?
  • 我确实在上面的评论中分享了 app.yaml ;) 这很简单,没有索引。不确定您所说的数据库结构是什么意思,它只是示例中的 Org 类。 ndb.Key.get 用于检查给定的密钥是否存在于数据库中(当然,在这个简单的玩具示例中,它永远不存在)。
猜你喜欢
  • 2014-10-31
  • 2021-02-11
  • 1970-01-01
  • 2021-08-24
  • 1970-01-01
  • 2011-04-22
  • 1970-01-01
  • 2019-12-12
  • 2021-07-23
相关资源
最近更新 更多