Size V2 newOrder requests randomly. (#3523)

Prior to this commit all of the `newOrder` requests generated by the
load generator had 1 DNS type identifier. In this commit the
`maxNamesPerCert` parameter that was present in the codebase is fixed
(it was never wired through to config before) and used to size the
orders randomly. Each order will have between 1 and `maxNamesPerCert`
identifiers.

For integration testing we set this at 20. 100 would be more realistic
but we'll start small for now.
This commit is contained in:
Daniel McCarney 2018-03-05 17:10:05 -05:00 committed by Jacob Hoffman-Andrews
parent 8954a07a49
commit 5f605167e1
5 changed files with 53 additions and 35 deletions

View File

@ -313,19 +313,24 @@ func randDomain(base string) string {
// newOrder creates a new pending order object for a random set of domains using
// the context's account.
func newOrder(s *State, ctx *context) error {
// generate a random(-ish) domain name, will cause some multiples but not enough to make rate limits annoying!
randomDomain := randDomain(s.domainBase)
// Pick a random number of names within the constraints of the maxNamesPerCert
// parameter
orderSize := 1 + mrand.Intn(s.maxNamesPerCert-1)
// Generate that many random domain names. There may be some duplicates, we
// don't care. The ACME server will collapse those down for us, how handy!
dnsNames := []core.AcmeIdentifier{}
for i := 0; i <= orderSize; i++ {
dnsNames = append(dnsNames, core.AcmeIdentifier{
Type: core.IdentifierDNS,
Value: randDomain(s.domainBase),
})
}
// create the new order request object
initOrder := struct {
Identifiers []core.AcmeIdentifier
}{
Identifiers: []core.AcmeIdentifier{
{
Type: core.IdentifierDNS,
Value: randomDomain,
},
},
Identifiers: dnsNames,
}
initOrderStr, err := json.Marshal(&initOrder)
if err != nil {

View File

@ -17,6 +17,7 @@
"certKeySize": 2048,
"regEmail": "loadtesting@letsencrypt.org",
"maxRegs": 20,
"maxNamesPerCert": 20,
"dontSaveState": true,
"results": "v2-example-latency.json"
}

View File

@ -17,5 +17,6 @@
"certKeySize": 2048,
"regEmail": "loadtesting@letsencrypt.org",
"maxRegs": 20,
"maxNamesPerCert": 20,
"dontSaveState": true
}

View File

@ -21,21 +21,22 @@ type Config struct {
RateDelta string // requests / s^2
Runtime string // how long to run for
}
ExternalState string // path to file to load/save registrations etc to/from
DontSaveState bool // don't save changes to external state
APIBase string // ACME API address to send requests to
DomainBase string // base domain name to create authorizations for
HTTPOneAddr string // address to listen for http-01 validation requests on
TLSOneAddr string // address to listen for tls-sni-01 validation requests on
RealIP string // value of the Real-IP header to use when bypassing CDN
CertKeySize int // size of the key to use when creating CSRs
RegEmail string // email to use in registrations
Results string // path to save metrics to
MaxRegs int // maximum number of registrations to create
ExternalState string // path to file to load/save registrations etc to/from
DontSaveState bool // don't save changes to external state
APIBase string // ACME API address to send requests to
DomainBase string // base domain name to create authorizations for
HTTPOneAddr string // address to listen for http-01 validation requests on
TLSOneAddr string // address to listen for tls-sni-01 validation requests on
RealIP string // value of the Real-IP header to use when bypassing CDN
CertKeySize int // size of the key to use when creating CSRs
RegEmail string // email to use in registrations
Results string // path to save metrics to
MaxRegs int // maximum number of registrations to create
MaxNamesPerCert int // maximum number of names on one certificate/order
}
func main() {
configPath := flag.String("config", "", "Path to configuration file for WFE load-generator")
configPath := flag.String("config", "", "Path to configuration file for load-generator")
resultsPath := flag.String("results", "", "Path to latency results file")
rateArg := flag.Int("rate", 0, "")
runtimeArg := flag.String("runtime", "", "")
@ -44,13 +45,13 @@ func main() {
configBytes, err := ioutil.ReadFile(*configPath)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to read wfe config file %q: %s\n", *configPath, err)
fmt.Fprintf(os.Stderr, "Failed to read load-generator config file %q: %s\n", *configPath, err)
os.Exit(1)
}
var config Config
err = json.Unmarshal(configBytes, &config)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to parse wfe config file: %s\n", err)
fmt.Fprintf(os.Stderr, "Failed to parse load-generator config file: %s\n", err)
os.Exit(1)
}
@ -73,11 +74,12 @@ func main() {
config.DomainBase,
config.RealIP,
config.MaxRegs,
config.MaxNamesPerCert,
config.Results,
config.RegEmail,
config.Plan.Actions,
)
cmd.FailOnError(err, "Failed to create WFE generator")
cmd.FailOnError(err, "Failed to create load generator")
if config.ExternalState != "" {
err = s.Restore(config.ExternalState)
@ -106,7 +108,7 @@ func main() {
Rate: config.Plan.Rate,
Delta: delta,
})
cmd.FailOnError(err, "Failed to run WFE load generator")
cmd.FailOnError(err, "Failed to run load generator")
if config.ExternalState != "" && !config.DontSaveState {
err = s.Snapshot(config.ExternalState)

View File

@ -340,7 +340,15 @@ func (s *State) Restore(filename string) error {
}
// New returns a pointer to a new State struct or an error
func New(apiBase string, keySize int, domainBase string, realIP string, maxRegs int, latencyPath string, userEmail string, operations []string) (*State, error) {
func New(
apiBase string,
keySize int,
domainBase string,
realIP string,
maxRegs, maxNamesPerCert int,
latencyPath string,
userEmail string,
operations []string) (*State, error) {
certKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return nil, err
@ -365,16 +373,17 @@ func New(apiBase string, keySize int, domainBase string, realIP string, maxRegs
return nil, err
}
s := &State{
client: client,
apiBase: apiBase,
certKey: certKey,
domainBase: domainBase,
callLatency: latencyFile,
wg: new(sync.WaitGroup),
realIP: realIP,
maxRegs: maxRegs,
email: userEmail,
respCodes: make(map[int]*respCode),
client: client,
apiBase: apiBase,
certKey: certKey,
domainBase: domainBase,
callLatency: latencyFile,
wg: new(sync.WaitGroup),
realIP: realIP,
maxRegs: maxRegs,
maxNamesPerCert: maxNamesPerCert,
email: userEmail,
respCodes: make(map[int]*respCode),
}
// convert operations strings to methods