Improve load test servlet

This adds better comments, sane defaults for most parameters, and
improved caching of test data.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=118996436
This commit is contained in:
mcilwain 2016-04-04 16:50:42 -07:00 committed by Justine Tunney
parent 45a194fd90
commit 17c4ad83c8
2 changed files with 160 additions and 95 deletions

View file

@ -61,22 +61,111 @@ public class LoadTestAction implements Runnable {
private static final Random random = new Random(); private static final Random random = new Random();
@Inject @Parameter("loadtestClientId") String clientId; /** The client identifier of the registrar to use for load testing. */
@Inject @Parameter("tld") String tld; @Inject
@Inject @Parameter("delaySeconds") int delaySeconds; @Parameter("loadtestClientId")
@Inject @Parameter("runSeconds") int runSeconds; String clientId;
@Inject @Parameter("successfulDomainCreates") int successfulDomainCreates;
@Inject @Parameter("failedDomainCreates") int failedDomainCreates; /**
@Inject @Parameter("domainInfos") int domainInfos; * The number of seconds to delay the execution of the first load testing tasks by. Preparatory
@Inject @Parameter("domainChecks") int domainChecks; * work of creating independent contacts and hosts that will be used for later domain creation
@Inject @Parameter("successfulContactCreates") int successfulContactCreates; * testing occurs during this period, so make sure that it is long enough.
@Inject @Parameter("failedContactCreates") int failedContactCreates; */
@Inject @Parameter("contactInfos") int contactInfos; @Inject
@Inject @Parameter("successfulHostCreates") int successfulHostCreates; @Parameter("delaySeconds")
@Inject @Parameter("failedHostCreates") int failedHostCreates; int delaySeconds;
@Inject @Parameter("hostInfos") int hostInfos;
@Inject TaskEnqueuer taskEnqueuer; /**
@Inject LoadTestAction() {} * The number of seconds that tasks will be enqueued for. Note that if system QPS cannot handle
* the given load then it will take longer than this number of seconds for the test to complete.
*/
@Inject
@Parameter("runSeconds")
int runSeconds;
/** The number of successful domain creates to enqueue per second over the length of the test. */
@Inject
@Parameter("successfulDomainCreates")
int successfulDomainCreatesPerSecond;
/** The number of failed domain creates to enqueue per second over the length of the test. */
@Inject
@Parameter("failedDomainCreates")
int failedDomainCreatesPerSecond;
/** The number of successful domain infos to enqueue per second over the length of the test. */
@Inject
@Parameter("domainInfos")
int domainInfosPerSecond;
/** The number of successful domain checks to enqueue per second over the length of the test. */
@Inject
@Parameter("domainChecks")
int domainChecksPerSecond;
/** The number of successful contact creates to enqueue per second over the length of the test. */
@Inject
@Parameter("successfulContactCreates")
int successfulContactCreatesPerSecond;
/** The number of failed contact creates to enqueue per second over the length of the test. */
@Inject
@Parameter("failedContactCreates")
int failedContactCreatesPerSecond;
/** The number of successful contact infos to enqueue per second over the length of the test. */
@Inject
@Parameter("contactInfos")
int contactInfosPerSecond;
/** The number of successful host creates to enqueue per second over the length of the test. */
@Inject
@Parameter("successfulHostCreates")
int successfulHostCreatesPerSecond;
/** The number of failed host creates to enqueue per second over the length of the test. */
@Inject
@Parameter("failedHostCreates")
int failedHostCreatesPerSecond;
/** The number of successful host infos to enqueue per second over the length of the test. */
@Inject
@Parameter("hostInfos")
int hostInfosPerSecond;
@Inject
TaskEnqueuer taskEnqueuer;
private final String xmlContactCreateTmpl;
private final String xmlContactCreateFail;
private final String xmlContactInfo;
private final String xmlDomainCheck;
private final String xmlDomainCreateTmpl;
private final String xmlDomainCreateFail;
private final String xmlDomainInfo;
private final String xmlHostCreateTmpl;
private final String xmlHostCreateFail;
private final String xmlHostInfo;
@Inject
LoadTestAction(@Parameter("tld") String tld) {
xmlContactCreateTmpl = loadXml("contact_create");
xmlContactCreateFail = xmlContactCreateTmpl.replace("%contact%", EXISTING_CONTACT);
xmlContactInfo = loadXml("contact_info").replace("%contact%", EXISTING_CONTACT);
xmlDomainCheck =
loadXml("domain_check").replace("%tld%", tld).replace("%domain%", EXISTING_DOMAIN);
xmlDomainCreateTmpl = loadXml("domain_create").replace("%tld%", tld);
xmlDomainCreateFail =
xmlDomainCreateTmpl
.replace("%domain%", EXISTING_DOMAIN)
.replace("%contact%", EXISTING_CONTACT)
.replace("%host%", EXISTING_HOST);
xmlDomainInfo =
loadXml("domain_info").replace("%tld%", tld).replace("%domain%", EXISTING_DOMAIN);
xmlHostCreateTmpl = loadXml("host_create");
xmlHostCreateFail = xmlHostCreateTmpl.replace("%host%", EXISTING_HOST);
xmlHostInfo = loadXml("host_info").replace("%host%", EXISTING_HOST);
}
@Override @Override
public void run() { public void run() {
@ -88,14 +177,14 @@ public class LoadTestAction implements Runnable {
ImmutableList.Builder<String> preTaskXmls = new ImmutableList.Builder<>(); ImmutableList.Builder<String> preTaskXmls = new ImmutableList.Builder<>();
ImmutableList.Builder<String> contactNamesBuilder = new ImmutableList.Builder<>(); ImmutableList.Builder<String> contactNamesBuilder = new ImmutableList.Builder<>();
ImmutableList.Builder<String> hostPrefixesBuilder = new ImmutableList.Builder<>(); ImmutableList.Builder<String> hostPrefixesBuilder = new ImmutableList.Builder<>();
for (int i = 0; i < successfulDomainCreates; i++) { for (int i = 0; i < successfulDomainCreatesPerSecond; i++) {
String contactName = getRandomLabel(MAX_CONTACT_LENGTH); String contactName = getRandomLabel(MAX_CONTACT_LENGTH);
String hostPrefix = getRandomLabel(ARBITRARY_VALID_HOST_LENGTH); String hostPrefix = getRandomLabel(ARBITRARY_VALID_HOST_LENGTH);
contactNamesBuilder.add(contactName); contactNamesBuilder.add(contactName);
hostPrefixesBuilder.add(hostPrefix); hostPrefixesBuilder.add(hostPrefix);
preTaskXmls.add( preTaskXmls.add(
loadXml("contact_create").replace("%contact%", contactName), xmlContactCreateTmpl.replace("%contact%", contactName),
loadXml("host_create").replace("%host%", hostPrefix)); xmlHostCreateTmpl.replace("%host%", hostPrefix));
} }
enqueue(createTasks(preTaskXmls.build(), DateTime.now(UTC))); enqueue(createTasks(preTaskXmls.build(), DateTime.now(UTC)));
ImmutableList<String> contactNames = contactNamesBuilder.build(); ImmutableList<String> contactNames = contactNamesBuilder.build();
@ -106,72 +195,44 @@ public class LoadTestAction implements Runnable {
DateTime startSecond = initialStartSecond.plusSeconds(offsetSeconds); DateTime startSecond = initialStartSecond.plusSeconds(offsetSeconds);
// The first "failed" creates might actually succeed if the object doesn't already exist, but // The first "failed" creates might actually succeed if the object doesn't already exist, but
// that shouldn't affect the load numbers. // that shouldn't affect the load numbers.
tasks.addAll(createTasks( tasks.addAll(
createNumCopies( createTasks(
loadXml("contact_create").replace("%contact%", EXISTING_CONTACT), createNumCopies(xmlContactCreateFail, failedContactCreatesPerSecond), startSecond));
failedContactCreates), tasks.addAll(
startSecond)); createTasks(createNumCopies(xmlHostCreateFail, failedHostCreatesPerSecond), startSecond));
tasks.addAll(createTasks( tasks.addAll(
createNumCopies( createTasks(
loadXml("host_create").replace("%host%", EXISTING_HOST), createNumCopies(xmlDomainCreateFail, failedDomainCreatesPerSecond), startSecond));
failedHostCreates),
startSecond));
tasks.addAll(createTasks(
createNumCopies(
loadXml("domain_create")
.replace("%tld%", tld)
.replace("%domain%", EXISTING_DOMAIN)
.replace("%contact%", EXISTING_CONTACT)
.replace("%host%", EXISTING_HOST),
failedDomainCreates),
startSecond));
// We can do infos on the known existing objects. // We can do infos on the known existing objects.
tasks.addAll(createTasks( tasks.addAll(
createNumCopies( createTasks(createNumCopies(xmlContactInfo, contactInfosPerSecond), startSecond));
loadXml("contact_info").replace("%contact%", EXISTING_CONTACT), tasks.addAll(createTasks(createNumCopies(xmlHostInfo, hostInfosPerSecond), startSecond));
contactInfos), tasks.addAll(createTasks(createNumCopies(xmlDomainInfo, domainInfosPerSecond), startSecond));
startSecond));
tasks.addAll(createTasks(
createNumCopies(
loadXml("host_info").replace("%host%", EXISTING_HOST),
hostInfos),
startSecond));
tasks.addAll(createTasks(
createNumCopies(
loadXml("domain_info")
.replace("%tld%", tld)
.replace("%domain%", EXISTING_DOMAIN),
domainInfos),
startSecond));
// The domain check template uses "example.TLD" which won't exist, and one existing domain. // The domain check template uses "example.TLD" which won't exist, and one existing domain.
tasks.addAll(createTasks( tasks.addAll(
createNumCopies( createTasks(createNumCopies(xmlDomainCheck, domainChecksPerSecond), startSecond));
loadXml("domain_check")
.replace("%tld%", tld)
.replace("%domain%", EXISTING_DOMAIN),
domainChecks),
startSecond));
// Do successful creates on random names // Do successful creates on random names
tasks.addAll(createTasks( tasks.addAll(
transform( createTasks(
createNumCopies(loadXml("contact_create"), successfulContactCreates), transform(
randomNameReplacer("%contact%", MAX_CONTACT_LENGTH)), createNumCopies(xmlContactCreateTmpl, successfulContactCreatesPerSecond),
startSecond)); randomNameReplacer("%contact%", MAX_CONTACT_LENGTH)),
tasks.addAll(createTasks( startSecond));
transform( tasks.addAll(
createNumCopies(loadXml("host_create"), successfulHostCreates), createTasks(
randomNameReplacer("%host%", ARBITRARY_VALID_HOST_LENGTH)), transform(
startSecond)); createNumCopies(xmlHostCreateTmpl, successfulHostCreatesPerSecond),
tasks.addAll(createTasks( randomNameReplacer("%host%", ARBITRARY_VALID_HOST_LENGTH)),
FluentIterable startSecond));
.from(createNumCopies( tasks.addAll(
loadXml("domain_create").replace("%tld%", tld), createTasks(
successfulDomainCreates)) FluentIterable.from(
.transform(randomNameReplacer("%domain%", MAX_DOMAIN_LABEL_LENGTH)) createNumCopies(xmlDomainCreateTmpl, successfulDomainCreatesPerSecond))
.transform(listNameReplacer("%contact%", contactNames)) .transform(randomNameReplacer("%domain%", MAX_DOMAIN_LABEL_LENGTH))
.transform(listNameReplacer("%host%", hostPrefixes)) .transform(listNameReplacer("%contact%", contactNames))
.toList(), .transform(listNameReplacer("%host%", hostPrefixes))
startSecond)); .toList(),
startSecond));
} }
enqueue(tasks.build()); enqueue(tasks.build());
} }

View file

@ -14,7 +14,7 @@
package com.google.domain.registry.loadtest; package com.google.domain.registry.loadtest;
import static com.google.domain.registry.request.RequestParameters.extractIntParameter; import static com.google.domain.registry.request.RequestParameters.extractOptionalIntParameter;
import static com.google.domain.registry.request.RequestParameters.extractRequiredParameter; import static com.google.domain.registry.request.RequestParameters.extractRequiredParameter;
import com.google.domain.registry.request.Parameter; import com.google.domain.registry.request.Parameter;
@ -22,6 +22,8 @@ import com.google.domain.registry.request.Parameter;
import dagger.Module; import dagger.Module;
import dagger.Provides; import dagger.Provides;
import org.joda.time.Minutes;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
/** /**
@ -43,72 +45,74 @@ public final class LoadTestModule {
@Provides @Provides
@Parameter("delaySeconds") @Parameter("delaySeconds")
static int provideDelaySeconds(HttpServletRequest req) { static int provideDelaySeconds(HttpServletRequest req) {
return extractIntParameter(req, "delaySeconds"); return extractOptionalIntParameter(req, "delaySeconds")
.or(Minutes.ONE.toStandardSeconds().getSeconds());
} }
@Provides @Provides
@Parameter("runSeconds") @Parameter("runSeconds")
static int provideRunSeconds(HttpServletRequest req) { static int provideRunSeconds(HttpServletRequest req) {
return extractIntParameter(req, "runSeconds"); return extractOptionalIntParameter(req, "runSeconds")
.or(Minutes.ONE.toStandardSeconds().getSeconds());
} }
@Provides @Provides
@Parameter("successfulDomainCreates") @Parameter("successfulDomainCreates")
static int provideSuccessfulDomainCreates(HttpServletRequest req) { static int provideSuccessfulDomainCreates(HttpServletRequest req) {
return extractIntParameter(req, "successfulDomainCreates"); return extractOptionalIntParameter(req, "successfulDomainCreates").or(0);
} }
@Provides @Provides
@Parameter("failedDomainCreates") @Parameter("failedDomainCreates")
static int provideFailedDomainCreates(HttpServletRequest req) { static int provideFailedDomainCreates(HttpServletRequest req) {
return extractIntParameter(req, "failedDomainCreates"); return extractOptionalIntParameter(req, "failedDomainCreates").or(0);
} }
@Provides @Provides
@Parameter("domainInfos") @Parameter("domainInfos")
static int provideDomainInfos(HttpServletRequest req) { static int provideDomainInfos(HttpServletRequest req) {
return extractIntParameter(req, "domainInfos"); return extractOptionalIntParameter(req, "domainInfos").or(0);
} }
@Provides @Provides
@Parameter("domainChecks") @Parameter("domainChecks")
static int provideDomainChecks(HttpServletRequest req) { static int provideDomainChecks(HttpServletRequest req) {
return extractIntParameter(req, "domainChecks"); return extractOptionalIntParameter(req, "domainChecks").or(0);
} }
@Provides @Provides
@Parameter("successfulContactCreates") @Parameter("successfulContactCreates")
static int provideSuccessfulContactCreates(HttpServletRequest req) { static int provideSuccessfulContactCreates(HttpServletRequest req) {
return extractIntParameter(req, "successfulContactCreates"); return extractOptionalIntParameter(req, "successfulContactCreates").or(0);
} }
@Provides @Provides
@Parameter("failedContactCreates") @Parameter("failedContactCreates")
static int provideFailedContactCreates(HttpServletRequest req) { static int provideFailedContactCreates(HttpServletRequest req) {
return extractIntParameter(req, "failedContactCreates"); return extractOptionalIntParameter(req, "failedContactCreates").or(0);
} }
@Provides @Provides
@Parameter("contactInfos") @Parameter("contactInfos")
static int provideContactInfos(HttpServletRequest req) { static int provideContactInfos(HttpServletRequest req) {
return extractIntParameter(req, "contactInfos"); return extractOptionalIntParameter(req, "contactInfos").or(0);
} }
@Provides @Provides
@Parameter("successfulHostCreates") @Parameter("successfulHostCreates")
static int provideSuccessfulHostCreates(HttpServletRequest req) { static int provideSuccessfulHostCreates(HttpServletRequest req) {
return extractIntParameter(req, "successfulHostCreates"); return extractOptionalIntParameter(req, "successfulHostCreates").or(0);
} }
@Provides @Provides
@Parameter("failedHostCreates") @Parameter("failedHostCreates")
static int provideFailedHostCreates(HttpServletRequest req) { static int provideFailedHostCreates(HttpServletRequest req) {
return extractIntParameter(req, "failedHostCreates"); return extractOptionalIntParameter(req, "failedHostCreates").or(0);
} }
@Provides @Provides
@Parameter("hostInfos") @Parameter("hostInfos")
static int provideHostInfos(HttpServletRequest req) { static int provideHostInfos(HttpServletRequest req) {
return extractIntParameter(req, "hostInfos"); return extractOptionalIntParameter(req, "hostInfos").or(0);
} }
} }