问题描述
我正在尝试为Google App Engine创建一个自定义托管VM,其行为与Google提供的标准python27托管VM完全相同.(我这样做是将C++库添加到运行时的第一步).
从谷歌文档,以下Dockerfile指定标准的python27运行时:
FROM gcr.io/google_appengine/python-compat
ADD . /app
Run Code Online (Sandbox Code Playgroud)
我通过检查gcloud preview app run使用标准python27运行时生成的那个来验证这是正确的Dockerfile .它与此完全相同.
但是,当我使用dev_appserver.py或使用此Dockerfile运行我的应用程序时,gcloud preview app run我收到错误消息:
The --custom_entrypoint flag must be set for custom runtimes
Run Code Online (Sandbox Code Playgroud)
我使用的是最新版本的gcloud(1.9.86,app-engine-python组件版本1.9.28)和独立的python app引擎SDK(1.9.28).我在早期版本中遇到了同样的问题,所以我更新到了最新版本.
我做过的事:
gcloud preview app run --help有以下说法--custom-entrypoint:
--custom-entrypoint CUSTOM_ENTRYPOINT
Specify an entrypoint for custom runtime modules. This is required when
such modules are present. Include "{port}" in the string (without
quotes) to pass the port number in as an argument. …Run Code Online (Sandbox Code Playgroud) python google-app-engine gae-module google-app-engine-python google-managed-vm
我目前正在尝试升级Web应用程序的工作版本,并且遇到了一个任务,该任务在单个HTTP请求期间完成需要花费太长时间的问题。应用程序通过HTTP Post操作从JavaScript前端获取JSON列表,然后返回该列表的排序/切片版本。随着输入列表变长,排序操作将花费更长的时间(显然),因此在适当长的输入列表上,我遇到了60秒的HTTP请求超时,应用程序失败了。
我想开始使用延迟库执行排序任务,但是在执行该任务之后,我不清楚如何存储/检索数据。这是我当前的代码:
class getLineups(webapp2.RequestHandler):
def post(self):
jsonstring = self.request.body
inputData = json.loads(jsonstring)
playerList = inputData["pList"]
positions = ["QB","RB","WR","TE","DST"]
playersPos = sortByPos(playerList,positions)
rosters, playerUse = getNFLRosters(playersPos, positions)
try:
# This step is computationally expensive, it will fail on large player lists.
lineups = makeLineups(rosters,playerUse,50000)
self.response.headers["Content-Type"] = "application/json"
self.response.out.write(json.dumps(lineups))
except:
logging.error("60 second timeout reached on player list of length:", len(playerList))
self.response.headers["Content-Type"] = "text/plain"
self.response.set_status(504)
app = webapp2.WSGIApplication([
('/lineup',getLineups),
], debug = True)
Run Code Online (Sandbox Code Playgroud)
理想情况下,我想用对延迟任务库的调用来替换整个try / except块:
deferred.defer(makeLineups,rosters,playerUse,50000)
Run Code Online (Sandbox Code Playgroud)
但是我不清楚如何从该操作中获得结果。我在想必须将其存储在数据存储中,然后再检索它,但是我的JavaScript前端如何知道操作何时完成?我已经阅读了Google网站上的文档,但对于如何完成此任务仍然不甚了解。
使用公认的答案中的基本轮廓,这是我解决此问题的方法:
def …Run Code Online (Sandbox Code Playgroud) javascript python google-app-engine google-app-engine-python
我正在使用App Engine编写新的应用程序,并且正如文档建议不使用Blobstore API,我正在使用Google云端存储客户端(GCS).一切都很好,但我希望能够将"签名的URL"返回给客户,这样他们就可以获得GCS资源而无需通过应用程序.我相信这是signet网址的用途.
但是如何测试呢?我可以成功地从客户端测试GCS调用,但我不知道如何使用urlfetch测试客户端的HTTP调用.
以下是一个完整的测试用例,说明了我的问题:
import base64
import mimetypes
import urllib
import urllib2
from datetime import datetime, timedelta
import time
from google.appengine.api import app_identity
from google.appengine.datastore import datastore_stub_util
from google.appengine.ext import testbed
from google.appengine.ext import ndb
import unittest
import cloudstorage
# IS THIS RIGHT ?
GCS_API_ACCESS_ENDPOINT = 'http://localhost:8000/_ah/gcs'
def sign_url(bucket_object, expires_after_seconds=60):
""" cloudstorage signed url to download cloudstorage object without login
Docs : https://cloud.google.com/storage/docs/access-control?hl=bg#Signed-URLs
API : https://cloud.google.com/storage/docs/reference-methods?hl=bg#getobject
"""
# source: https://github.com/voscausa/appengine-gcs-signed-url/blob/05b8a93e2777679d40af62cc5ffce933216e6a85/sign_url.py
method = 'GET'
gcs_filename = urllib.quote(bucket_object)
content_md5, content_type = …Run Code Online (Sandbox Code Playgroud) google-app-engine google-cloud-storage google-app-engine-python
当我安装Google App Engine SDK并运行启动器时,它会要求我配置python位置:
当我打开Preferences它,它要求一个python可执行文件的路径:
我应该插入哪条路径,区别是什么:
python google-app-engine launcher google-app-engine-python google-app-engine-launch
我在Google Cloud Datastore中有一个表,我在其中存储一个小数据结构,该结构用一个Python服务编写,另一个用另一个Python服务读取.我正在使用gcloud版本0.15.0.这是我用来向GCD写入/读取数据的Python代码:
from gcloud import datastore
import datetime
import json
class GCD(object):
def __init__(self, project_id):
self.client = datastore.Client(project_id)
def put(self, table, key, data):
with self.client.transaction():
entity = datastore.Entity(self.client.key(table, key), exclude_from_indexes=['context'])
entity.update({'context': json.dumps(data), 'created': datetime.datetime.utcnow(), 'done': True})
try:
self.client.put(entity)
except Exception as e:
print "GCD save failed with exception: %s" % e
return None
def get(self, table, key):
entity_key = self.client.key(table, key)
entity = None
try:
entity = self.client.get(entity_key)
except Exception as e:
print "GCD read failed with exception: %s" …Run Code Online (Sandbox Code Playgroud) python google-cloud-datastore gcloud-python google-app-engine-python google-cloud-python
我的Google App Engine应用程序似乎有内存泄漏,但我无法弄清楚原因.
在缩小了负责的代码行之后,我将问题简化为一个定期运行的简单cron作业,它所做的就是使用查询加载一些实体.
我包括使用的内存使用情况logging.info(runtime.memory_usage()),我可以看到内存使用量从一次调用增加到下一次调用,直到超过软私有内存限制.
以下是我使用过的代码:
class User(ndb.Model):
_use_cache = False
_use_memcache = False
name = ndb.StringProperty(required=True)
...[OTHER_PROPERTIES]...
class TestCron(webapp2.RequestHandler):
def get(self):
is_cron = self.request.headers.get('X-AppEngine-Cron') == 'true'
if is_cron:
logging.info("Memory before keys:")
logging.info(runtime.memory_usage())
keys = models.User.query().fetch(1000, keys_only=True)
logging.info("Memory before get_multi:")
logging.info(runtime.memory_usage())
user_list = ndb.get_multi(keys)
logging.info("Memory after:")
logging.info(runtime.memory_usage())
logging.info(len(user_list))
app = webapp2.WSGIApplication([
('/test_cron', TestCron)
], debug=True)
Run Code Online (Sandbox Code Playgroud)
在cron.yaml我有:
- description: Test cron
url: /test_cron
schedule: every 1 mins from 00:00 to 23:00
Run Code Online (Sandbox Code Playgroud)
每分钟运行此任务时,每2次迭代就必须重新启动一个新实例.第一次以36mb开始,并在完成后说
此请求导致为您的应用程序启动新进程,从而导致您的应用程序代码首次加载.因此,此请求可能需要更长时间,并且比应用程序的典型请求使用更多CPU.
但是在第二次执行时,它开始使用107mb的内存(意味着它没有清除前一次迭代的内存?),它超出了软私有内存限制并通过以下方式终止进程:
在处理完6个请求后超过128 MB的软私有内存限制(134 MB)处理此请求后,发现处理此请求的进程使用了太多内存并被终止.这可能会导致新进程用于您的应用程序的下一个请求.如果经常看到此消息,则可能是应用程序中存在内存泄漏.
以下是两个日志的完整输出:
输出只是在这两个日志之间交替.请注意,我已在模型的定义中禁用了缓存,因此在每次调用函数时是否应重置内存使用情况?
python google-app-engine app-engine-ndb google-app-engine-python
我在使用dev_appserver.py连接到生产数据存储时遇到问题。
我遵循了https://cloud.google.com/appengine/docs/standard/python/tools/remoteapi上 有关使用本地脚本使用Google-Datastore 的教程,并且在运行单个脚本时效果很好。
我制作了一个小的Git存储库,其中包含一个最小的appengine应用程序,并且在appengine_config.py脚本上添加了代码以连接到远程数据存储。
https://github.com/fcaldas/appengine_remote_datastore
app.yaml:
runtime: python27
api_version: 1
threadsafe: true
builtins:
- remote_api: on
handlers:
- url: /
script: index.app
Run Code Online (Sandbox Code Playgroud)
index.py:
import webapp2
class MainPage(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.write('Hello, World!')
app = webapp2.WSGIApplication([
('/', MainPage),
], debug=True)
Run Code Online (Sandbox Code Playgroud)
appengine_config.py:
import os
try:
import dev_appserver
dev_appserver.fix_sys_path()
except ImportError:
print "Could not import dev_appserver"
pass
if os.environ['SERVER_SOFTWARE'].startswith('Development'):
from google.appengine.ext.remote_api import remote_api_stub
from google.appengine.datastore.entity_pb import Reference
PROJECT_ID = "YOUR-PROJECT-ID"
remote_api_stub.ConfigureRemoteApiForOAuth(
'{}.appspot.com'.format(PROJECT_ID),
'/_ah/remote_api/', secure=False)
Reference.app = lambda *args: os.environ['APPLICATION_ID'].replace('dev~', …Run Code Online (Sandbox Code Playgroud) google-app-engine python-2.7 app-engine-ndb google-cloud-datastore google-app-engine-python
版本
错误
从six.moves导入http_client
ImportError:没有名为move的模块
描述
在使用谷歌应用引擎运行的烧瓶应用程序,dev_appserver.py同时在导入时使用上面的错误在本地系统上运行它from six.moves import http_client
我试过了什么
导入六个已经尝试过dir(six)哪个显示moves列表中有但是它无法导入它,这很奇怪.
产量six.__version__:1.11.0
dir输出(六)
['/ opt/tribes-backend','/ opt/tribes-backend/lib1','/ usr/lib/google-cloud-sdk/platform/google_appengine','/ usr/lib/google-cloud-sdk/platform/google_appengine','/ usr/lib/python2.7','/ usr/lib/python2.7/lib-dadload','/ usr/lib/google-cloud-sdk/platform/google_appengine/lib/ssl -2.7.11','/ usr/lib/google-cloud-sdk/platform/google_appengine/lib/grccio-1.0.0','/ usr/lib/google-cloud-sdk/platform/google_appengine/lib/six -1.9.0','/ usr/lib/google-cloud-sdk/platform/google_appengine/lib/protobuf-3.0.0','/ usr/lib/google-cloud-sdk/platform/google_appengine/lib/enum -0.9.23','/ usr/lib/google-cloud-sdk/platform/google_appengine/lib/finuts3.0.5','/ usr/lib/google-cloud-sdk/platform/google_appengine/lib/setuptools -36.6.0','/ usr/lib/google-cloud-sdk/platform/google_appengine/lib/protocc-1.0','/ usr/lib/google-cloud -sdk/platform/google_appengine/lib/pyk-1717.2 ','/ usr/lib/google-cloud-sdk/platform/google_appengine/lib/webapp2-2.3','/ usr/lib/google-cloud-sdk/platform/google_appengine/lib/webob -1.1.1','/ usr/lib/google-cloud-sdk/platform/google_appengine/lib/werkzeug-0.11.10','/ usr/lib/google-cloud-sdk/platform/google_appengine/lib/yaml -3.10','/ usr/local/lib/python2.7 /dist-packages/enum','/ usr/lib/google-cloud-sdk/platform/google_appengine/lib/concurrent/concurrent','/ usr/local/lib/python2.7/dist-packages/concurrent','/ usr/local/lib/python2.7/record-packages/google','/ usr/lib/google-cloud-sdk/platform/google_appengine/google'] ['BytesIO','Iterator','MAXSIZE','Module_six_moves_urllib','Module_six_moves_urllib_error','Module_six_moves_urllib_parse','Module_six_moves_urllib_request','Module_six_moves_urllib_response','Module_six_moves_urllib_robotparser','MovedAttribute','MovedModule','PY2 ','PY3','StringIO','_ LazyDescr','_ LazyModule','_ MoveIItems','_ SixMetaPathImporter',' author ',' builtins ',' doc ',' file ',' …
作为API调用的一部分,我在Google App Engine上运行了一个功能.结构是这样的
import externalmod
...
...
@app.route('/calc_here')
def calc:
answer = externalmod.Method()
return answer
Run Code Online (Sandbox Code Playgroud)
函数externalmod是一个复杂的算法(不是数据存储区,不是urlfetch,只是纯python),它适用于桌面上的每种可能情况,但对于app引擎上的一些输入情况,当调用端点时会出现以下错误
{
"code": 13,
"message": "BAD_GATEWAY",
"details": [
{
"@type": "type.googleapis.com/google.rpc.DebugInfo",
"stackEntries": [],
"detail": "application"
}
]
}
Run Code Online (Sandbox Code Playgroud)
在查看https://cloud.google.com/appengine/articles/deadlineexceedederrors并进行以下讨论之后: 如何增加Google App Engine请求计时器.默认值为60秒
和 https://groups.google.com/forum/#!topic/google-appengine/3TtfJG0I9nA
我意识到这是因为如果任何代码运行超过60秒,App引擎将停止.我首先尝试根据Do Exception捕获DeadlineExceededError异常执行以下操作?
from google.appengine.runtime import DeadlineExceededError
try:
answer = externalmod.Method()
except DeadlineExceededError:
answer = some_default
Run Code Online (Sandbox Code Playgroud)
但我得到的错误是没有模块google.appengine
然后意识到所有的文档都是针对标准环境的,但我使用的是灵活的环境,我认为这个appengine.runtime可能甚至不再存在当我这样做:
try:
answer = externalmod.Method()
except :
answer = some_default
Run Code Online (Sandbox Code Playgroud)
它工作,我开始捕捉一些DeadlineExceededErrors.但显然,我不能总是像这样捕获DeadlineExceededErrors.有时我会发现错误,有时候不会.我认为最好的方法是增加允许代码运行的时间,而不是仅仅捕获异常.
我尝试通过添加CPU来更改app.yaml文件:2但没有任何区别.
runtime_config:
python_version: 3
resources:
cpu: 2
memory_gb: 4
manual_scaling: …Run Code Online (Sandbox Code Playgroud) 是否有必要在AppEngine Standard Python 3.7运行时中从IAP验证签名的标头?
IAP文档未提及Python 3.7运行时的细节。
IAP 文档说:
用户API对于标准3.7不可用。签名头是。可以验证标题。
我可以看到AppEngine环境添加了一些标题。我想知道X-Appengine-值是否可以隐式信任(即AppEngine在验证来自IAP的标头后是否附加这些值)?
X-Appengine-User-Id: <user id>
X-Appengine-Auth-Domain: <domain>
X-Appengine-User-Email: <user email>
...
X-Goog-Iap-Jwt-Assertion: <assertion>
X-Goog-Authenticated-User-Email: accounts.google.com:<user email>
X-Goog-Authenticated-User-Id: accounts.google.com:<user id>
Run Code Online (Sandbox Code Playgroud) python ×5
python-2.7 ×2
gae-module ×1
google-iap ×1
javascript ×1
launcher ×1
python-3.x ×1
six ×1