在Google App Engine上使用3年史诗评论。

在过去的3年里,我参与了在Google App Engine上运行的应用程序这是谷歌在这里提供的一项迷人而独特的服务不像你在其他地方找到的任何东西这是我对它的深入,个人的看法。

谷歌的云(估计2008)

首先,是什么Google App Engine(GAE) actually? It is a platform to run your web applications on喜欢Heroku的但是当你仔细观察时会有所不同它也是一个多功能的云计算平台喜欢AWS但不同让我解释。

谷歌在2008年推出了GAE,当时云计算仍处于起步阶段亚马逊领先于他们,因为他们已经开始在2006年租用他们的IT基础设施但是对于GAE,谷歌很早就提供了一种复杂的平台即服务(PaaS),亚马逊将在2011年与其Elastic Beanstalk服务相匹配现在GAE有什么特别之处?

这是一个全面管理应用平台So far, I do not know a platform which comes close to GAE's full package: log management, mail delivery, scaling, memcache, image manipulation, distributed Cron jobs, load balancing, version management, task queue, search, performance analysis, cloud debugging, content delivery network - and that is not even mentioning auxiliary services that have popped up on Google's cloud in the meantime like SQL, BigQuery, file storage..名单还在继续。

通过使用Google App Engine,您可以在(可能)世界上最好的基础架构之上运行您的应用程序此外,您还可以获得开箱即用的功能,这些功能将至少需要Heroku上的第三方附加组件,或者如果您自己完成,则需要几周的安装时间。是GAE的吸引力。

在GAE上运行的值得注意的应用程序包括Snapchat可汗学院

发展

我一直在努力的Web应用程序是一个单独的大型Java应用程序App Engine还支持Python,PHP和Go现在您可能想知道为什么选择如此有限一个原因是,为了拥有一个完全托管的环境,Google需要将平台与环境集成你可以说环境和平台是紧密耦合的一旦你开始为GAE开发,这需要付出很多努力和投资。

SDK

每个应用程序都需要使用特殊的SDK(软件开发工具包)来使用GAE提供的APISDK非常庞大例如,Java SDK下载大约为190 MB当然,大多数用例都不需要其中的一些JAR,有些只在开发过程中需要 - 但是,它肯定不是轻量级的(即使对于Java来说也是如此)。

SDK不仅是您通往Google App Engine世界的桥梁,还可以作为其在本地计算机上的模拟对于几乎所有GAE API,它都具有您可以开发的存根首先,这意味着当您在本地运行应用程序时,您将获得相当接近它在生产中的表现其次,您可以轻松地针对API编写集成测试And usually this will get you very far; the mismatch between the production and stub behavior is quite small.

Java API

说到API,当您使用某些Java API时,您会感到惊讶由于GAE以某种方式运行您的应用程序砂箱,它禁止使用特定的Java API主要限制包括写入文件系统,某些方法java.lang.System中并使用Java Native Interface(JNI)使用线程和套接字也有一些特点,但稍后会有更多内容。

有趣的是,Java SDK实际上确保您不在本地使用这些受限制的API当您运行应用程序或仅进行集成测试时,它会使用一个Java代理来监视您的每个方法调用它会立即针对任何检测到的违规行为抛出异常这有助于及早发现违规行为,不仅仅是在生产中,而且还有令人讨厌的副作用在分析应用程序的性能时,代理会进行大量的违规检查最后,很难判断你的应用以来的实际表现方法调用越多,越开销代理生成。

Java开发工具包(JDK)

接下来你可能会注意到当你开始是可以发展使用Java 8尽管Java 7的生命终结时间是在2015年,但它仍然非常活跃并且在GAE上崭露头角第三高的投票问题GAE的问题跟踪器支持Java 8(第二高的是对Python 3的支持)它创建于2013年从那以后,关于此事的任何进展的唯一新闻是2016年App Engine邮件列表上的帖子,说明工程师正积极致力于此嗯,对你有好处。

显然,这种限制对任何开发者来说都是一个主要的烦恼就我个人而言,失踪的lambda支撑非常重当然,可以迁移到许多JVM语言之一,如Groovy,Scala或Kotlin,它们都提供了比Java 8更多的功能。但这是一个昂贵的和风险投资我们的项目成本太高,风险太大我们还调查了可行性retrolambda虽然在第一次测试中看起来很有前途,但是它还没有追求它。

不得不留下旧版本也是业务的责任这使得找到开发人员变得更加困难整体应用程序安全性也受到威胁谷歌支持告诉我们,我们仍然会收到生产JDK 7的安全补丁但最终,喜欢春天会停止支持所有主要的库最终,你会成为卡住了

部署

To deploy your application, you need to create anAppEngine上-web.xml中配置文件在那里,您可以指定应用程序ID和版本以及一些其他设置,例如将应用标记为线程能够同时为每个实例接收多个请求。

上传

App Engine希望将Java应用程序作为打包的WAR文件接收您可以使用它将其上传到他们的服务器下,appcfg来自SDK的脚本可选地,Maven和Gradle都有插件,这使得写入变得简单mvn appengine:更新上传可以相当一段为典型的Java应用程序,你最好有一个快速的internet连接流程完成后,您可以在Google云端控制台中查看新部署的版本:

Google云端控制台 - 版本

静态文件

像图像,样式表和脚本这样的静态文件是当今任何Web应用程序的一部分在里面AppEngine上-web.xml中文件可以标记为静态Google将直接提供这些文件 - 无需点击您的应用程序它不是究竟内容交付网络(CDN),因为它没有分发到数百个边缘节点,但它有助于减少服务器的负载。

版本

App Engine的优点在于您部署的所有内容都具有特定版本每个版本都可以访问HTTPS:// <版本> -dot- <应用ID> .appspot.com的但是哪一个是其实生活?

您可以将版本标记为默认的这意味着当你去HTTPS:// <应用ID> .appspot.com的(或您为应用程序指定的域名),即接收所有请求的版本将版本切换为默认的非常简单:只需按一下按钮或简单的终端命令即可GAE可以立即切换或逐步迁移您的流量,以防止压倒新版本。

还有一个选项(我们从未使用过)允许您跨多个版本分发流量这允许通过仅在将其提供给用户的一小部分之前逐步推出新版本,然后使其可供所有人使用。

由于很容易创建新版本并在它们之间切换生产流量,因此GAE是一个完美的练习平台蓝绿色部署每次我们由于新版本中的错误而需要回滚时,它都是毫不费力的通过编写一个有点智能的部署脚本,也可以实现持续交付。

实例

每个版本都可以运行任意数量的实例(唯一的限制是您的信用卡)The actual number is the result of incoming traffic and the scaling configuration of your app; we'll look at that laterGoogle将在该版本的所有正在运行的实例之间分发传入请求你可以看到一个实例列表,包括一些基本的指标要求和延迟,在谷歌云控制台:

Google Cloud Console  - 实例

您可以选择运行这些实例的硬件选项 - 让我们坦率地说 - 可悲App Engine主要提供四种不同的功能实例类从128MB和600MHz CPU(您正确读取)到1024MB和2.4GHz CPU是的,再一次,这是事实而且真的很伤心On a developer's laptop our app started almost twice as fast as in production.

服务

到目前为止,我只讨论过一个单一的单片应用程序But what do you do if yours consists of multiple services? App Engine has got you covered每个应用程序都是一项服务如果你只有一个,它只是被称为默认的您可以直接通过访问每个HTTPS:// <版本> -dot- <服务> -dot- <应用ID> .appspot.com的

App Engine应用程序,服务,版本和实例

您可以很容易地部署多个版本的每个服务,规模和显示器分开由于每项服务都与其他服务分开,因此您可以运行任何受支持语言的组合不幸的是,一些配置设置在所有服务中共享因此,它们并非完全孤立总而言之,GAE似乎非常适合微服务有一些精心制作的文件关于Google的这个主题,也是如此。

由于后来会变得清晰的原因,我们决定将我们的应用程序分成两个服务:前端(面向用户)和后端(后台工作)但要做到这一点,我们实际上并没有将这块巨石分成两部分 - 这可能需要几个月的时间我们只是部署相同的应用程序只两次,发送用户到另一个服务和背景工作。

操作

让我们来谈谈它意味着什么您的应用程序在应用程序引擎正如您将看到的,它对您施加了许多限制但并不是所有的悲观最后你会明白为什么。

应用程序启动

当App Engine启动新实例时,应用程序需要初始化它将直接发送HTTP请求的用户应用程序或-如果配置和扩展情况下允许它发送一个所谓的预热要求无论哪种方式,第一个请求称为加载请求正如您可以想象的那样,快速启动非常重要。

另一方面,实例本身的启动速度非常快如果你有开始在云服务器之前,您可能已经等了超过一分钟不在GAE上实例几乎立即开始我猜谷歌拥有一批准备好的服务器瓶颈将始终是您自己的应用程序我们的应用程序开始生产需要40多秒因此,除非我们想要将我们庞大的巨型组合分成不同的服务,否则我们需要它更有效地开始。

该应用程序使用Spring谷歌甚至还有专门的文档条目:为App Engine应用程序优化Spring框架在那里,我们找到了最重要的创业优化的灵感。

我们摆脱了Spring的类路径扫描它在App Engine上特别慢(可能是因为CPU很糟糕)幸运的是,有一个名为的图书馆classindex它使用特殊注释将类的完全限定路径写入文本文件通过简单地从文本文件中读取bean,Spring初始化下降了大约8-10秒。

请求处理

我在这里要提到的第一件事是App Engine要求在60秒内处理用户请求,并在10分钟内处理后台请求当应用程序响应时间过长时,请求将以500状态代码和a中止DeadlineExceededException被抛出。

通常,这应该不是问题如果您的应用需要超过60秒的时间来响应,那么用户很快就会消失但由于通过HTTP请求启动一个实例,这也意味着它在60秒开始在生产中,我们观察到启动时间的变化长达10秒这意味着您现在只需不到50秒即可启动应用Java应用程序花费这么长时间并不罕见。

我要强调的一个不错的小功能是地理HTTP标头:对于每个传入的用户请求,Google添加包含用户的国家,地区,城市以及所述城市的经度和纬度的标头这可以非常有用的,例如用于预先填写电话号码国家代码或检测异常帐户登录位置从我们的观察来看,准确性似乎也很高从第三方API或数据库获得具有此级别准确性的那种信息通常非常麻烦和/或昂贵所以想要在App Engine是一个很好的免费奖金。

背景工作

主题

正如前面提到的,有一些限制使用Java线程尽管可以通过自定义GAE启动新线程ThreadManager,它不能“超过”它创建的请求这在实践中可能很烦人,因为第三方库当然不遵循App Engine的限制找到一个兼容库或适应一个看似不相容,花费我们很多汗水和泪水例如,我们无法使用Dropwizard指标库开箱即用,因为它依赖于使用后台线程。

队列

But there are other ways of doing background work: In the spirit of the Cloud, you apply the divide and conquer approach on the instance level通过使用任务队列你可以将工作排队等待以后处理例如,当需要发送电子邮件时,您可以使用有效负载排队新任务(例如,收件人,主题和正文)和一个URL队列然后,您的一个实例将接收有效负载作为对指定端点的HTTP POST请求如果失败,App Engine将重试该操作。

当你需要处理很多工作时,这种模式真的很棒简单地将一批独立运行的任务排入队列App Engine将负责故障处理无需自定义重试代码想象一下,如果没有它会有多么尴尬:一旦你发现错误就需要停止并从头开始运行或者仔细跟踪哪些失败并再次将它们排队以进行另一次尝试。

