编写一个简单的TCP请求压力测试工具,并希望指定停止它的时间,但这会延迟每次执行
使用两个选择器进行收听,但仍然相同
我怀疑因为completeChannel已被接受,所以我不会执行testDuration.C,所以我编写了一个演示,一直在通道中写入数据,但是计时器仍然可以工作
客户端:
package main
import (
"encoding/json"
"flag"
"fmt"
"net"
"os"
"strings"
"syscall"
"time"
)
var (
count int
second int
conn int
ip string
completeChannel = make(chan struct{}, 0)
testDuration = new(time.Timer)
printOutTpl = `
Test results:
The process ID: %d
Request the address: %s
Total number of requests: %d
Test of time: %f
Total number of completed: %d
`
)
const (
network = "tcp"
)
func getPutMessage(key, value string) string {
m := struct {
Protocol int `json:"protocol"` // 协议版本,保留字段
Type int `json:"type"` // 消息类型,见constant
Put interface{} `json:"put"` // 消息体
}{
Protocol: 1,
Type: 20000, // PUT
Put: struct {
Key string `json:"key"`
Value string `json:"value"`
}{
Key: key,
Value: value,
},
}
bytes, _ := json.Marshal(m)
return string(bytes)
}
func writeToLoopex(id, address string) {
connection, err := net.Dial(network, address)
if err != nil {
fmt.Printf("connect to %s failed: %v\n", address, err)
return
}
value := `{"remote_ip":"127.0.0.1","referrer":"http://www.baidu.com","channel":1,"province":11,"click_at":1556275700473}`
for i := 0; i < count; i += 1 {
k := fmt.Sprintf("%s-%d", id, i)
s := getPutMessage(k, value)
connection.Write([]byte(s + "\n"))
completeChannel <- struct{}{}
}
connection.Close()
}
func concurrentlyWriteToLoopex(id, address string, concurrency int) {
for i := 0; i < concurrency; i++ {
nid := fmt.Sprintf("%s%d", id, i)
go func() {
writeToLoopex(nid, address)
}()
}
}
func main() {
var (
complete = 0
allCount = 0
start = time.Now()
ids = []string{"A", "B", "C", "D", "E", "F"}
)
flag.IntVar(&conn, "conn", 300, "连接数")
flag.IntVar(&second, "second", 0, "持续时间")
flag.IntVar(&count, "count", 100, "单个连接发送数量")
flag.StringVar(&ip, "ip", "127.0.0.1", "IP 地址支持逗号 , 分隔多个")
flag.Parse()
ips := strings.Split(ip, ",")
if len(ips) < 1 {
fmt.Println("请输入IP地址!")
os.Exit(1)
}
if second >= 1 {
testDuration = time.NewTimer(time.Duration(second) * time.Second)
}
defer func() {
testDuration.Stop()
end := time.Since(start)
fmt.Printf(printOutTpl, syscall.Getpid(), ip, allCount, end.Seconds(), complete)
}()
for i := 0; i < len(ips); i++ {
go concurrentlyWriteToLoopex(ids[i], ips[i], conn)
}
allCount = conn * count * len(ips)
for {
select {
case <-completeChannel:
complete++
if complete == allCount {
return
}
case <-testDuration.C:
return
}
}
}
服务器:
package main
import (
"fmt"
"log"
"net"
"sync/atomic"
"time"
)
var (
count int64 = 0
)
func main(){
n,err := net.Listen("tcp", ":8081")
if err != nil{
log.Fatal(err)
}
for {
conn,err := n.Accept()
if err != nil{
log.Fatal(err)
}
go func(conn net.Conn) {
bytes := make([]byte,4096)
conn.Read(bytes)
fmt.Println(string(bytes))
atomic.AddInt64(&count,1)
defer conn.Close()
}(conn)
fmt.Println(count)
}
}
cmd: 我希望这花费一秒钟以上的时间
./cli/cli -conn=200 -count 3000 -ip 127.0.0.1:8081,127.0.0.1:8081 -second 1
只要时间到了,就执行defer并打印结果。 时间与时间测试相同