更新工具

This commit is contained in:
wh_zcy 2022-12-08 10:54:28 +08:00
parent ebafb109b4
commit 1516520a4b
14 changed files with 434 additions and 61 deletions

BIN
cmd/v2/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -126,6 +126,9 @@ func (a *assistant) asyncCall() {
}()
req := a.caller.BuildReq()
if req.ID == 0 {
return
}
//调用状态 0未调用 1调用结束 2调用超时
var callStatus uint32
@ -180,7 +183,7 @@ func (a *assistant) prepareStop(ctxErr error) {
}
// 发送请求即调用接口
func (a *assistant) handleReq(tick <-chan time.Time) {
func (a *assistant) handleReq(throttle <-chan time.Time) {
for {
select {
case <-a.ctx.Done():
@ -191,7 +194,7 @@ func (a *assistant) handleReq(tick <-chan time.Time) {
a.asyncCall()
if a.lps > 0 {
select {
case <-tick:
case <-throttle:
case <-a.ctx.Done():
a.prepareStop(a.ctx.Err())
return
@ -226,12 +229,12 @@ func (a *assistant) Start() bool {
logrus.Debug("AI助手启动")
// 节流 周期性向目标发送
var ticker <-chan time.Time
var throttle <-chan time.Time
if a.lps > 0 {
//间隔时间
interval := time.Duration(1e9 / a.lps)
logrus.Debugf("启动节流控制 间隔: %v", interval)
ticker = time.Tick(interval)
throttle = time.Tick(interval)
}
// 初始化上下文和设置取消函数
@ -245,7 +248,7 @@ func (a *assistant) Start() bool {
go func() {
logrus.Debug("请求处理中...")
a.handleReq(ticker)
a.handleReq(throttle)
logrus.Infof("停止 调用次数:%d", a.callCount)
}()

View File

@ -101,6 +101,7 @@ const (
TOOLBAR_PERF_CONF = "配置"
TOOLBAR_PERF_LOGIN = "登陆"
TOOLBAR_PERF_CREATE = "创角"
TOOLBAR_PERF_CHOOSE = "选项"
TOOLBAR_PERF_PB = "协议"
TOOLBAR_PERF_RES = "结果"

View File

@ -1,16 +1,21 @@
package lib
import "time"
import (
"sync"
"time"
)
// 处理器接口
type Handler interface {
SetReq(req []byte)
SetReq(req []byte, flag bool)
// 处理请求
BuildReq() RawReq
//调用
Call(req []byte) ([]byte, error)
// 检查响应
Check(req RawReq, rsp RawResp) *CallResult
GetConnMap() sync.Map
}
// 调用结果

56
cmd/v2/lib/quen.go Normal file
View File

@ -0,0 +1,56 @@
package lib
import (
"fmt"
"sync"
)
type Queue[T any] struct {
data []T
lock sync.RWMutex
}
func NewQueue[T any]() *Queue[T] {
return &Queue[T]{data: make([]T, 0)}
}
func (this *Queue[T]) Add(obj T) {
this.lock.Lock()
defer this.lock.Unlock()
this.data = append(this.data, obj)
}
func (this *Queue[T]) List() []T {
this.lock.RLock()
defer this.lock.RUnlock()
list := make([]T, 0, len(this.data))
for _, v := range this.data {
list = append(list, v)
}
return list
}
func (this *Queue[T]) Get(index int) (T, bool) {
this.lock.RLock()
defer this.lock.RUnlock()
var ret T
if index < 0 || index >= len(this.data) {
return ret, false
}
return this.data[index], true
}
func (this *Queue[T]) Pop() (T, error) {
this.lock.Lock()
defer this.lock.Unlock()
var ret T
if len(this.data) == 0 {
return ret, fmt.Errorf("not found")
}
pop := this.data[0]
this.data = this.data[1:]
return pop, nil
}

View File

@ -164,7 +164,7 @@ func setupLogger() (err error) {
// FullTimestamp: true,
})
logrus.SetLevel(logrus.InfoLevel)
logrus.SetLevel(logrus.DebugLevel)
logrus.SetOutput(os.Stdout)
//设置output,默认为stderr,可以为任何io.Writer比如文件*os.File

View File

@ -21,6 +21,6 @@ services:
name: 李伟
url: ws://10.0.0.85:7891/gateway
- service:
sid: "0"
name: 广告位
url:
sid: "df01"
name: 压测服
url: ws://106.54.189.74:7891/gateway

View File

@ -42,7 +42,7 @@ func TestStart(t *testing.T) {
if err != nil {
t.Fatal(err)
}
h.SetReq(b)
h.SetReq(b, false)
param := lib.ParamMgr{
Caller: h,
Timeout: 50 * time.Millisecond,

View File

@ -1,33 +1,48 @@
package service
import (
"encoding/base64"
"go_dreamfactory/cmd/v2/lib"
"go_dreamfactory/cmd/v2/lib/common"
"go_dreamfactory/comm"
"go_dreamfactory/lego/sys/log"
"go_dreamfactory/pb"
"strings"
"sync"
"time"
"github.com/gorilla/websocket"
"github.com/sirupsen/logrus"
"github.com/tidwall/gjson"
"google.golang.org/protobuf/proto"
)
type WsCli struct {
addr string
conn *websocket.Conn
reqData []byte //请求数据
// reqData []byte //请求数据
uid string
reqDatas *lib.Queue[[]byte]
conns sync.Map
flag bool
reqData []byte
}
func NewWsCli(addr string, timeout time.Duration) (lib.Handler, error) {
cli := &WsCli{addr: addr}
if err := cli.connect(timeout); err != nil {
return nil, err
cli := &WsCli{
addr: addr,
reqDatas: lib.NewQueue[[]byte](),
}
// if err := cli.connect(timeout); err != nil {
// return nil, err
// }
return cli, nil
}
func (cli *WsCli) GetConnMap() sync.Map {
return cli.conns
}
func (cli *WsCli) connect(timeout time.Duration) error {
if cli.conn == nil {
dialer := &websocket.Dialer{
@ -55,7 +70,7 @@ func (cli *WsCli) connect(timeout time.Duration) error {
return nil
}
// 检查登录相应
// 检查相应
func (cli *WsCli) checkResp(data []byte) bool {
msg := &pb.UserMessage{}
if err := proto.Unmarshal(data, msg); err != nil {
@ -97,7 +112,12 @@ func (cli *WsCli) checkPush(data []byte) bool {
if strings.HasSuffix(methodName, "Push") {
if methodName == "NotifyErrorNotifyPush" {
logrus.WithField("methodName", methodName).Debug("收到错误码")
push := &pb.NotifyErrorNotifyPush{}
if !comm.ProtoUnmarshal(msg, push) {
logrus.Error("unmarsh err")
return false
}
logrus.WithField("methodName", methodName).WithField("code", push.Code).Debug("收到错误码")
} else {
logrus.WithField("methodName", methodName).Debug("收到推送")
}
@ -106,35 +126,88 @@ func (cli *WsCli) checkPush(data []byte) bool {
return false
}
func (cli *WsCli) SetReq(data []byte) {
func (cli *WsCli) SetReq(data []byte, flag bool) {
cli.flag = flag
if flag {
cli.reqData = data
}
cli.reqDatas.Add(data)
}
func (cli *WsCli) BuildReq() lib.RawReq {
id := time.Now().UnixNano()
rawReq := lib.RawReq{ID: id, Req: cli.reqData}
var (
data []byte
err error
)
data, err = cli.reqDatas.Pop()
if err != nil {
if cli.flag {
data = cli.reqData
} else {
return lib.RawReq{}
}
}
rawReq := lib.RawReq{ID: id, Req: data}
return rawReq
}
func (cli *WsCli) Call(req []byte) ([]byte, error) {
msg := &pb.UserMessage{}
if err := proto.Unmarshal(req, msg); err != nil {
logrus.Error("结果解析失败")
return nil, err
}
base64Str := msg.Sec
dec, err := base64.StdEncoding.DecodeString(base64Str[35:])
if err != nil {
log.Errorf("base64 decode err %v", err)
return nil, err
}
jsonRet := gjson.Parse(string(dec))
account := jsonRet.Get("account").String()
dialer := &websocket.Dialer{
HandshakeTimeout: 2 * time.Second,
}
var conn *websocket.Conn
if c, ok := cli.conns.Load(account); ok {
conn = c.(*websocket.Conn)
} else {
conn, _, err = dialer.Dial(cli.addr, nil)
if err != nil {
logrus.Errorf("websocket conn err:%v", err)
return nil, err
}
}
if msg.MainType == "user" && msg.SubType == "login" {
cli.conns.Store(account, conn)
}
// 向连接写数据
cli.conn.WriteMessage(websocket.BinaryMessage, req)
conn.WriteMessage(websocket.BinaryMessage, req)
// 读数据
var res []byte
for {
_, data, err := cli.conn.ReadMessage()
_, data, err := conn.ReadMessage()
if err != nil {
logrus.Errorf("readMessage err:%v", err)
break
}
if cli.checkResp(data) {
// if cli.checkResp(data) {
// return data, nil
// } else {
if !cli.checkPush(data) {
return data, nil
} else {
cli.checkPush(data)
}
// }
}
return res, nil

View File

@ -39,6 +39,7 @@ var (
&perfConf{},
&perfPb{},
&perfResult{},
&perfChoose{},
}
)

226
cmd/v2/ui/perf_choose.go Normal file
View File

@ -0,0 +1,226 @@
package ui
import (
cfg "go_dreamfactory/cmd/v2/configure/structs"
"go_dreamfactory/cmd/v2/lib"
"go_dreamfactory/cmd/v2/lib/common"
"go_dreamfactory/cmd/v2/lib/storage"
"go_dreamfactory/cmd/v2/service"
"go_dreamfactory/cmd/v2/service/observer"
"go_dreamfactory/comm"
"go_dreamfactory/pb"
"strings"
"time"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/layout"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
"github.com/Pallinder/go-randomdata"
"github.com/sirupsen/logrus"
"google.golang.org/protobuf/proto"
)
type perfChoose struct {
appAdapter
obs observer.Observer
conf *storage.Config
binduids []string //账号
handler lib.Handler
}
func (app *perfChoose) LazyInit(ptService service.PttService, obs observer.Observer) error {
app.obs = obs
app.conf = perfWin.UIImpl.config
app.tabItem = container.NewTabItemWithIcon(common.TOOLBAR_PERF_CHOOSE, theme.ContentCopyIcon(), nil)
content := container.NewMax()
content.Objects = []fyne.CanvasObject{}
loginTestBtn := widget.NewButton("登陆(注册)", nil)
loginTestBtn.OnTapped = func() {
closeApp3(perfWin.tabs, common.TOOLBAR_PERF_CHOOSE)
openApp3(perfWin.tabs, common.TOOLBAR_PERF_RES)
var err error
app.handler, err = service.NewWsCli(app.conf.WsAddr, 2*time.Second)
if err != nil {
panic(err)
}
userCount := app.conf.UserCount
for i := int32(0); i < userCount; i++ {
account := randomdata.SillyName()
app.binduids = append(app.binduids, account)
// 登录
rqLogin := ReqParams{
Sid: app.conf.SId,
Account: account,
PbReq: &pb.UserLoginReq{Sid: app.conf.SId, Account: account},
MainType: "user",
SubType: "login",
}
b, err := app.buildReq(rqLogin)
if err != nil {
logrus.Error(err)
return
}
app.handler.SetReq(b, false)
}
param := lib.ParamMgr{
Caller: app.handler,
Timeout: time.Duration(app.conf.Pressure.TimeoutMs) * time.Millisecond,
Lps: uint32(app.conf.Pressure.Concurrency),
Duration: time.Duration(app.conf.Pressure.DurationS) * time.Second,
ResultCh: make(chan *lib.CallResult, 50),
}
a, err := lib.NewAssistant(obs, param)
if err != nil {
logrus.Error(err)
}
a.Start()
a.ShowResult()
}
createTestBtn := widget.NewButton("创角", func() {
closeApp3(perfWin.tabs, common.TOOLBAR_PERF_CHOOSE)
openApp3(perfWin.tabs, common.TOOLBAR_PERF_RES)
for _, account := range app.binduids {
rq := ReqParams{
Sid: app.conf.SId,
Account: account,
PbReq: &pb.UserCreateReq{NickName: account},
MainType: "user",
SubType: "create",
}
b, err := app.buildReq(rq)
if err != nil {
logrus.Error(err)
return
}
app.handler.SetReq(b, false)
}
param := lib.ParamMgr{
Caller: app.handler,
Timeout: time.Duration(app.conf.Pressure.TimeoutMs) * time.Millisecond,
Lps: uint32(app.conf.Pressure.Concurrency),
Duration: time.Duration(app.conf.Pressure.DurationS) * time.Second,
ResultCh: make(chan *lib.CallResult, 50),
}
a, err := lib.NewAssistant(obs, param)
if err != nil {
logrus.Error(err)
}
a.Start()
a.ShowResult()
})
//场景
scenBtn := widget.NewButton("其它场景", nil)
scenBtn.OnTapped = func() {
// defer openApp3(perfWin.tabs, common.TOOLBAR_PERF_PB)
// closeApp3(perfWin.tabs, common.TOOLBAR_PERF_CHOOSE)
closeApp3(perfWin.tabs, common.TOOLBAR_PERF_CHOOSE)
openApp3(perfWin.tabs, common.TOOLBAR_PERF_RES)
if tables, err := cfg.NewTables(common.Loader); err != nil {
println(err.Error())
} else {
for _, v := range tables.TestFlow.GetDataList() {
p, ok := pbMap[v.Route]
if !ok {
logrus.WithField("route", v.Route).Debug("未注册")
continue
}
routeStr := strings.SplitN(v.Route, ".", 2)
for _, account := range app.binduids {
rq := ReqParams{
Sid: app.conf.SId,
Account: account,
PbReq: p,
MainType: routeStr[0],
SubType: routeStr[1],
}
b, err := app.buildReq(rq)
if err != nil {
logrus.Error(err)
return
}
app.handler.SetReq(b, true)
}
param := lib.ParamMgr{
Caller: app.handler,
Timeout: time.Duration(app.conf.Pressure.TimeoutMs) * time.Millisecond,
Lps: uint32(app.conf.Pressure.Concurrency),
Duration: time.Duration(app.conf.Pressure.DurationS) * time.Second,
ResultCh: make(chan *lib.CallResult, 50),
}
a, err := lib.NewAssistant(obs, param)
if err != nil {
logrus.Error(err)
}
a.Start()
a.ShowResult()
}
}
}
//上一步
preBtn := widget.NewButtonWithIcon("上一步", theme.NavigateBackIcon(), nil)
preBtn.OnTapped = func() {
defer openApp3(perfWin.tabs, common.TOOLBAR_PERF_CONF)
closeApp3(perfWin.tabs, common.TOOLBAR_PERF_CHOOSE)
}
btns := container.NewVBox(loginTestBtn, createTestBtn, scenBtn)
c := container.NewBorder(nil, container.NewHBox(layout.NewSpacer(), preBtn), nil, nil, btns)
content.Objects = append(content.Objects, c)
app.tabItem.Content = content
return nil
}
func (a *perfChoose) GetAppName() string {
return common.TOOLBAR_PERF_CHOOSE
}
func (a *perfChoose) OnClose() bool {
return false
}
func (a *perfChoose) OnDestroy() bool {
return true
}
type ReqParams struct {
Sid string
Account string
PbReq proto.Message
MainType string
SubType string
}
func (a *perfChoose) buildReq(rp ReqParams) ([]byte, error) {
head := &pb.UserMessage{MainType: rp.MainType, SubType: rp.SubType}
head.Sec = common.BuildSecStr(rp.Sid, rp.Account)
if comm.ProtoMarshal(rp.PbReq, head) {
data, err := proto.Marshal(head)
if err != nil {
return nil, err
}
return data, nil
}
return nil, nil
}

View File

@ -115,7 +115,7 @@ func (app *perfConf) LazyInit(ptService service.PttService, obs observer.Observe
//next
defer closeApp3(perfWin.tabs, common.TOOLBAR_PERF_CONF)
openApp3(perfWin.tabs, common.TOOLBAR_PERF_PB)
openApp3(perfWin.tabs, common.TOOLBAR_PERF_CHOOSE)
}
resetBtn := widget.NewButtonWithIcon("重置", theme.ContentRedoIcon(), nil)

View File

@ -84,7 +84,7 @@ func (app *perfPb) LazyInit(ptService service.PttService, obs observer.Observer)
}
var login *UserLogin
login, err = app.loginReq(perfWin.config.SId)
handler.SetReq(login.req)
handler.SetReq(login.req, false)
assist := app.createAssistantWithoutConf(handler)
assist.Start()
assist.ShowResult()
@ -127,7 +127,7 @@ func (app *perfPb) LazyInit(ptService service.PttService, obs observer.Observer)
}
// }
handler.SetReq(reqData)
handler.SetReq(reqData, false)
assist := app.createAssistant(handler)
assist.Start()
assist.ShowResult()

View File

@ -48,13 +48,21 @@ func (app *perfResult) LazyInit(ptService service.PttService, obs observer.Obser
closeApp3(perfWin.tabs, common.TOOLBAR_PERF_RES)
}
// 返回
returnBtn := widget.NewButtonWithIcon("返回", theme.NavigateBackIcon(), nil)
returnBtn.OnTapped = func() {
defer openApp3(perfWin.tabs, common.TOOLBAR_PERF_CHOOSE)
app.itemList.Reset()
closeApp3(perfWin.tabs, common.TOOLBAR_PERF_RES)
}
//统计Panel
app.report = widget.NewCard("测试报告", "登录/创角", container.NewVBox(
// widget.NewLabel("结果:"),
))
app.report.Hide()
//layout
c := container.NewBorder(app.report, container.NewHBox(layout.NewSpacer(), app.resetBtn), nil, nil, app.itemList.ItemList)
c := container.NewBorder(app.report, container.NewHBox(layout.NewSpacer(), app.resetBtn, returnBtn), nil, nil, app.itemList.ItemList)
content.Objects = append(content.Objects, c)
app.tabItem.Content = content
app.listen()