就像App Engine的其他部分一样,任务队列可以很好地扩展队列可以得到几乎无限的任务其缺点是有效载荷只能1 MB,但我们通常只是简单地将对数据的引用传递给队列但是,您需要特别注意数据处理,因为在排队任务和实际执行任务的时间之间很容易发生某些事情。

队列配置为queue.xml文件下面是一个推送队列的示例,每秒最多激活一个任务,最多重试两次:

<queue>  
  <name>my-push-queue</name>
  <rate>1/s</rate>
  <retry-parameters>
    <task-retry-limit>2</task-retry-limit>
  </retry-parameters>
</queue>

克龙

另一个非常有价值的工具是分布式Cron在一个cron.xml您可以告诉GAE以特定时间间隔发出请求这些只是您的一个实例将收到的简单HTTP GET请求可能的最小间隔是每分钟一次它对常规报告,电子邮件和清理非常有用。

这是一个条目cron.xml好像:

<cron>  
  <url>/tasks/summary</url>
  <schedule>every 24 hours</schedule>
</cron>

Cron工作也可以与之结合使用队列:它们允许从队列中主动获取一批任务根据用例,使实例批量处理大量任务比单独将它们推送到实例要高效得多。

像所有其他应用程序引擎配置文件,cron.xmlis shared across all services and versions of an application这可能很烦人In our case, sometimes when we deployed a version where a new Cron entry had been added, App Engine would start sending requests to an endpoint which did not exist on the live (but older) version - generating noise for our production error reporting我想在使用App Engine托管微服务时,这一定会更加痛苦。

此外,Cron作业不在本地运行我可以理解为什么这可能是:很多的工作通常通常安排在繁忙时间,因此没有一个正常的工作日期间被触发但一些每隔几分钟或几小时跑一次 - 这些都非常有趣例如,他们可能会触发通知你想在本地看到这些因为最终你会引入一个导致不良行为的变化(正如在我们的项目中多次发生的那样)并且在本地看到它可能会阻止你运送它但是在本地模拟Cron工作很棘手(不幸的是我们没有打扰)一个可能需要编写一个外部工具,解析cron.xml然后ping相应的终点(哎呀!)。

扩展

App Engine将根据流量来扩展实例数量How? Well, depending on how you have configured your application有三种模式:

  • 自动:这是GAE独特的卖点它将基于实例的数量规模等指标请求率和响应延迟因此,如果有大量流量或您的应用响应缓慢,则会有更多实例启动。
  • 手册:基本上就像你的老式虚拟私人服务器你告诉谷歌有多少实例和谷歌提供如果您知道,这个固定的实例大小很有用究竟你会得到什么样的交通。
  • 基础:基本上与手动缩放模式相同,但是当实例变为空闲时,它将被关闭。

最有用的和有趣的一个当然是自动模式它有一些参数可以帮助我们了解它在内部的工作原理:max_concurrent_requests,max_idle_instances,min_idle_instancesmax_pending_latency引用App Engine文档:

App Engine调度程序决定是使用现有实例(空闲或接受并发请求的实例)提供每个新请求,将请求放入待处理请求队列中,还是为该请求启动新实例该决定考虑了可用实例的数量,应用程序服务请求的速度(延迟)以及启动新实例所需的时间。

每当我们试图调整这些数字时,感觉就像练习黑魔法一样实际上很难在这里推断出一个好的设置然而,这些数字决定了您应用的真实性能,并极大地影响了您的每月账单。

但总而言之,自动缩放是非常邪恶的它特别适合处理背景工作(例如生成报告,发送邮件),因为它经常-比用户请求大,突然爆发。

但事实是,由于启动时间较慢,Java非常适合这种自动缩放更糟糕的是,调度程序向a分配请求是很常见的开始(冷)实例然后,进入亚秒级REST响应的所有努力都会消失自2012年以来,有一个问题面向用户的请求永远不会被锁定到冷实例除了状态变化为“已接受”之外,它甚至没有引起谷歌的任何评论(听起来像是此时悲伤的一个阶段)。

