Skip to content

Should I wait for ports to clear between attacks? #718

@jtlapp

Description

@jtlapp

Question

I've noticed that when an attack completes, many ports remain in the "established" or "time wait" states for some time afterward.

Should I be waiting for these ports to become available again between attacks? I know that I don't have to, but I'm worried that the number of ports in use at the start of an attack will affect the benchmark for the attack.

If so, what is the appropriate way to accomplish this? I've written the following code, but my program eventually hits Postgres on the local machine, which subsequently keeps ports open. That makes this approach untenable unless I hard-code initialPortsInUse to the number of ports Postgres seems to subsequently keep open. I'd rather have Vegeta wait for all the ports it knowns it opened to free.

func WaitForPortsToClear(initialPortsInUse uint) {
	timeWaitPortsCount, establishedPortsCount := getPortsInUseCounts()
	for timeWaitPortsCount+establishedPortsCount > initialPortsInUse {
		time.Sleep(time.Second)
		timeWaitPortsCount, establishedPortsCount = getPortsInUseCounts()
	}
}

func getPortsInUseCounts() (timeWaitCount, establishedCount uint) {
	data, err := os.ReadFile("/proc/net/tcp")
	if err != nil {
		panic(err)
	}

	// Skip header line
	lines := strings.Split(string(data), "\n")[1:]

	// Column 4 contains the connection state in hex
	for _, line := range lines {
		fields := strings.Fields(line)
		if len(fields) >= 4 {
			state := fields[3]
			switch state {
			case "06":
				timeWaitCount++
			case "01":
				establishedCount++
			}
		}
	}
	return timeWaitCount, establishedCount
}

Here's my attack:

	attacker := vegeta.NewAttacker(
		vegeta.Workers(uint64(br.testConfig.WorkerCount)),
		vegeta.Connections(br.testConfig.MaxConnections),
		vegeta.Timeout(time.Duration(br.testConfig.RequestTimeoutSeconds)*time.Second),
		vegeta.KeepAlive(true),
	)
	rateLimiter := vegeta.Rate{Freq: rate, Per: time.Second}
	duration := time.Duration(durationSeconds) * time.Second

	var metrics vegeta.Metrics
	for res := range attacker.Attack(targetProvider, rateLimiter, duration, "") {
		br.logger.Log(res.Code, string(res.Body))
		metrics.Add(res)
	}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions