我在交易中更新了具有客体化的实体。我的猜测是我每秒只能写入1到5次相同的实体组。这符合围绕写入数据存储区的文档和建议。但是在对以下代码运行一些简单的负载测试之后,我看到了
为什么这可能?我的错误在哪里?
// text => a random text, different for each request
public void update(final Key<SomeEntity> toLoad, String text) {
final AtomicInteger attempts = new AtomicInteger(0);
SomeEntity modified = ofy().transact(new Work<SomeEntity>() {
public SomeEntity run() {
// count every attempt
attempts.incrementAndGet();
SomeEntity toModify = ofy().load().key(toLoad).now();
if (toModify != null) {
// modifies the entity
toModify.setText(text);
ofy().save().entity(toModify).now();
}
return toModify;
}
});
if (attempts.get() > 1) {
logger.warning(attempts.get() + " attempts for update on " + modified);
}
}
在云控制台日志查看器中报告了大量重试,大多数警告有2次尝试,一些事务有5次尝试,但是已执行并更新了实体。对GAE进行负载测试是否有特殊策略?或者关于这个主题的任何一般性建议?
更新
实体组结构和测试设置的简短描述。为了便于选择实体,密钥名称反映了实体在其实体组中的位置。 “001-001-100”是实体组中的第二级实体,其根实体为“100”并且具有父“001-100”。所以实体组看起来像这样:
- 100
- 001-100
- 001-001-100
- 002-001-100
- 003-001-100
- ...
- 002-100
- 003-100
- 004-100
- 005-100
- ...
- 101
- ...
我尝试了三种不同的版本。每个人都在JMeter中使用另一个值来更新请求。所有更新完全相同的实体“001-001-100”。
// Version A: text does not change during load test
vars.put("text", "Foo Bar");
// Version B: text changes every second during load test
var d = new Date();
vars.put("text", [d.getHours(), d.getMinutes(), d.getSeconds()].join("-")));
// Version B: text changes every request
vars.put("text", Math.random());
但是:每秒在一个实体上写入24次真的很高。所以我稍微重新设计了测试。
然后我稍微修改了测试。我现在只在一个实体的第二层上分发请求,而不是仅在一个实体上触发请求。因此JMeter随机使用“001-001-100”,“002-001-100”,“003-001-100”,“004-001-100”或“005-001-100”。或多或少的结果就像我只选择一个实体一样。
更新2: 如果仅使用一个线程执行负载测试,则吞吐量大约为每秒2.5次更新。这更接近拟议的限制。如果我使用80个线程运行测试,吞吐量会上升到我之前发布的数字。样本的响应时间不是最好的,但吞吐量保持很高:avg = 2100ms,中值= 1350ms,90%= 5400ms,max = 18000ms。也许吞吐量可能不是数据存储限制的直接衡量标准?
答案 0 :(得分:1)
您可以获得实体缓存的好处(版本A和B)。它可能位于Objectify级别,也可能位于Datastore的基础架构内。
每秒5个请求不是硬限制。这是一个警告:
App Engine会将写入单个实体组的序列化 数据存储,因此对更新数据存储的速度有限制 实体组。一般来说,这可以在1到5之间 每秒更新;一个好的指导方针是你应该考虑的 重新架构,如果您希望实体组必须维持更多 超过每秒一次更新。
请注意:
(a)简单的文本字符串几乎没有序列化开销。对于复杂的实体,情况并非如此。
(b)警告包括&#34;延长期&#34;。