package battletest import ( "fmt" "go_dreamfactory/comm" "go_dreamfactory/lego/core" "go_dreamfactory/lego/core/cbase" "go_dreamfactory/lego/sys/log" "go_dreamfactory/lego/sys/mgo" "go_dreamfactory/pb" "go_dreamfactory/utils" "os" "sync" "sync/atomic" "time" "go.mongodb.org/mongo-driver/bson" "google.golang.org/protobuf/proto" ) // 压测组件 type pressuretestComp struct { cbase.ModuleCompBase module *BattleTest report *pb.BattleReport lock sync.RWMutex workers []*worker state int32 //状态 1 运行 2结束 start time.Time //开始时间 end time.Time //结束时间 msgsize int64 cmdnum int64 round int64 battleinfosize int64 } // 组件初始化接口 func (this *pressuretestComp) Init(service core.IService, module core.IModule, comp core.IModuleComp, options core.IModuleOptions) (err error) { this.ModuleCompBase.Init(service, module, comp, options) this.module = module.(*BattleTest) return } func (this *pressuretestComp) Start() (err error) { err = this.ModuleCompBase.Start() var ( db mgo.ISys ) if db, err = mgo.NewSys( mgo.SetMongodbUrl(this.module.options.MongodbUrl), mgo.SetMongodbDatabase(this.module.options.MongodbDatabase), ); err != nil { return } result := &pb.DBBattlePlayRecord{} if err = db.FindOne(core.SqlTable(comm.TableBattlerecord), bson.M{"_id": this.module.options.BattleReportId}).Decode(result); err != nil { return } this.report = &pb.BattleReport{} this.msgsize = int64(len(result.Record)) if err = proto.Unmarshal(result.Record, this.report); err != nil { return } this.cmdnum = int64(len(this.report.Outcmd)) this.round = int64(this.report.Round) datas, _ := proto.Marshal(this.report.Info) this.battleinfosize = int64(len(datas)) for _, v := range this.report.Outcmd { datas, _ := proto.Marshal(v) log.Debugf("指令:%s大小 %s:", v.Cmdtype, utils.FormatByesSize(int64(len(datas)))) } this.cmdnum = int64(len(this.report.Outcmd)) this.workers = make([]*worker, this.module.options.Workers) this.start = time.Now() this.state = 1 go this.worker() go this.run() return } func (this *pressuretestComp) worker() { var wg sync.WaitGroup for i := int32(0); i < this.module.options.Workers; i++ { this.workers[i] = &worker{ module: this.module, report: this.report, statistics: make([]int64, 0, this.module.options.TestNum), testnum: this.module.options.TestNum, } wg.Add(1) go this.workers[i].Worker(&wg) } wg.Wait() log.Debug("[测试结束]") this.end = time.Now() atomic.StoreInt32(&this.state, 2) } func (this *pressuretestComp) run() { timer := time.NewTicker(time.Second * 10) locp: for { select { case <-timer.C: this.OutReport() this.end = time.Now() if atomic.LoadInt32(&this.state) == 2 { break locp } } } timer.Stop() log.Debug("[机器人 WTask]") } //输出报表 func (this *pressuretestComp) OutReport() { var ( workers [][]int64 = make([][]int64, this.module.options.Workers) num1, num2, num3, num4, num5 int ) for i, v := range this.workers { dst := make([]int64, len(v.statistics)) copy(dst, v.statistics) workers[i] = dst } file, err := os.OpenFile(this.module.options.OutFilePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) if err != nil { fmt.Println(err) return } defer file.Close() file.WriteString(fmt.Sprintf("并发数: %d\n", this.module.options.Workers)) file.WriteString(fmt.Sprintf("消息总请求数: %d\n", this.module.options.Workers*this.module.options.TestNum)) file.WriteString(fmt.Sprintf("回合数: %d\n", this.round)) file.WriteString(fmt.Sprintf("战报InfoSize: %s\n", utils.FormatByesSize(this.battleinfosize))) file.WriteString(fmt.Sprintf("指令数: %d\n", (this.cmdnum))) file.WriteString(fmt.Sprintf("消息总请求大小: %s\n", utils.FormatByesSize(this.msgsize))) file.WriteString(fmt.Sprintf("压测执行时长: %.2f秒\n", this.end.Sub(this.start).Seconds())) file.WriteString("0-5ms------------------5-10ms -------------------10-20ms -------------------------20-50ms-------------------->50ms\n") for _, data := range workers { for _, num := range data { if num <= 5 { num1++ } else if num <= 10 { num2++ } else if num <= 20 { num3++ } else if num <= 50 { num4++ } else { num5++ } } } file.WriteString(fmt.Sprintf("%-5d次 ------------------%-5d次 -------------------%-5d次 -------------------------%-5d次-------------------->%-5d次\n", num1, num2, num3, num4, num5)) }