简体   繁体   English

优化Google App Engine的应用程序体系结构和实现

[英]Optimizing Application Architecture and Implementation for Google App Engine

It's my understanding that billing on GAE all boils down to instance-hours ("IH"), or how many server instances are running for some duration of time. 据我了解,GAE的计费全部归结为实例小时数 (“ IH”),或在一定时间内运行了多少个服务器实例。 However, it is obviously not that simple, because in addition to IH you quotas and resource limits that you must be leary of throughout the course of the day (since quotas replenish every 24 hours). 但是,这显然不是那么简单,因为除了IH之外,您还必须在一天的整个过程中保持配额和资源限制(因为配额每24小时会补充一次)。

I am in the process of designing my first GWT/GAE app, and have come across many articles (some of which are cited below) where the authors talk about major refactorings they had to make to their code - post release - in order to help minimize billing and operational costs with Google. 我正在设计我的第一个GWT / GAE应用程序,并且遇到了许多文章(下面引用了其中的一些文章),在这些文章中,作者谈论了他们必须对代码进行的重大重构-发布后-以帮助与Google最大限度地减少结算和运营成本。

In one instance, a developer implemented a set of optimizations to his GAE app which caused the same app to go from $7/day (~$220/month) down to $0 because it was finally under the "free" quotas and billing thresholds for resources. 在一个实例中,开发人员对其GAE应用程序进行了一系列优化,导致同一应用程序从每天7美元(约合每月220美元)下降到0美元,因为它最终处于“免费”配额和资源计费阈值以下。

Being so new to GAE, I'm wondering if there are any set of principles or practices I can incorporate into the architecture/design of my app upfront, that once trickled down into implemented, functional code and deployed to GAE, will cause the app to run as efficiently (monetarily-speaking) as possible. 对于GAE而言,它是如此陌生,我想知道是否有任何原则或实践可以整合到我的应用程序的架构/设计中,一旦被扎入到已实现的功能代码中并部署到GAE,将会导致该应用程序以尽可能高效地运行(以语言进行交流)。

Here are some deductions I've made so far: 到目前为止,我做了一些推断:

  • Maximize caching and minimize datastore hits 最大化缓存并最小化数据存储命中
  • Try to push as many asynchronous request handling to backend instances as possible 尝试将尽可能多的异步请求处理推送到后端实例
  • Enable concurrent HTTP request handling so that the same instance can handle multiple requests at the same time 启用并发HTTP请求处理,以便同一实例可以同时处理多个请求

So my question: are any of these generalizations I've made incorrect, and if so, why (or are they conditional, where they hold true in some cases but not in others)? 所以我的问题是:我对这些归纳法中的任何一项都做错了吗?如果是,为什么? Am I missing anything critical here? 我在这里错过任何重要的东西吗? For instance, how to determine what code belongs on a backend instance (where resource constraints are little more lax), making use of what kinds of GAE-specific profiling tools (AppStats, SpeedTracer, etc.) to see bottlenecks, etc. 例如,如何确定哪些代码属于后端实例(资源约束更为宽松),如何利用GAE特定的分析工具(AppStats,SpeedTracer等)来查看瓶颈等。

Also, some cited articles: 另外,一些引用的文章:

Based on experience, there are a huge laundry list of strategies for App Engine optimization, the applicability of which depends on the nature of your apps. 根据经验,适用于App Engine优化的策略有很多,其适用性取决于您应用的性质。 Here are some more tips that I know of: 以下是一些我所知道的提示:

  • For apps that serves a high amount of relatively static content, enabling the (as yet undocumented) edge caching could be a blessing to your weekly bills. 对于提供大量相对静态内容的应用程序, 启用(尚未记录的)边缘缓存可能是您每周账单的一大福音。

  • Even with concurrent requests/threadsafe enabled, each frontend instances could only process 8 (for Python) to 10 (Java, Go) simultaneous incoming request before the scheduler decides to spin up a new instance for you. 即使启用了并发请求/线程安全 ,在调度程序决定为您启动一个新实例之前,每个前端实例也只能处理8个(对于Python)到10个(Java,Go)同时传入的请求

  • To counter the above restriction, I think there's a Google I/O video that recommends you to reduce the response time for any user-facing request going to the frontend instances to be ~100 ms. 为了克服上述限制,我认为有一个Google I / O视频建议您将前往前端实例的任何面向用户的请求的响应时间减少到100毫秒。

  • To the tune of the above strategy, if you have any task that requires a large amount of processing or datastore I/O, offload the task to the push task queue , and immediately respond the request. 根据上述策略,如果您有任何需要大量处理或数据存储I / O的任务,请将任务卸载到推送任务队列中 ,然后立即响应请求。 You can specify the target of the task queue , but for this purpose it does not need to be the backend, frontend instances are good enough, and offer infinite scalability. 您可以指定任务队列目标 ,但是为此,它不必是后端,前端实例足够好,并提供无限的可伸缩性。

  • If you use the above strategy but still need to give the result of the processing or I/O to the user, use Channel API or any other messaging services to send the result back asynchronously. 如果您使用上述策略,但仍需要将处理或I / O的结果提供给用户,请使用Channel API或任何其他消息传递服务将结果异步发送回。

  • Task queues are amazing stuff to distribute the workload of your app. 任务队列是分发应用程序工作负载的绝佳工具。 You could customize its behavior in detail , and they are invaluable in making sure your app scales nicely. 您可以详细自定义其行为 ,它们对于确保应用程序可扩展性非常宝贵。 You can even have a two-way communication between instances using both push and pull queues. 您甚至可以使用推和拉队列在实例之间进行双向通信。

I'll add more points later on. 稍后再添加更多点。

Most of the time, cost optimizations will be specific to your app. 在大多数情况下,成本优化将针对您的应用。 Since you're asking about general principles, they mostly apply to CPU and datastore. 由于您在询问一般原则,因此它们通常适用于CPU和数据存储。

CPU: 中央处理器:

Watch out about paying for a stalled CPU. 提防为停滞的CPU付款。 If your CPU is stalled on a long operation (a slow datastore request, or a URL fetch, etc), App Engine may launch another instance, driving up your cost. 如果您的CPU在长时间的操作(缓慢的数据存储请求或URL提取等)上停滞不前,则App Engine可能会启动另一个实例,从而增加了成本。 There's a number of strategies for this - enable threading, task queues. 为此,有许多策略-启用线程,任务队列。 I suspect when you talked about putting asynchronous requests on backends, it's to solve this problem as well. 我怀疑当您谈论将异步请求放在后端时,它也可以解决此问题。 There's multiple ways to handle this. 有多种处理方法。

Datastore: 数据存储:

  1. Control your indexes carefully. 仔细控制索引。 Indexing contributes a lot to your costs. 索引对您的成本有很大贡献。

  2. Design your datstore carefully to minimize the number of requests you need. 精心设计数据存储区,以最大程度地减少所需的请求数量。

  3. Denormalize. 非正规化。 Denormalizing is pretty standard procedure for NoSQL datastores. 对于NoSQL数据存储,非规范化是非常标准的过程。 Essentially, it means store duplicate data in multiple entities when necessary. 本质上,这意味着在必要时将重复数据存储在多个实体中。 This saves $ on App Engine because you pay per request, but you don't pay on the size of the entity you return. 这样可以在App Engine上节省$,因为您可以按请求付费,但不必为返回的实体大小付费。 For example, if you have Stores that sell Widgets, you may want to store a summarized version of all a single store's widgets inside the Store entity (provided it's expected to fit inside the 1MB entity limit). 例如,如果您有出售小部件的商店,则您可能希望将所有单个商店小部件的摘要版本存储在Store实体中(前提是它应符合1MB实体限制)。 That way, when you display the store's page, you only fetch the one store entity, rather than the store entity plus every widget entity. 这样,当显示商店的页面时,您仅获取一个商店实体,而不是商店实体加上每个小部件实体。 Likewise, if you need to count the number of widgets, it's better to have that value inside the store entity than to issue queries to get the count. 同样,如果您需要计算小部件的数量,则最好在商店实体中拥有该值,而不是发出查询以获取该数量。

Caching: 缓存:

Caching saves you money on both the CPU and Datastore side. 缓存可以节省CPU和数据存储方面的成本。 There's a pretty good video from Google IO: https://developers.google.com/events/io/sessions/gooio2012/310/ 有一个来自Google IO的不错的视频: https : //developers.google.com/events/io/sessions/gooio2012/310/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM