написать простой инструмент для стресс-тестирования TCP-запросов и указать, как долго его останавливать. Но он будет задерживать каждое выполнение
использовать два селектора для прослушивания, но все равно
iподозревал, что, поскольку completeChannel принимал, я не буду выполнять testDuration.C, поэтому я написал демо, продолжал записывать данные в chennel, но таймер все еще работал
client:
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 и печатаете результат.и время такое же, как испытание временем