这也解释了为什么我们将应用程序分成两个服务之前,我们经常发现,随着后台请求的激增,用户请求会受到影响这是因为App Engine极大地扩展了实例,并且由于请求在实例之间平均路由,因此导致更多用户请求命中冷实例通过拆分应用程序,我们大大减少了这种情况同时,我们也可以运用不同的扩展策略两种服务。

最后一件事:在一个副项目中,我使用Go on App Engine并在App Engine上发现了一个新视角Go的特点是能够立即启动应用程序这使得App Engine和Go成为完美组合,如蝙蝠侠和罗宾从我了解它之后,它们一起体现了我个人对云的期望它真正适应工作负载,并且毫不费力地完成工作即使是糟糕的硬件选项似乎也不会给Go带来真正的问题,因为它非常有效。

数据

当App Engine推出时,您拥有的唯一数据库选项是用于结构化数据的Google Datastore和用于二进制数据的Google Blobstore从那时起,他们又添加了Google Cloud SQL(托管MySQL)和谷歌云存储(如亚马逊的S3),取代了Blobstore从一开始,App Engine就提供了一个托管的Memcache。

以前连接到第三方数据库非常困难,因为您只能使用HTTP进行通信但通常数据库需要原始TCP几年前,当Socket API发布时,这只是改变了但它是仍然在Beta中,这使得它成为任务关键型使用的可疑选择因此,在数据库方面,仍有很多供应商锁定。

无论如何,在一开始,只有数据存储区。

Datastore

数据存储区是专有的NoSQL数据库,完全由Google管理它不像我以前用过的任何东西它是一种具有非常独特的特性,保证和限制的大规模野兽。

在早期,数据存储是基于主从设置以强烈一致的读取几年之后,谷歌遭遇了一些严重的攻击之后介绍了一个新的配置选项:高复制API保持不变,但写入延迟增加,一些读取变为最终一致(稍后会详述)好处是可用性显着增加它甚至拥有99.95%的正常运行时间SLA自从我使用它以来,我从未遇到过Datastore可用性的单个问题这只是你不必考虑的事情。

实体

数据存储的基础很简单你可以读写实体它们根据特定情况分类一个实体包括性能属性具有名称和具有特定类型的值喜欢,布尔,浮动要么整数每个实体也都有一个独特的

写作

但是,没有任何架构具有相同类型的实体可能看起来完全不同这使得开发很简单:只添加一个新的属性,保存它,它会在那里另一方面,您需要编写自定义迁移代码来重命名属性原因是实体无法就地更新 - 必须再次加载,更改和保存根据实体的数量,这可能会成为一项非常重要的任务,因为您可能需要使用任务队列来规避请求时间要求根据我的经验,由于重构是如此昂贵和危险,这导致了整个地方的旧属性名称。

有一些limits for working with entities最关键的两个是:

  • 一个实体可能只是1 mb,包括额外的元数据编码的实体
  • 您只能每秒写入一个实体(组,确切地说)

在实践中,这可能是一个问题我们很少大小限制,但是当我们做了,这是痛苦的客户数据可能会丢失当你达到写入速率限制时,通常在下次尝试时就可以了当然你要设计你的应用程序的几率降到最低例如,像定期更新的计数器之类的东西需要做很多工作才能做好谷歌甚至有一个文档条目使用分片来构建计数器

Reading

可以使用其密钥或查询来获取实体读,关键是强烈一致的,这意味着你将收到最新数据即使你之前更新实体获取它然而,这并不适用于查询他们最终是一致的因此写入并不总是立即反映出来这可能导致问题并且可能需要减轻,例如通过巧妙的数据建模(例如,使用助记符作为密钥)或利用特殊的数据存储功能(例如实体组)。

查询始终指定实体类型和可选过滤器和/或排序顺序必须为过滤器中使用的每个属性或作为排序键建立索引Adding an index can only be done as part of the regular write operation不像大多数SQL数据库那样在后台自动运行索引还将增加写入操作的时间和成本(稍后将详细介绍)。

如果查询涉及多个属性,则需要多索引必须在名为的配置文件中指定数据存储,indexes.xml这是一个例子:

