【发布时间】:2015-01-16 00:09:08
【问题描述】:
我在事务中使用 objectify 更新实体。我的猜测是,我每秒只能向同一个实体组写入 1 到 5 次。这将符合有关写入数据存储的文档和建议。但是在对以下代码进行了一些简单的负载测试后,我看到了
- 单个实体每秒大约 90 次写入
- 每秒对同一实体组中的随机实体进行大约 50 次写入。
为什么会这样?我的错在哪里?
// 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);
}
}
在 Cloud Console 日志查看器中报告了很多重试,大多数警告有 ~ 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());
- 版本 A:~ 110 个请求/秒
- 版本 B:约 70 个请求/秒
- 版本 C:~ 24 个请求/秒
但仍然:每秒对一个实体进行 24 次写入确实很高。所以我稍微重新设计了测试。
然后我稍微修改了测试。我现在不再只对一个实体发出请求,而是将它们分发到实体组的第二层。所以 JMeter 随机使用“001-001-100”、“002-001-100”、“003-001-100”、“004-001-100”或“005-001-100”。与我只选择一个实体的结果大致相同。
- 版本 A:~ 110 个请求/秒
- 版本 B:~ 100 个请求/秒
- 版本 C:~ 20 个请求/秒
更新 2: 如果您只使用一个线程执行负载测试,则吞吐量约为每秒 2.5 次更新。这更接近建议的限制。如果我用 80 个线程运行测试,吞吐量会上升到我之前发布的数字。样本的响应时间不是最好的,但吞吐量一直很高:avg = 2100ms,median = 1350ms,90% = 5400ms,max = 18000ms。也许吞吐量可能不是数据存储限制的直观衡量标准?
【问题讨论】:
-
您是否真的在修改实体,即每次都设置不同的文本?
-
是的,文本是由 JMeter 随机生成的,如果我在负载测试期间加载实体,更改是可见的。
-
如果没有更完整的测试,这很难回答。我的建议是将它封装在一个最小的 github 项目中,并邀请人们来看看。
-
这里是这个例子的代码:gist.github.com/botic/7885fe0266ad0f97c99f
标签: google-app-engine google-cloud-datastore objectify