mirror of
https://github.com/singchia/frontier.git
synced 2025-09-26 20:31:25 +08:00
154 lines
3.5 KiB
Go
154 lines
3.5 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"math/rand"
|
|
"net"
|
|
"net/http"
|
|
_ "net/http/pprof"
|
|
"os"
|
|
"strings"
|
|
"sync"
|
|
"sync/atomic"
|
|
"time"
|
|
|
|
armlog "github.com/jumboframes/armorigo/log"
|
|
"github.com/jumboframes/armorigo/sigaction"
|
|
"github.com/singchia/frontier/api/dataplane/v1/edge"
|
|
"github.com/singchia/go-timer/v2"
|
|
"github.com/spf13/pflag"
|
|
)
|
|
|
|
var (
|
|
edges = map[int]edge.Edge{}
|
|
mtx sync.RWMutex
|
|
)
|
|
|
|
func main() {
|
|
network := pflag.String("network", "tcp", "network to dial")
|
|
address := pflag.String("address", "127.0.0.1:30012", "address to dial")
|
|
loglevel := pflag.String("loglevel", "info", "log level, trace debug info warn error")
|
|
count := pflag.Int("count", 10000, "edges to dial")
|
|
topic := pflag.String("topic", "test", "topic to specific")
|
|
nseconds := pflag.Int("nseconds", 10, "publish message every n seconds for every edge")
|
|
msg := pflag.String("msg", "testtesttest", "the message content to publish")
|
|
sourceIPs := pflag.String("source_ips", "", "source ips to dial, if you want dial more than \"65535\" source ports")
|
|
pprof := pflag.String("pprof", "", "pprof addr to listen")
|
|
pflag.Parse()
|
|
|
|
if *pprof != "" {
|
|
go func() {
|
|
http.ListenAndServe(*pprof, nil)
|
|
}()
|
|
}
|
|
|
|
ips := []string{}
|
|
idx := int64(0)
|
|
|
|
if *sourceIPs != "" {
|
|
ips = strings.Split(*sourceIPs, ",")
|
|
idx = 0
|
|
|
|
}
|
|
|
|
dialer := func() (net.Conn, error) {
|
|
if len(ips) != 0 {
|
|
for retry := 0; retry < 3; retry++ {
|
|
thisidx := atomic.LoadInt64(&idx)
|
|
ip := ips[int(thisidx)%len(ips)]
|
|
localAddr := &net.TCPAddr{
|
|
IP: net.ParseIP(ip),
|
|
}
|
|
dialer := &net.Dialer{
|
|
LocalAddr: localAddr,
|
|
Timeout: 5 * time.Second,
|
|
}
|
|
conn, err := dialer.Dial(*network, *address)
|
|
if err == nil {
|
|
return conn, nil
|
|
}
|
|
if strings.Contains(err.Error(), "cannot assign requested address") ||
|
|
strings.Contains(err.Error(), "address already in use") {
|
|
atomic.AddInt64(&idx, 1)
|
|
continue
|
|
}
|
|
fmt.Printf("unknown dial err: %s, source ip: %s:%d \n", err, localAddr.IP.String(), localAddr.Port)
|
|
return nil, err
|
|
}
|
|
}
|
|
return net.Dial(*network, *address)
|
|
}
|
|
// log
|
|
level, err := armlog.ParseLevel(*loglevel)
|
|
if err != nil {
|
|
fmt.Println("parse log level err:", err)
|
|
return
|
|
}
|
|
armlog.SetLevel(level)
|
|
armlog.SetOutput(os.Stdout)
|
|
|
|
wg := sync.WaitGroup{}
|
|
wg.Add(*count)
|
|
|
|
tmr := timer.NewTimer()
|
|
for i := 0; i < *count; i++ {
|
|
go func(i int) {
|
|
defer wg.Done()
|
|
// avoid congestion of connection
|
|
n := *count / 100
|
|
if n == 0 {
|
|
n = 1
|
|
}
|
|
random := rand.Intn(n) + 1
|
|
time.Sleep(time.Second * time.Duration(random))
|
|
// new edge connection
|
|
cli, err := edge.NewEdge(dialer,
|
|
edge.OptionEdgeLog(armlog.DefaultLog),
|
|
edge.OptionEdgeTimer(tmr),
|
|
edge.OptionServiceBufferSize(128, 128))
|
|
if err != nil {
|
|
armlog.Info("new edge err:", err)
|
|
return
|
|
}
|
|
mtx.Lock()
|
|
edges[i] = cli
|
|
mtx.Unlock()
|
|
// publish message in loop
|
|
for {
|
|
gmsg := cli.NewMessage([]byte(*msg))
|
|
err := cli.Publish(context.TODO(), *topic, gmsg)
|
|
if err != nil {
|
|
fmt.Println("publish err", err)
|
|
break
|
|
}
|
|
time.Sleep(time.Duration(*nseconds) * time.Second)
|
|
}
|
|
mtx.Lock()
|
|
delete(edges, i)
|
|
mtx.Unlock()
|
|
cli.Close()
|
|
}(i)
|
|
}
|
|
|
|
go func() {
|
|
ticker := time.NewTicker(time.Second * 10)
|
|
for {
|
|
<-ticker.C
|
|
mtx.RLock()
|
|
online := len(edges)
|
|
mtx.RUnlock()
|
|
fmt.Printf("online: %d\n", online)
|
|
}
|
|
}()
|
|
|
|
sig := sigaction.NewSignal()
|
|
sig.Wait(context.TODO())
|
|
|
|
mtx.RLock()
|
|
for _, edge := range edges {
|
|
edge.Close()
|
|
}
|
|
mtx.RUnlock()
|
|
}
|