<datastore-index kind="Employee" ancestor="false">  
   <property name="lastName" direction="asc" />
   <property name="hireDate" direction="desc"
</datastore-index>

与其他数据库相比,缺少多索引不仅会导致低效,慢的查询 - 它会立即失败数据存储区尽力执行高性能查询不平等的过滤器,例如,只支持一个属性当然,总有办法在脚下射击自己 - 但它们很少见。

我现在还有其他一些功能,例如分页,投影查询和事务去吧数据存储文档要了解更多信息,它非常广泛且有用。

与其他数据库相比,读写操作非常慢根据我的观察,按键读取平均需要10-20ms很少见到重大偏差我最好的猜测是谷歌序列化实体,只有索引实际上保存在内存中。

定价模型似乎支持:您支付存储数据,读取,写入和删除操作而已注意数据库内存不是在那个列表中操作本身也很便宜:读取100k实体成本为0.06美元,10万次写入操作成本为0.18美元 - 写入操作可以是实际的实体写入,但也可以写入每个索引如果你不写任何东西,你就不付任何代价但是在一分钟之内你就可以写出数十亿字节的数据了这里是踢球者:对于没有实体或十亿的数据库,读写性能基本相同它像疯了一样扩展。

API

数据存储的API感觉如此非常低级别因此,对于任何严肃的Java应用程序,都无法解决物化这是一个由Jeff Schnitzer编写的图书馆如果谷歌还没有这样做,他们应该给他写一张巨大的支票,让App Engine变得更好他是为自己的事业而写的,但多年来不懈的奉献精神,他在论坛上提供的大量文档和支持令人震惊使用Objectify,与数据存储区合作实际上很有趣。

这是一个例子的文档:

@Entity
class Car {  
    @Id String vin;
    String color;
}

ofy().save().entity(new Car("123123", "red")).now();  
Car c = ofy().load().type(Car.class).id("123123").now();  
ofy().delete().entity(c);

Objectify使得将实体声明为简单类非常容易,然后处理数据存储之间的所有映射。

它也有一些技巧例如,它带有一级缓存这意味着每当您按键请求实体时,它首先会查看请求范围的缓存,无论该实体是否已被提取这有助于提高性能但是,它也可能令人困惑,因为当您获取实体并修改它时不要保存它,下一次读取将产生相同的缓存,修改对象这可能导致Heisenbugs。

开发和测试

由于App Engine是专有的云数据库,因此您无法在本地启动它当您运行您的应用程序在您的机器上,启动模拟数据存储的SDK它的行为非常接近生产环境只有表现要好得多,这可能会产生误导。

对于针对数据存储区运行测试,SDK还可以为您启动本地数据存储区但是,这必须是不同的实现,因为它的行为与运行应用程序的行为不同This becomes apparent when you realize that a missing multi-index will throw an error when executing the app locally but not when testing the same query多年来,我意外地发布了几个缺少索引的查询到生产中(通常仍然在Beta切换之后) - 尽管我对它进行了测试在与支持人员联系后,他们承认了疏忽,并承诺要解决这个问题 - 一年多后他们仍然没有。

备份

备份数据存储区是一个非常糟糕的过程有手动和自动方式当然,当你有一个生产应用程序时,你想要定期备份官方方式是2012年推出的功能,仍然是Alpha!

通过添加条目到您的cron.xml您可以启动备份过程该条目将包括要备份的实体的名称以及要将其保存到的Google Cloud Storage存储桶当时代已经来临,它将推出一些Python实例备份代码,遍历的数据存储和拯救他们某种专有的备份格式你的桶有趣的是,存储桶可以包含多少文件的限制,因此您最好不时使用新存储桶。

这是最糟糕的数据存储。

内存缓存

在App Engine上存储数据的另一个重要方法是Memcache默认情况下,你得到一个共享内存缓存这意味着,它在尽力而为的基础上工作,并且无法保证它将具有多少容量还有专用的Memcache,每小时每GB 0.06美元。

