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:
parent
8954a07a49
commit
5f605167e1
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
"certKeySize": 2048,
|
||||
"regEmail": "loadtesting@letsencrypt.org",
|
||||
"maxRegs": 20,
|
||||
"maxNamesPerCert": 20,
|
||||
"dontSaveState": true,
|
||||
"results": "v2-example-latency.json"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,5 +17,6 @@
|
|||
"certKeySize": 2048,
|
||||
"regEmail": "loadtesting@letsencrypt.org",
|
||||
"maxRegs": 20,
|
||||
"maxNamesPerCert": 20,
|
||||
"dontSaveState": true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue