<![CDATA[云-此编程寿命]manbetx手机版登陆]> 云-这个编程生命manbetx手机版登陆 //www.djindien.com网站/ 幽灵0.11 结婚,2019年2月6日13:55:36格林尼治标准时间 60 <![CDATA[3 years on Google App Engine.史诗审查。]]> <p>在过去的3年里,我在一个运行在谷歌应用引擎上的应用程序上工作。这是一个迷人的,谷歌在这里提供独一无二的服务。不像你在别处能找到的任何东西。这是我的深度,个人体验。<p><img src=“//www.djindien.com/content/images/2017/01/google-app-engine-logo.png”alt><p><h2 id=“googlescloudest2008”>google's cloud(est)。2008)< / h2 > < p >首先,什么是</P> //www.djindien.com/3-years-on-google-app-engine-an-epic-review/ ce13c232 - 987 - c - 4382 ba01 - 48 - b806ac99cd 举办 爪哇 数据存储 谷歌 应用程序引擎 manbetx万博体育 周一,格林尼治时间2017年3月13日15:23:59 <p>在过去的3年里,我在一个运行在谷歌应用引擎上的应用程序上工作。这是一个迷人的,谷歌在这里提供独一无二的服务。不像你在别处能找到的任何东西。这是我的深度,个人体验。<p><img src=“//www.djindien.com/content/images/2017/01/google-app-engine-logo.png”alt><p><h2 id=“googlescloudest2008”>google's cloud(est)。2008)< / h2 > < p >首先,Google应用引擎实际上是什么?它是一个运行Web应用程序的平台。比如<a href=“https://www.heroku.com”>heroku</a>。但当你仔细看的时候就不同了。它也是一个多功能的云计算平台。比如<a href=“https://aws.amazon.com”>aws</a>。但不同。Let me explain.</p><p>Google launched GAE in 2008,当云计算还处于初级阶段时。亚马逊早在2006年就开始出租其IT基础设施。但与盖伊谷歌很早就提供了一个复杂的平台即服务(PaaS),亚马逊在2011年就将其弹性的Beanstalk服务与之匹配。盖伊有什么特别之处?<p><p>it is a<em>fully managed.<em>application platform.到目前为止,我不知道一个平台可以接近GAE的完整包:日志管理,邮件发送,缩放比例,内存缓存图像处理,分布式cron作业,负载平衡、版本管理,任务队列搜索,性能分析,云调试,内容交付网络——这甚至没有提到像SQL一样出现在谷歌云上的辅助服务,BigQu疑问,文件存储…名单还在继续。</p><p>使用谷歌App引擎,你可以在世界上最好的基础设施之上运行你的应用程序。也,您可以获得开箱即用的功能,这些功能至少需要第三方在Heroku上提供12个插件,如果您自己完成,则需要几个星期的设置。<em>这是GAE的吸引力。<p><p>在GAE上运行的值得注意的应用程序包括<a href=“https://www.snapchat.com”>snapchat<a>和<a href=“https://www.khanacolademy.org”>khan academy<a><p><h2 id=“development”>development<h2><p>web a p p i was working on all this time i s a single,大型Java应用程序。App Engine也支持Python,PHP和走。现在你可能想知道为什么选择如此有限。一个原因是为了拥有一个完全管理的环境,谷歌需要将这个平台与环境结合起来。可以说环境和平台是紧密耦合的。这需要大量的努力和投资,一旦您开始为GAE开发,这一点就变得非常清楚了。<p><h3 id=“sdk”>sdk<h3><p>每个应用程序都需要使用一个特殊的sdk(软件开发工具包)来使用GAE提供的API。SDK非常庞大。例如,Java SDK的下载大约为190 MB。授予,其中的一些jar对于大多数用例来说是不需要的,有些只是在开发过程中——但仍然是,它当然不是轻量级的(甚至对于Java来说,that is).</p><p>The SDK is not just your bridge to the world of Google App Engine but also serves as its simulation on your local machine.对于几乎每一个GAE API,它都有一个存根,您可以针对它进行开发。首先,这意味着当你在本地运行你的应用程序时,你会非常接近它在生产中的表现。其次,您可以轻松地针对API编写集成测试。通常这会让你走得很远;生产和存根行为之间的不匹配很小。</P> < H3ID=“JavaAPI”> JAVA API < /H3> < API >当你使用某些Java API时,你会感到惊讶。因为gae在某种类型的<a href=“https://cloud.google.com/appengine/docs/java/runtime”中运行应用程序?csw=1 The The诳Sandbox“>Sandbox</a>,它禁止使用特定的Java api。主要限制包括写入文件系统,<代码> java. Lang.Stase<代码>和使用Java本机接口(JNI)的某些方法。使用线程和套接字也有一些特殊之处,但稍后将详细介绍。有趣的是,Java SDK实际上可以确保您不会在本地使用这些受限制的api。当你运行你的应用或只是一个集成测试,它使用一个监视每个方法调用的Java代理。它会立即为检测到的任何违规抛出异常。这有助于尽早发现违规行为,不仅在生产中,而且会产生令人讨厌的副作用。当你分析应用的性能时,代理将进行大量的违规检查。最后,很难判断你的应用程序的实际性能,因为你做的方法调用越多,the more overhead the agent generates.</p><h3 id="javadevelopmentkitjdk">Java Development Kit (JDK)</h3><p>The next thing you might notice when you start developing is that you can <em>not</em> use Java 8.即使Java 7的生命终结在2015,它仍然是非常活跃和踢同性恋。The third highest voted issue on <a href="https://code.google.com/p/googleappengine/issues">GAE's issue tracker</a> is <a href="https://code.google.com/p/googleappengine/issues/detail?id=9537">support for Java 8</a> (the second highest is support for Python 3).它创建于2013年。从那时起,关于这件事进展的唯一消息就是2016年发布在应用引擎邮件列表上。说明工程师们正在积极地进行这项工作。好,对你有好处。<p>显然,这个限制对于任何开发人员都是一个主要的麻烦。就我个人而言,缺少的lambda支持非常重要。当然,可以迁移到许多JVM语言中的一种,比如groovy,Scala或Kotlin,它们都提供了比Java 8更多的特性。但这是一项代价高昂、风险很高的投资。对我们的项目来说,成本太高,风险太大。我们还研究了<a href="https://github.com/orfjackal/retrolambda">retrolambda</a>的可行性,LAMBDAS到Java 7的后端,但是还没有追求它,尽管它在第一次测试中看起来很有前途。.<p>Having to stay with a old version is also a responsibility for the business.这使得很难找到开发人员。整个应用程序安全受到威胁,也。谷歌支持告诉我们,我们仍然会收到JDK 7产品的安全补丁。但最终,像Spring这样的所有主要图书馆都将停止支持它。最终,您将被卡在部署中。you need to create an <code>appengine-web.xml</code> configuration file.在那里,指定应用程序ID和版本以及一些其他设置,例如将应用程序标记为<代码> THeRealStaby<代码>,以同时接收多个实例的请求。</P> < H3ID=“上载”>上载</H3> < P> AppEngine,希望接收Java应用程序作为打包的WAR文件。您可以使用SDK中的<code>appcfg<code>script将其上载到服务器。可选地,Maven和Gradle都有插件,这些插件可以轻松地编写<code>mvn appengine:update</code>。对于典型的Java应用程序,上传可以花费<em>相当</em>一段时间,你最好有一个快速的互联网连接。一旦过程完成,您可以在谷歌云控制台中看到您新部署的版本:</p><p><img src=" //www.djindien.com/content/images/2017/01/screen - shot-2017/01-22 -15.15.45-2.png" alt="谷歌云控制台- version "></p><h3 id="staticfiles">Static Files</h3><p>Static Files like images,样式表和脚本是当今任何Web应用程序的一部分。In the <code>appengine-web.xml</code> files can be marked as static.谷歌将直接服务这些文件-不打击您的应用程序。它不是内容交付网络(cdn),因为它不分布到数百个边缘节点,但它有助于减少服务器上的负载。<p><h3 id=“versions”>versions<h3><p>The nice thing in a p p engine is that everything you deploy has a specific version.每个版本都可以在<code>https://<version>-dot-<app id>.appspot.com上访问。但哪一个实际上是<em>live?<p><p>You can mark a version as<code>default.<code>。这意味着当您转到<code>https://<app id>.appspot.com时(或您为应用程序指定的域名),会这将是接收所有请求的版本。将版本切换到<code>default<code>非常简单:只需单击按钮或简单的终端命令。GAE可以立即切换或增量迁移您的流量,以防止压倒新版本。<p>还有一个选项(我们从未使用过)允许您将流量分布到多个版本。这就允许在每个人都可以使用新版本之前,只将其提供给一小部分用户群,从而逐步推出新版本。<p>Since it is so easy to create new versions and switch production traffic between them,GAE是一个完美的实践平台<a href=“https://martinfowler.com/bliki/blue green deployment.html”>blue-green deployment<a>。每次我们因为新版本中的错误而需要回滚时,这是毫不费力。通过编写某种智能的部署脚本,也可以实现持续交付。每个版本都可以运行任意数量的实例(唯一的限制是您的信用卡)。实际数量是传入流量和应用程序的缩放配置的结果;我们稍后再看。Google将在该版本的所有运行实例之间分发传入的请求。你可以看到一个实例列表,包括一些基本指标,比如请求和延迟,在google cloud console中:<p><img src=“//www.djindien.com/content/images/2017/01/screen-shot-2017-01-22-at-15.28.57.png”alt=“google cloud console-instances”><p><p>The hardware options you can choose from to run these instances on are-let's be frank here-pathetic.app engine基本上提供了四种不同的<a href=“https://cloud.google.com/app engine/docs/about the standard environment instance _classes“>instance classes<a>范围从128MB和600MHz cpu(正确读取)到1024MB和2.4GHz cpu。对,再一次,那是真的。和真正的悲伤。在开发人员的笔记本电脑上,我们的应用程序的启动速度几乎是生产中的两倍。<p><h3 id=“services”>services<h3><p>so far,我只谈过单身,独立的应用程序。但是,如果您的服务由多个服务组成,您会怎么做?应用引擎为您提供服务。每个应用程序都是一项服务。如果你只有一个,它被简单地称为<code>default<code>。您可以通过<code> -dot-< version>-dot-<service>-dot-< App -id>.appspot.com > /code>.</p><p><img src=" //www.djindien.com/content/images/2017/02/screen - shot -2017-02-20- 21.36.57.png" alt="App Engine Application,服务,版本和实例“><p><p>You can easyly deploy multiple versions of each service,分别缩放和监控。因为每项服务都是独立的,您可以运行任何受支持语言的组合。但不幸的是,一些配置设置在所有服务之间共享。因此,它们并不是完全孤立的。仍然,总而言之,gae似乎很适合微服务。有一些<a href=" https://cloud.google.com/appengine/docs/java/microservices-onapp-engine ">详细的文档</a>,也。<p>for reasons that will been clear later,<p>for reasons that will been clear,我们决定将应用程序分为两个服务:前端(面向用户)和后端(后台工作)。但要做到这一点,实际上,我们并没有将整块巨石一分为二——这需要几个月的时间。We simply deployed the same app twice and only sent users to one service and background work to the other.</p><h2 id="operations">Operations</h2><p>Let's talk about what it means to <em>run</em> your application on App Engine.如你所见,它对你有很多限制。但这并不都是悲观的。In the end you will understand why.</p><h3 id="applicationstartup">Application Startup</h3><p>When App Engine starts a new instance,应用程序需要初始化。它要么直接将用户的HTTP请求发送到应用程序,要么(如果配置和伸缩环境允许的话)发送所谓的预热请求。无论哪种方式,第一个请求称为加载请求。你可以想象,starting quickly is important.</p><p>The instance itself on the other hand is ridiculously fast to start.如果您以前在云中启动过服务器,你可能等了一分钟多。不是在盖伊上。实例几乎立即启动。我想谷歌有一个服务器池准备好了。瓶颈总是你自己的应用程序。我们的应用程序用了40多秒才开始生产。所以除非我们想把我们庞大的整体分割成独立的服务,我们需要它来提高效率。</p><p> app使用Spring谷歌甚至有专门的文档条目:<a href="https://cloud.google.com/appengine/articles/spring_optimization"> optimization Spring Framework for App Engine Applications</a>。在那里,我们找到了最重要的启动优化的灵感。<p>我们摆脱了Spring的类路径扫描。它在App Engine上特别慢(可能是由于糟糕的CPU)。幸运的是,有一个名为classindex的库。它将具有特殊注释的类的完全限定路径写入文本文件。只需从文本文件中读取bean,Spring初始化下降了约8-10秒。<p><h3 id=“RequestHandling”>Request Handling<h3><p>The very first thing I have to notify here is the requirement of the a p p engine to handle a user request within 60 seconds and a background request in 10 minutes.当应用程序花费太长时间来响应时,请求被中止,状态代码为500,异常情况为<code>deadlineexceedexception<code>is through.<p>通常,这应该不成问题。如果你的应用程序的响应时间超过60秒,很有可能用户早就不在了。但由于实例是通过HTTP请求启动的,这也意味着它必须在60秒内启动。在生产中,我们观察到启动时间变化达10秒。这意味着你现在有不到50秒的时间来启动你的应用程序。Java应用程序花这么长时间并不少见。</P> < P>一个很好的小功能,我想强调的是地理HTTP报头:对于每一个传入的用户请求,谷歌添加了包含用户国家的标题,区域,城市及其经纬度。这可以是<em>非常</em>有用,例如,预填电话号码国家代码或检测异常帐户登录位置。从我们的观察来看,精确度似乎也相当高。从第三方API或数据库中获得这样高精度的信息通常非常麻烦和/或昂贵。So getting it for free on App Engine is a nice bonus.</p><h3 id="backgroundwork">Background Work</h3><h4 id="threads">Threads</h4><p>As mentioned earlier,使用Java线程有限制。虽然可以启动一个新线程,尽管通过自定义GAE<code>threadmanager<code>,它不能“活过”创建它的请求。这在实践中可能很烦人,因为第三方库不遵守应用程序引擎的限制,当然可以。要找到一个兼容的库或修改一个看似不兼容的库,这些年来我们付出了很多汗水和眼泪。例如,我们无法使用<a href=“https://github.com/dropwizard/metrics”>dropwizard metrics<a>library out of the box,因为它依赖于使用后台线程。<p><h4 id=“queue”>queue<h4><p>但是还有其他方法来执行后台工作:in the spirit of the cloud,您可以在实例级别上应用分治方法。通过使用<HeRF=“http://Loop.com /AppEngine /DOCS/Java/TaskQue/”>任务队列</A>,您可以排队等待以后的处理。例如,当需要发送电子邮件时,你可以用有效负载(例如:收件人,subject和body)和一个url。然后,您的一个实例将作为对指定端点的HTTP POST请求接收有效负载。如果失败了,a p p engine将重试此操作。<p><p>当您有大量工作要处理时,此模式真的很亮。只需将一批独立运行的任务排队即可。应用程序引擎将负责处理故障。不需要自定义重试代码。想象一下没有它会有多尴尬:一次运行数百个任务,当发生错误时,您要么需要停止并从头开始,要么仔细跟踪哪些任务失败了,然后再次将它们排队进行另一次尝试。<p>and just like the rest of the app engine,任务队列的规模非常庞大。队列可以接收几乎无限的任务。缺点是有效负载最多只能达到1 MB,虽然。但我们通常只是简单地将对数据的引用传递给队列。但是,在处理数据时,您需要格外小心,因为很容易在您将任务排队到实际执行该任务的时间之间,会有一些东西消失。<p><p>The queues are configured in a<code>queue.xml.<code>file.下面是一个推送队列的示例,该队列每秒最多触发一个任务,最大重试次数为两次:<p><pre><code class=“language xml”><queue><name>my push queue<name><rate>1/s<rate><retry parameters><task retry limit>2<task retry limit><retry parameters><queue><code><pre><h4 id=“cron”>cron<h4><p>another extreme valible工具是分布式cron。In a <code>cron.xml</code> you can tell GAE to issue requests at certain time intervals.这些只是一个实例将接收到的简单HTTP GET请求。可能的最小间隔是每分钟一次。它对定期报告非常有用,电子邮件和清理。<p><p>This is what an entry in<code>cron.xml</code>looks like:<p><pre><code class=“language xml”><cron><url>/tasks/summary<url><schedule>every 24 hours.<schedule><cron><code><p>a cron job can also be combined with<em>pull<em>queues:they allow to activitive fetch a batch of tasks from a queue.取决于用例,使一个实例在一个批处理中拉取大量任务比单独将它们推送到实例中效率更高。<p><p>like all other a p p engine configuration files,在应用程序的所有服务和版本之间共享<code>cron.xml。这很烦人。在我们的例子中,有时,当我们部署一个版本,其中添加了一个新的cron条目时,应用程序引擎将开始向一个端点发送请求,该端点在活动(但较旧)版本上不存在,从而为我们的生产错误报告生成噪音。我想,当使用应用引擎托管微服务时,这肯定会更加痛苦。<p>also,cron作业不在本地运行。我可以理解为什么会这样:很多工作通常安排在通常繁忙的时间之外,因此在正常工作日甚至不会触发。但是,每隔几分钟或几小时运行一次,这些都是非常有趣的观察。它们可能触发通知,为例。你想在当地看到这些。因为最终您将引入一个导致不良行为(在我们的项目中多次发生)的变更,并且在本地看到它可能会阻止您装运它。但是在本地模拟cron作业是很棘手的(我们不费心,不幸的是)One would probably need to write an external tool that parses the <code>cron.xml</code> and then pings the according endpoints (yuck!).</p><h3 id="scaling">Scaling</h3><p>App Engine will take care of scaling the number of instances based on the traffic.如何?好,取决于您如何配置应用程序。有三种模式:</p><ul><li><strong>Automatic:</ p>这是GAE独特的卖点。它将根据请求率和响应延迟等指标来扩展实例的数量。如果流量很大或者你的应用反应很慢,更多实例启动。<li><li><strong>manual:<strong>基本上喜欢您的旧虚拟专用服务器。你告诉谷歌你想要多少实例,谷歌提供。如果您知道要获得什么流量,这个固定的实例大小很有用。<li><li><strong>basic:<strong>本质上与手动缩放模式相同,但是当实例变为空闲时,它是关闭的。<li>><ul>><p>这里最有用和最有趣的一个当然是<em>自动模式</em>。它有一些参数可以帮助您了解它的内部工作方式:<code>max_concurrent_requests</code>,<code>max_idle_instances<code>,<代码> min_idle_instances < /代码>和<代码> max_pending_latency > < /代码。引用应用引擎文档:<p><blockquote><p>The app engine scheduler decides when to service each new request with an existing instance(either one that is idle or accepts concurrent requests),将请求放入挂起的请求队列中,或者为该请求启动一个新实例。该决定考虑到可用实例的数量,应用程序服务请求的速度(延迟时间)有多快,以及每次我们试图调整这些数字时,旋转一个新实例所需的时间。<p>.<blockquote><p>感觉就像在练习黑魔法。实际上很难推导出一个好的设置。然而,这些数字决定了你的应用程序的真实性能,并极大地影响你的每月账单。<p>but all in all,自动缩放非常糟糕。它特别适合处理背景工作(例如生成报告,(发送电子邮件)由于它经常——比用户请求更频繁——大量出现,sudden bursts.</p><p>But the thing is,Java是一个可怕的适合这种类型的自动缩放,因为其启动时间慢。更糟的是,调度器将一个请求分配给从</em>(冷)实例开始的<em>是非常常见的。然后,所有进入亚秒休息反应的努力都被抛到了窗外。自2012年以来,有关于<a href=“https://code.google.com/p/googleappengine/issues/detail的问题吗?id=7865“>面向用户的请求永远不会锁定到冷实例上。它甚至没有引起google的任何评论,除了状态更改为“已接受”(听起来像是此时的悲伤阶段之一)。<p><p>This also explains why we split our app into two services.之前,我们经常发现随着后台请求的激增,用户请求会受到影响。这是因为应用引擎极大地扩展了实例,由于请求是跨实例均匀路由的,这导致更多的用户请求命中冷实例。通过拆分应用程序,我们大大减少了这种情况的发生。也,我们能够为这两个服务应用不同的扩展策略。<p>One last thing:in a side project,我使用了Go on App Engine,发现了一个关于App Engine的新视角。Go的特点之一是能够即时启动应用程序。这使得应用引擎成为完美的组合,像蝙蝠侠和罗宾。一起,自从我了解到云之后,它们就体现了我个人对云的所有期望。它可以真正地适应工作负载,而且很容易做到。即使是糟糕的硬件选项似乎也不会给Go带来真正的问题,因为它是如此高效。<p><h2 id=“data”>data<h2><p>when a p p engine launched,唯一的数据库选项是用于结构化数据的google datastore和用于二进制数据的google blobstore。从那时起,他们添加了谷歌云SQL(ManagedMySQL)和谷歌云存储(如亚马逊的S3),取代了blobstore。从一开始App Engine就提供了一个托管的Memcache,as well.</p><p>It used to be very difficult to connect to a third-party database since you could only use HTTP for communication.但通常数据库需要原始TCP。这种情况在几年前Socket API发布时才有所改变。但在beta中仍然是<em>still<em>这使得对于关键任务的使用来说,它是一个值得怀疑的选择。所以database-wise,仍然有很多供应商锁定。无论如何,P>一开始,只有数据存储。<p><h3 id=“datastore”>datastore<h3><p>The datastore is a proprietary nosql database,完全由谷歌管理。它不像我以前用过的任何东西。它是一种巨大的鳞状动物,具有非常独特的特征,保证和限制。<p>数据存储基于主从设置,具有强一致的读取功能。几年之后,在经历了几次严重的外泄之后,google<a href=“http://googleappengine.blogspot.ca/2011/01/announcing high replication datastore.html”>引入了新的配置选项</a>:high replication。API保持不变,但写入延迟增加,一些读取最终变为<em>一致(稍后详细介绍)。其好处是显著提高了可用性。它甚至拥有99.95%的正常运行时间SLA。自从我和它合作以来,我从未遇到过数据存储可用性的单一问题。It was just something you did not have to think about.</p><h4 id="entities">Entities</h4><p>The basics of the Datastore are simple.您可以读写实体。它们被分类为特定的类型。实体由<em>属性组成。属性具有具有特定类型的名称和值。类似于<code>string<code>,<代码>布尔> < /代码,<code>float<code>或<code>integer<code>。Each entity also has a unique <em>key</em>.</p><h4 id="writing">Writing</h4><p>There is no schema whatsoever,虽然。具有相同类型的实体看起来完全不同。这使得开发非常简单:只需添加一个新属性,保存它,它就会在那里。另一方面,您需要编写自定义迁移代码来重命名属性。这样做的原因是一个实体不能在适当的位置更新——它必须被加载,更改并再次保存。根据实体的体积,这可以成为一个非常重要的任务,因为您可能需要使用任务队列来规避请求时间要求。根据我的经验,这会导致整个地方出现旧的属性名,因为重构成本高且危险。<p>There are a some<a href=“https://cloud.google.com/datastore/docs/concepts/limits”>limits for working with entities.<a>。两个最关键的是:<p><ul><li>an entity may only be 1MB in total,包括编码实体的附加元数据<<li>You can only write to an entity(group,准确地说)在实践中,最多每秒一次</li></ul><p>,这可能是个问题。我们很少达到尺寸限制-但当我们做到了,这是痛苦的。客户数据可能会丢失。当您达到写速率限制时,下次试穿通常都可以。但当然,您必须设计应用程序,以最小化这种可能性。例如,像定期更新计数器这样的东西需要大量的工作才能正常工作。Google even has a documentation entry on <a href="https://cloud.google.com/appengine/articles/sharding_counters">using sharding to build a counter</a>.</p><h4 id="reading">Reading</h4><p>An entity can be fetched by using its key or via a query.按键读取是强一致的,这意味着即使您在获取实体之前对其进行了更新,您也将收到最新的数据。然而,对于查询,这不是真的。它们最终是一致的。所以写并不总是立即反映出来。这可能会导致问题,可能需要减轻,例如,通过智能数据建模(例如使用助记键或利用特殊的数据存储功能(例如实体组)。<p><p>a query always specify an entity kind and optional filters and/or sort orders.必须索引筛选器或排序键中使用的每个属性。添加索引只能作为常规写入操作的一部分完成。不像大多数SQL数据库那样在后台自动执行。索引还将增加写入操作的时间和成本(稍后将详细介绍)。</p><p>如果查询涉及多个属性,它需要一个多索引。它必须在一个名为<code>data astore-index .xml</code>的配置文件中指定。这里有一个例子:<p><pre><code class=“language xml”><datastore index kind=“employee”ancestor=“false”><property name=“lastname”direction=“asc”/><property name=“hiredate”direction=“desc”<datastore index><code><pre><p>in contrast to other databases,缺少多个索引不仅会导致效率低下,慢速查询-它将立即失败。数据存储尽其所能地强制执行性能查询。不等式滤波器,例如,仅支持单个属性。当然,总是有办法射自己的脚-但他们是罕见的。</p><p>还有其他几个功能我现在还不能讲,例如分页,预测查询和事务。转到<HeRF=“http://x.com,AppEngine /DOPCs/Stimult/Java/DATASOR/API概览”>数据存储文档</A>以了解更多信息,与其他数据库相比,读写操作非常慢。根据我的观察,按键读取平均需要10-20毫秒。很少看到明显的偏差。我的最佳猜测是,谷歌序列化实体,实际上只有索引保存在内存中。<p>The pricing model appears to support that:You pay for stored data,阅读,写入和删除操作。就是这样。请注意,数据库内存不在该列表中。操作本身也很便宜:读取10万个实体需要花费0.06美元,100k写操作花费$0.18—写操作可以是实际的实体写,也可以是每个索引写。如果你什么都不写,你什么都不用付。但在一分钟内,您就可以写入千兆字节的数据。但问题是:对于没有实体或十亿的数据库,读写性能基本上是相同的。它像疯了一样伸缩。><h4 id="api"> api </h4><p>数据存储的api感觉<em>非常</em>底层。因此,对于任何严肃的Java应用程序,都没有办法绕过<HReF=“http://Github.com/Objyf/ObjyFy”> ObjyFix/A>。这是杰夫·施尼策写的图书馆。如果谷歌还没有这样做,他们应该给他开一张巨额支票,感谢他让应用引擎变得更好。他写这本书是为了自己的事业,但多年来他孜孜不倦的奉献,他在论坛上提供的大量文档和支持令人震惊。客观化,使用数据存储是非常有趣的。< /P> < P>这里是一个例子,从文档:</P><Prime>代码类=“语言Java”> @ Entityclass CAR{@ ID字符串VIN;String color;}ofy().save().entity(new Car("123123",“红色”(现在);car c=ofy().load().type(car.class).id(“123123”).now();ofy().delete().entity(c);<code><pre><p>objectify makes it really easy to declare entities as simple classes and then takes care of all the mapping between the datastore.<p><p>it also have a some tricks up its sleeve.例如,它带有一级缓存。这意味着,每当您通过键请求实体时,它首先检查请求范围的缓存是否已提取实体。这有助于提高性能。然而,它也可能会令人困惑,因为当您提取实体并修改它时,但是不要<em>保存它,下一次读取将产生相同的缓存,修改对象。This can lead to Heisenbugs.</p><h4 id="developmenttesting">Development & Testing</h4><p>Since the App Engine is a proprietary cloud database,你不能只在本地启动它。在计算机上运行应用程序时,模拟数据存储由SDK启动。它的行为非常接近于生产环境。只有性能好得多,这可能会产生误导。</p><p>用于对数据存储运行测试,SDK还可以为您启动本地数据存储。然而,这必须是一个不同的实现,因为它的行为不同于运行应用程序的实现。当您意识到丢失的多索引将在本地执行应用程序时抛出错误,而不是在测试同一查询时,这一点就会变得明显。多年来,我不小心将几个索引缺失的查询发布到了生产环境中(通常仍处于beta切换之后),尽管我对此进行了测试。在与技术支持部门取得联系后,他们承认了这一疏忽,并承诺将予以纠正——一年多过去了,他们仍然没有这样做。><h4 id="backup "> backup </h4><p>对数据存储进行备份是一个非常糟糕的过程。有手动和自动两种方式。当然,当您有一个生产应用程序时,您希望有定期备份。The official way is a feature introduced in 2012 which is still in Alpha!</p><p>By adding an entry to your <code>cron.xml</code> you can initiate the backup process.条目将包括要备份的实体的名称,以及保存它们的Google云存储桶。当时间到了,它将用备份代码启动一些python实例,迭代数据存储并以某种专有的备份格式保存到您的bucket中。有趣的是,一个bucket可以包含多少个文件,所以你最好偶尔用一个新桶。</p><p>This is the absolute worst thing about the Datastore.</p><h3 id="memcache">Memcache</h3><p>The other crucial way to store data on App Engine is Memcache.默认情况下,得到一个<em>共享</em> Memcache。这意味着,它是在尽最大努力的基础上工作的,无法保证它将有多少能力。还有每GB每小时0.06美元的专用memcache。<p>Objectify is able to use this as a second level cache.只需用<code>@Cache</code>注释一个实体,它会在数据存储之前询问Memcache,并首先保存那里的每个实体。这会对性能产生巨大影响。通常Memcache会在5毫秒内响应,这比数据存储快得多。我不知道我们可能遇到过任何陈旧的缓存问题。So this works very well in production.</p><p>The benefits of it are actually very noticeable when Memcache is down.这种情况大约每年发生一次,持续一两个小时。我们的网站几乎无法使用,速度很慢。<p><h3 id=“big query”>big query<h3><p><a href=“https://cloud.google.com/big query/”>big query<a>is a data warehouse as a service,由谷歌管理。You import data - which can be petabytes - and can run analyses via a custom query language.</p><p>It integrates somewhat well with the Datastore since it allows to import Datastore backup files from Google Cloud Storage.我用过几次,不幸的是,并非总是成功。对于<em>,我们实体中的一些</em>,我收到了一个神秘的错误。我一直搞不清楚到底是哪里出了问题。但有些实体确实起了作用。在修改了一些查询语言文档之后,我能够产生我的第一个见解。所有的考虑,这是一种运行简单分析的好方法。如果不编写自定义代码,我肯定无法做到这一点。但我并没有充分利用这项服务的全部潜力。我所做的所有查询都可以直接在任何SQL数据库中完成,我们的数据集非常小。只有因为数据存储的工作方式,我才不得不首先求助于BigQuery服务。<p><h2 id=“monitoring”>monitoring<h2><p>Google Cloud控制台带来了许多功能来诊断应用程序在生产中的行为。只需看看谷歌云控制台导航:<p><p><img src=“//www.djindien.com/content/images/2017/02/screen-shot-2017-02-27-at-19.58.46.png”alt=“google cloud console-monitoring”><p>this is the result of<a href=“https://techcrunch.com/2014/05/07/google acquires cloud monitoring service stackdriver/”>google's acquisition of StackDriver</a>2014年。它仍然感觉是独立的,独立服务-但其与Google云控制台的集成正在改进。<p><p>让我们逐个查看功能。<p><h3 id=“logging”>logging<h3><p>it is critical to access an application's logs quickly and with ease.这是一个真正痛苦的应用程序引擎开始。它过去非常繁琐,因为它无法搜索应用程序的所有版本。这意味着当你在找东西的时候,你必须知道当时哪个版本是在线的-或者尝试几个版本,逐一地。它几乎不能用了。再加上它非常慢。<p><p>从那时起,他们添加了有用的过滤器,只显示特定的模块,版本,日志级别,用户代理或状态代码。它非常强大。仍然不快速但现在比早期好多了。以下是它的外观:<p><p><img src=“//www.djindien.com/content/images/2017/02/screen-shot-2017-02-27-at-20.26.16.png”alt=“google cloud console-logging”><p><p>one very unique idea you can see here is that logs are always grouped by request.在我遇到的所有其他工具中,例如,基巴纳,您将只得到与您的搜索匹配的日志行。通过始终显示与搜索匹配的所有其他日志行,它给你更多的背景。在调查日志中的问题时,我发现这非常有用,因为它可以立即帮助您更好地理解所发生的事情。我真的很怀念我使用的每一个其他日志查看器中的这个特性。<p>应用引擎的另一个有趣特性是,每个HTTP请求都自动分配了一个请求ID。它被添加到传入的HTTP请求中并唯一地标识它。这有助于将请求与其日志关联起来。例如,我们在发送电子邮件时,发生了一个未捕获的异常并包含了请求ID——这使得查找日志变得很简单。The same can be done for frontend error tracking.</p><h3 id="metrics">Metrics</h3><p>The Cloud Console gives access to a few basic application metrics.这包括请求量和延迟,交通量,内存使用情况,实例数和错误计数。当您调查一个问题以及想要快速获得应用程序一般状态的第一印象时,它作为一个起点非常有用。<p><p>here is an example with the a p p's request volume:<p><img src=“//www.djindien.com/content/images/2017/01/screen-shot-2017-01-22-at-15.44.06.png”alt=“google cloud console-graphs”><p><h3 id=“tracing”>tracing<h3><p>since the a p p engine instance is a black box,不能使用其他工具来诊断其性能。如果日志控制台不够,<em>Trace</em>页提供了更详细的数据。它允许搜索特定请求的延迟分布。<p><img src=“//www.djindien.com/content/images/2017/02/screen-shot-2017-02-20-at-22.31.44.png”alt=“google cloud console-trace”><p>when you select a specific request,它打开了一个时间线。在这里,它显示在日志中看不到的远程过程调用(RPC)。另外,侧边按类型列出的每个RPC的摘要。单击一个RPC,更多细节,例如响应大小,显示。<p><p>这对于查找缓慢请求的原因非常有用。In the following example you can see that the request makes a few fast Memcache calls and a very slow Datastore write operation.</p><p><img src="//www.djindien.com/content/images/2017/02/Screen-Shot-2017-02-20-at-22.32.49.png" alt="Google Cloud Console - Analysis"></p><p>The only problem is that the RPCs do not include enough information to figure out what happened exactly.例如,数据存储写入操作的详细视图如下所示:<p><p><img src=“//www.djindien.com/content/images/2017/02/screen-shot-2017-02-21-at-08.14.16.png”alt=“google cloud console-analysis detail view”><p>it does not even include the name of the updated entity.这是一个巨大的烦恼,可以使整个屏幕几乎无用。只有一件事可以帮助你:点击右上角的“显示日志”按钮。它将包括请求的日志语句<em>inline</em>interleaved with the rpcs.This way you <em>might</em> be able to infer more details from the context.</p><h2 id="resources">Resources</h2><p>It is also important to point out that pricing is completely usage-based.这意味着你的应用程序的成本几乎是一个字节一个字节地扩展,按小时和按操作操作。这也意味着,这是非常负担得起的开始。没有固定成本。如果几乎没有人使用你的应用程序-因为有一个免费配额-你不支付任何东西。<p>The maximum item on the bill will most certainly be for the instances,在我上一个项目中贡献了大约80%。下一大块可能是数据存储读/写成本,15% of the total cost for us.</p><p>There is a nice interface in the Google Cloud Console to keep track of all quotas:</p><p><img src="//www.djindien.com/content/images/2017/03/Screen-Shot-2017-03-13-at-11.33.20.png" alt="Google Cloud Console - Quotas"></p><p>To be more specific,当我说“所有配额”时,我是指谷歌告诉你的所有配额。我们实际上遇到了一个问题,我们遇到了一个不可见的配额。我认为在API可能已经进入测试版的时候,虽然。不管怎样,应用程序的一部分停止工作,我们不知道为什么。幸运的是,我们订阅了谷歌云支持。他们通知我们有关所述配额的信息,我们必须重写应用程序的一部分以使其再次工作。<p>We also have one minor interrupt due to the mizzle pricing setup.有一次,我们的一个应用程序突然停止工作,只是用默认的错误页面回复。我们花了十分钟才发现我们达到了我们设定的预算限额。在我们提出之后,一切都重新开始工作。<p><h2 id=“support”>support<h2><p>关于google cloud support有很多话要说。首先,如果没有它,我们有时会遇到严重的麻烦。因此,在我看来,对于任何任务关键型应用程序来说,拥有它都是必须的。例如,大约一年一次,我们的应用程序将停止服务请求。我们什么也没做。在联系了谷歌支持之后,我们会了解到他们将我们的应用程序移动到了“不同的集群”。它又开始工作了。这是一个非常可怕的情况。You cannot do anything but 'pray to the Google gods'.</p><p>Second of all,它是基于支持人员的成功或失败。质量变化很大。有时我们需要交换一打信息,直到他们最终理解我们。就像任何支持一样,这可能会让人愤怒。但最后,they would usually resolve our issue or at least give us enough information to help us resolve it ourselves.</p><h2 id="anewage">A New Age</h2><p>Google is working on a new type of App Engine,<a href="https://cloud.google.com/appengine/docs/flexible/">flexible environment</a>。目前它还处于测试阶段。它的目标是提供两个世界中最好的:在App Engine上运行的便利性和舒适性,以及谷歌计算引擎的灵活性和强大功能。它允许使用任何编程平台(如Java 9!)在任何强大的谷歌计算引擎机器上(比如416GBRAM!)同时让Google负责维护服务器并确保应用程序运行良好。<p>他们已经为此工作多年了。自然地,我们渴望尝试一下。到目前为止,<a href=“https://tech.small-improvements.com/2016/09/12/running-our-app-engine-application-in-the-flexible-environment-java-8/”>我们没有那么兴奋</a>。但是,让我们看看Google是从哪里开始的。<p><h2 id=“DesignForscale”>Design for scale<h2><p>now,您可以将应用程序引擎对应用程序施加的限制视为烦恼。不过,请稍等片刻。应用引擎是由谷歌创建的。这些人知道如何构建可扩展的系统。这些限制只是必要的。它们迫使你使你的应用程序适应云计算的方式。这是一件好事,应该被接受。如果你觉得自己在和应用引擎较劲,那么你就是在与云计算的“新”规则作斗争。This is certainly one lesson I'm taking away from three years on Google App Engine.</p><p>Some restrictions and annoyances are the result of neglect by Google,虽然。感觉他们只投资了最低限度。实际上,过去两年我一直有这种感觉。与一个古老的科技堆合作是令人沮丧的,看不到任何改善的希望。如果有已知的问题但没有得到解决,那将是令人恼火的。令人沮丧的是,关于该平台走向的信息如此之少。你觉得被困住了。<p>All in all,我喜欢应用引擎如何让开发团队专注于实际构建应用程序,让用户快乐并赚钱。谷歌从运营工作中解决了很多麻烦。但“老”应用程序引擎正在退出。我不认为在它上面再开始新的项目是一个好主意。另一方面,如果App Engine的灵活环境可以解决其前身的主要问题,它可能成为开发应用程序的一个非常有趣的平台。<p>