Objectify能够将其用作二级缓存只需注释一个实体@Cache它会在数据存储区之前询问Memcache并首先保存每个实体这会对性能产生巨大影响通常Memcache会在大约5毫秒内响应,这比数据存储快得多我不知道我们可能有任何过时的缓存问题所以这在生产中非常有效。

The benefits of it are actually very noticeable when Memcache is down这件事发生在我们身上一年一次,持续一两个小时我们的网站几乎无法使用,速度很慢。

大查询

BigQuery是由Google管理的数据仓库即服务您可以导入数据(可以是PB级),并可以通过自定义查询语言运行分析。

它与数据存储区集成得很好,因为它允许从Google云存储导入数据存储区备份文件我已经使用这几次,不幸的是并不总是成功对于一些我的实体收到了一个神秘的错误我无法弄清楚出了什么问题但是有些实体确实有效摆弄的查询语言文档后,我第一次能够产生的见解考虑到所有因素,这是一种运行简单分析的好方法如果不编写自定义代码,我肯定无法做到这一点但我并没有真正利用该服务的全部潜力我所做的所有查询都可以直接在任何SQL数据库中完成,我们的数据集非常小只是因为数据存储的工作方式,我必须首先使用BigQuery服务。

监控

Google Cloud Console提供了许多功能来诊断您的应用在生产中的行为只需查看Google Cloud Console导航:

Google云端控制台 - 监控

这是结果谷歌的收购Stackdriver在2014年It still feels like a separate, standalone service - but its integration into Google Cloud Console is improving.

让我们一个一个地看看这些功能。

记录

快速轻松地访问应用程序日志至关重要这在App Engine开始时真的很痛苦它曾经非常麻烦,因为它无法搜索所有应用程序的版本这意味着当你在寻找某些东西时,你必须知道当时在线版本 - 或者逐个尝试几个版本它几乎无法使用而且它非常慢。

从那时起,他们添加了有用的过滤器,仅显示特定的模块,版本,日志级别,用户代理或状态代码它是非常强大的还没有快速,但现在它变得更好而早期以下是它的外观:

Google Cloud Console  - 日志记录

您可以在此处看到一个非常独特的想法,即日志始终按请求进行分组在我遇到的所有其他工具中,例如Kibana,您将只获得与您的搜索匹配的日志行通过始终显示与您的搜索匹配的所有其他日志行,它为您提供更多上下文在调查日志中的问题时,我发现这非常有用,因为它可以立即帮助您更好地完成了解发生了什么我真的很想念我使用的每个其他日志查看器中的该功能。

App Engine的另一个有趣特性是每个HTTP请求都会自动分配一个请求ID它被添加到传入的HTTP请求中并唯一地标识它这可以方便地将请求与其日志相关联例如,我们在发生未捕获的异常时发送电子邮件并包含请求ID - 这使查找日志变得微不足道对于前端错误跟踪也可以这样做。

度量

云控制台访问一些基本应用程序指标这包括请求量和延迟,流量,内存使用情况,实例数和错误计数在调查问题时以及想要快速了解应用程序的一般状态时,它非常有用。

以下是应用程序请求量的示例:

Google Cloud Console  - 图表

追踪

由于App Engine实例是黑盒子,因此您无法使用其他工具来诊断其性能如果日志控制台是不够的,跟踪页面提供更详细的数据它允许搜索某些请求的延迟分布。

Google Cloud Console  - 跟踪

当您选择特定请求时,它会打开一个时间轴它显示您在日志中看不到的远程过程调用(RPC)Plus, a summary for each RPC by type on the side通过单击RPC,可以获得更多详细信息,例如显示响应大小。

这对于找到请求缓慢的原因非常有帮助在下面的示例中,您可以看到请求发出一些快速Memcache调用和一个非常慢的数据存储区写操作。

Google Cloud Console  - 分析

唯一的问题是RPC没有包含足够的信息来确定究竟发生了什么例如,数据存储区写操作的详细视图如下所示:

Google Cloud Console  - 分析详细信息视图

它甚至不包括更新实体的名称这是一个巨大的烦恼,可以使整个屏幕几乎无用只有一件事可以提供帮助:点击右上角的“显示日志”按钮它将包括请求的日志语句排队交错的rpc这样你威力能够从上下文中推断出更多细节。

资源

同样重要的是要指出,定价是完全基于使用这意味着您的应用程序的成本几乎逐字节,逐小时和按操作操作这也意味着,入门非常实惠没有固定成本如果几乎没有人使用你的应用——因为有一个免费的配额——你不需要支付任何费用。

该法案中最重要的项目肯定是针对这些案例,在我上一个项目中贡献了大约80%下一个大块可能是数据存储区的读/写成本,占我们总成本的15%。

Google云端控制台中有一个很好的界面可以跟踪所有配额:

谷歌云控制台——配额

更具体地说,当我说“所有配额”我的意思是所有配额谷歌告诉你我们实际上有一个问题,我们打了一个无形配额一世认为但是,虽然API可能已经在测试版中无论如何,我们的应用程序的一部分停止工作,我们不知道为什么幸运的是,我们被订阅Google Cloud支持他们向我们通报了所述配额,我们不得不重写我们的部分应用程序以使其再次运行。

由于定价设置混乱,我们也遭遇了一次轻微停电有一次,我们的一个应用程序突然停止工作,只是回复了默认的错误页面我们花了十分钟才发现我们达到了我们设定的预算限额在我们提出它之后,一切都开始了。

支持

Google云支持有很多话要说首先,没有它我们会偶尔遇到严重的麻烦因此这是一个必须为任何任务关键型应用程序——在我的眼睛例如,大约每年一次,我们的应用程序将停止提供请求我们没有做任何事情导致这一点联系Google支持后,我们会了解到他们已将我们的应用程序移至“不同群集”它刚刚再次运作这是一个非常可怕的情况除了“向Google众神祈祷”之外,你什么也做不了。

其次,它是基于支持者的命中或错过质量差异很大有时我们需要交换十几条消息,直到他们最终理解我们为止像任何支持一样,它可能令人愤怒但最终,他们通常会解决我们的问题,或者至少给我们足够的信息来帮助我们自己解决问题。

一个新时代

谷歌正在开发一种新型的App Engine灵活的环境It is currently in Beta它的目标是提供两个世界中最好的:App Engine上运行的简便性和舒适性以及Google Compute Engine的灵活性和强大功能它允许在任何功能强大的Google Compute Engine机器(如416GB RAM!)上使用任何编程平台(如Java 9!),同时让Google负责维护服务器并确保应用程序正常运行。

他们已经在这方面工作了好几年了自然,我们热衷于尝试至今,我们并不那么激动但是,让我们看看谷歌在哪里采取这个。

规模设计

现在,您可以查看App Engine对您的应用程序施加的限制作为烦恼但请忍受我一会儿App Engine由Google创建这些人知道如何构建可伸缩的系统这些限制仅仅是必要的它们迫使您调整应用程序以适应云的方式这是一件好事,应该被接受如果您觉得自己正在与App Engine作战,那么您就是在反对云的“新”规则这肯定是我在Google App Engine上花了三年时间的一课。

但是,一些限制和烦恼是谷歌忽视的结果感觉他们只是投入了最低限度实际上,过去两年我有这种感觉令人沮丧的是使用一个古老的技术堆栈,没有任何改善的希望如果存在已知问题但是它们没有修复则令人愤怒收到关于平台前进方向的信息很少令人沮丧你感到困惑。

总而言之,我喜欢App Engine如何让开发团队专注于实际构建应用程序,让用户满意并赚钱谷歌在运营工作中花了很多麻烦但是,“旧”App Engine即将问世我不认为这是一个好主意开始新项目了另一方面,如果App Engine Flexible Environment能够真正解决其前任的主要问题,它可能会成为开发应用程序的一个非常有趣的平台。


评论由Disqus