You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
openim-sdk-cpp/go/chao-sdk-core/test/reliability.go

687 lines
19 KiB

// Copyright © 2023 OpenIM SDK. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package test
import (
"errors"
"fmt"
"github.com/openimsdk/openim-sdk-core/v3/pkg/utils"
"github.com/openimsdk/tools/log"
"io/ioutil"
"math/rand"
"os"
"runtime"
"strconv"
"strings"
"sync"
"time"
)
func GetFileContentAsStringLines(filePath string) ([]string, error) {
result := []string{}
b, err := ioutil.ReadFile(filePath)
if err != nil {
return result, err
}
s := string(b)
for _, lineStr := range strings.Split(s, "\n") {
lineStr = strings.TrimSpace(lineStr)
if lineStr == "" {
continue
}
result = append(result, lineStr)
}
return result, nil
}
func GetCmd(myUid int, filename string) int {
cmd, err := GetFileContentAsStringLines("cmd.txt")
if err != nil {
fmt.Println("GetFileContentAsStringLines failed")
return -1
}
if len(cmd) < myUid {
fmt.Println("len failed")
return -1
}
return int(utils.StringToInt64(cmd[myUid-1]))
}
func ReliabilityTest(msgNumOneClient int, intervalSleepMS int, randSleepMaxSecond int, clientNum int) {
msgNumInOneClient = msgNumOneClient
timeStamp := utils.Int64ToString(time.Now().Unix())
var wg sync.WaitGroup
// 注册
wg.Add(clientNum)
for i := 0; i < clientNum; i++ {
go func(idx int) {
RegisterReliabilityUser(idx, timeStamp)
wg.Done()
}(i)
}
wg.Wait()
log.ZWarn(ctx, "RegisterReliabilityUser finished, clientNum:", errors.New(""), "clientNum", clientNum)
log.ZWarn(ctx, "init, login, send msg, start", errors.New(""))
rand.Seed(time.Now().UnixNano())
// 一半用户立刻登录发消息
wg.Add(clientNum)
for i := 0; i < clientNum; i++ {
rdSleep := rand.Intn(randSleepMaxSecond) + 1
isSend := 0 // 消息是否成功发送控制量
if isSend == 0 {
go func(idx int) {
log.ZWarn(ctx, " send msg flag true ", errors.New(""), "idx", idx)
ReliabilityOne(idx, rdSleep, true, intervalSleepMS)
wg.Done()
}(i)
sendMsgClient++
} else {
go func(idx int) {
log.ZWarn(ctx, " send msg flag false ", errors.New(""), "idx", idx)
ReliabilityOne(idx, rdSleep, false, intervalSleepMS)
wg.Done()
}(i)
}
}
wg.Wait()
log.ZWarn(ctx, "send msg finish, CheckReliabilityResult", errors.New(""))
for {
// 消息异步落库可能出现延迟,每隔五秒再检查一次
if CheckReliabilityResult(msgNumOneClient, clientNum) {
log.ZWarn(ctx, "CheckReliabilityResult ok, exit", errors.New(""))
os.Exit(0)
return
} else {
log.ZWarn(ctx, "CheckReliabilityResult failed , wait.... ", errors.New(""))
}
time.Sleep(time.Duration(5) * time.Second)
}
}
func WorkGroupReliabilityTest(msgNumOneClient int, intervalSleepMS int, randSleepMaxSecond int, clientNum int, groupID string) {
msgNumInOneClient = msgNumOneClient
//timeStamp := utils.Int64ToString(time.Now().Unix())
var wg sync.WaitGroup
wg.Add(clientNum)
for i := 0; i < clientNum; i++ {
go func(idx int) {
WorkGroupRegisterReliabilityUser(idx)
wg.Done()
}(i)
}
wg.Wait()
log.ZWarn(ctx, "RegisterReliabilityUser finished", errors.New(""), "clientNum", clientNum)
log.ZWarn(ctx, " init, login, send msg, start ", errors.New(""))
rand.Seed(time.Now().UnixNano())
wg.Add(clientNum)
for i := 0; i < clientNum; i++ {
rdSleep := rand.Intn(randSleepMaxSecond) + 1
isSend := 0
if isSend == 0 {
go func(idx int) {
log.ZWarn(ctx, "send msg flag true", errors.New(""), "idx", idx)
WorkGroupReliabilityOne(idx, rdSleep, true, intervalSleepMS, groupID)
wg.Done()
}(i)
sendMsgClient++
} else {
go func(idx int) {
log.ZWarn(ctx, "send msg flag false", errors.New(""), "idx", idx)
ReliabilityOne(idx, rdSleep, false, intervalSleepMS)
wg.Done()
}(i)
}
}
wg.Wait()
//log.Warn("send msg finish, CheckReliabilityResult")
for {
if CheckReliabilityResult(msgNumOneClient, clientNum) {
//log.Warn("", "CheckReliabilityResult ok, exit")
os.Exit(0)
return
} else {
//log.Warn("", "CheckReliabilityResult failed , wait.... ")
}
time.Sleep(time.Duration(5) * time.Second)
}
}
func WorkGroupMsgDelayTest(msgNumOneClient int, intervalSleepMS int, randSleepMaxSecond int, clientBegin int, clientEnd int, groupID string) {
msgNumInOneClient = msgNumOneClient
var wg sync.WaitGroup
wg.Add(clientEnd - clientBegin + 1)
for i := clientBegin; i <= clientEnd; i++ {
go func(idx int) {
WorkGroupRegisterReliabilityUser(idx)
wg.Done()
}(i)
}
wg.Wait()
//log.Warn("", "RegisterReliabilityUser finished, client: ", clientBegin, clientEnd)
//log.Warn("", " init, login, send msg, start ")
rand.Seed(time.Now().UnixNano())
wg.Add(clientEnd - clientBegin + 1)
for i := clientBegin; i <= clientEnd; i++ {
rdSleep := rand.Intn(randSleepMaxSecond) + 1
isSend := 0
if isSend == 0 {
go func(idx int) {
//log.Warn("", " send msg flag true ", idx)
WorkGroupReliabilityOne(idx, rdSleep, true, intervalSleepMS, groupID)
wg.Done()
}(i)
sendMsgClient++
} else {
go func(idx int) {
//log.Warn("", " send msg flag false ", idx)
WorkGroupReliabilityOne(idx, rdSleep, false, intervalSleepMS, groupID)
wg.Done()
}(i)
}
}
wg.Wait()
//log.Warn("send msg finish, CheckReliabilityResult")
for {
if CheckReliabilityResult(msgNumOneClient, clientEnd-clientBegin+1) {
//log.Warn("", "CheckReliabilityResult ok, exit")
os.Exit(0)
return
} else {
//log.Warn("", "CheckReliabilityResult failed , wait.... ")
}
time.Sleep(time.Duration(5) * time.Second)
}
}
func PressTest(msgNumOneClient int, intervalSleepMS int, clientNum int) {
msgNumInOneClient = msgNumOneClient
//timeStamp := utils.Int64ToString(time.Now().Unix())
var wg sync.WaitGroup
wg.Add(clientNum)
for i := 0; i < clientNum; i++ {
go func(idx int) {
RegisterPressUser(idx)
log.ZInfo(ctx, "GetUserTokenFinish", "index", idx)
wg.Done()
}(i)
}
wg.Wait()
//log.Warn("", "get all user token finish ", clientNum, " cost time: ", time.Since(t1))
//log.Warn("", "init and login begin ")
wg.Add(clientNum)
for i := 0; i < clientNum; i++ {
go func(idx int) {
strMyUid := allLoginMgr[idx].userID
token := allLoginMgr[idx].token
PressInitAndLogin(idx, strMyUid, token, WSADDR, APIADDR)
wg.Done()
}(i)
}
wg.Wait()
//log.Warn("", "init and login end ", " cost time: ", time.Since(t1))
//log.Warn("", "send msg begin ")
wg.Add(clientNum)
for i := 0; i < clientNum; i++ {
go func(idx int) {
PressOne(idx, 0, true, intervalSleepMS)
//log.Warn("", "press finished ", idx)
wg.Done()
}(i)
}
wg.Wait()
sendMsgTotalSuccessNum := uint32(0)
sendMsgTotalFailedNum := uint32(0)
for _, v := range allLoginMgr {
sendMsgTotalSuccessNum += v.sendMsgSuccessNum
sendMsgTotalFailedNum += v.sendMsgFailedNum
}
//log.Warn("send msg end ", "number of messages expected to be sent: ", clientNum*msgNumOneClient, " sendMsgTotalSuccessNum: ", sendMsgTotalSuccessNum, " sendMsgTotalFailedNum: ", sendMsgTotalFailedNum, "cost time: ", time.Since(t1))
}
func WorkGroupPressTest(msgNumOneClient int, intervalSleepMS int, clientNum int, groupID string) {
msgNumInOneClient = msgNumOneClient
var wg sync.WaitGroup
wg.Add(clientNum)
for i := 0; i < clientNum; i++ {
go func(idx int) {
WorkGroupRegisterReliabilityUser(idx)
log.ZInfo(ctx, "GetUserTokenFinish", "index", idx)
wg.Done()
}(i)
}
wg.Wait()
//log.Warn("", "get all user token finish ", clientNum, " cost time: ", time.Since(t1))
//log.Warn("", "init and login begin ")
wg.Add(clientNum)
for i := 0; i < clientNum; i++ {
go func(idx int) {
strMyUid := allLoginMgr[idx].userID
token := allLoginMgr[idx].token
ReliabilityInitAndLogin(idx, strMyUid, token, WSADDR, APIADDR)
wg.Done()
}(i)
}
wg.Wait()
//log.Warn("", "init and login end ", " cost time: ", time.Since(t1))
//log.Warn("", "send msg begin ")
wg.Add(clientNum)
for i := 0; i < clientNum; i++ {
go func(idx int) {
WorkGroupPressOne(idx, 0, true, intervalSleepMS, groupID)
wg.Done()
}(i)
}
wg.Wait()
sendMsgTotalSuccessNum := uint32(0)
sendMsgTotalFailedNum := uint32(0)
for _, v := range allLoginMgr {
sendMsgTotalSuccessNum += v.sendMsgSuccessNum
sendMsgTotalFailedNum += v.sendMsgFailedNum
}
//log.Warn("send msg end ", "number of messages expected to be sent: ", clientNum*msgNumOneClient, " sendMsgTotalSuccessNum: ", sendMsgTotalSuccessNum, " sendMsgTotalFailedNum: ", sendMsgTotalFailedNum, "cost time: ", time.Since(t1))
}
func CheckReliabilityResult(msgNumOneClient int, clientNum int) bool {
log.ZInfo(ctx, "StartCheckMapSendToMapRecv")
sameNum := 0
// 消息数量不一致说明出现丢失
if len(SendSuccAllMsg)+len(SendFailedAllMsg) != msgNumOneClient*clientNum {
//log.Warn("", utils.GetSelfFuncName(), " send msg success number: ", len(SendSuccAllMsg),
// " send msg failed number: ", len(SendFailedAllMsg), " all: ", msgNumOneClient*clientNum)
return false
}
for ksend, _ := range SendSuccAllMsg {
_, ok := RecvAllMsg[ksend] // RecvAllMsg 的初始化何时?
if ok {
sameNum++
} else {
// 埋点日志,第 ksend 个消息数据 本地和服务器不一致
//log.Error("", "check failed not in recv ", ksend)
//log.Error("", "send failed num: ", len(SendFailedAllMsg),
// " send success num: ", len(SendSuccAllMsg), " recv num: ", len(RecvAllMsg))
return false
}
}
log.ZInfo(ctx, "CheckMapSendToMapRecvOK", "sameNum", sameNum)
//log.Info("", "start check map recv -> map send ")
//sameNum = 0
//for k1, _ := range RecvAllMsg {
// _, ok := SendSuccAllMsg[k1]
// if ok {
// sameNum++
// //x := v1 + v2
// //x = x + x
//
// } else {
// log.Error("", "check failed not in send ", k1, len(SendFailedAllMsg), len(SendSuccAllMsg), len(RecvAllMsg))
// // return false
// }
//}
minCostTime := int64(1000000)
maxCostTime := int64(0)
totalCostTime := int64(0)
for ksend, vsend := range SendSuccAllMsg {
krecv, ok := RecvAllMsg[ksend]
if ok {
sameNum++
costTime := krecv.RecvTime - vsend.SendTime
totalCostTime += costTime
if costTime > maxCostTime {
maxCostTime = costTime
}
if minCostTime > costTime {
minCostTime = costTime
}
}
}
//log.Warn("", "need send msg num : ", sendMsgClient*msgNumInOneClient)
//log.Warn("", "send msg succ num ", len(SendSuccAllMsg))
//log.Warn("", "send msg failed num ", len(SendFailedAllMsg))
//log.Warn("", "recv msg succ num ", len(RecvAllMsg))
//log.Warn("", "minCostTime: ", minCostTime, "ms, maxCostTime: ", maxCostTime, "ms, average cost time: ",
// totalCostTime/(int64(sendMsgClient*msgNumInOneClient)), "ms", " maxCostMsgID: ", maxCostMsgID)
return true
}
func ReliabilityOne(index int, beforeLoginSleep int, isSendMsg bool, intervalSleepMS int) {
// time.Sleep(time.Duration(beforeLoginSleep) * time.Second)
strMyUid := allLoginMgr[index].userID
token := allLoginMgr[index].token
log.ZInfo(ctx, "LoginOKClientNum", "clientNum", len(allLoginMgr), "userID", strMyUid, "token", token, "index", index)
ReliabilityInitAndLogin(index, strMyUid, token, WSADDR, APIADDR)
//log.Warn("start One", index, beforeLoginSleep, isSendMsg, strMyUid, token, WSADDR, APIADDR)
msgnum := msgNumInOneClient
uidNum := len(allLoginMgr)
rand.Seed(time.Now().UnixNano())
if msgnum == 0 {
os.Exit(0)
}
if !isSendMsg {
// Msgwg.Done()
} else {
for i := 0; i < msgnum; i++ {
var r int
time.Sleep(time.Duration(intervalSleepMS) * time.Millisecond)
for {
r = rand.Intn(uidNum)
if r == index {
continue
} else {
break
}
}
recvId := allLoginMgr[r].userID
idx := strconv.FormatInt(int64(i), 10)
for {
if runtime.NumGoroutine() > MaxNumGoroutine {
time.Sleep(time.Duration(intervalSleepMS) * time.Millisecond)
//log.Warn("", "NumGoroutine > max ", runtime.NumGoroutine(), MaxNumGoroutine)
continue
} else {
break
}
}
DoTestSendMsg(index, strMyUid, recvId, "", idx)
}
//Msgwg.Done()
}
}
func WorkGroupReliabilityOne(index int, beforeLoginSleep int, isSendMsg bool, intervalSleepMS int, groupID string) {
// time.Sleep(time.Duration(beforeLoginSleep) * time.Second)
strMyUid := allLoginMgr[index].userID
token := allLoginMgr[index].token
ReliabilityInitAndLogin(index, strMyUid, token, WSADDR, APIADDR)
log.ZInfo(ctx, "LoginSuccess", "clientNum", len(allLoginMgr))
//log.Warn("start One", index, beforeLoginSleep, isSendMsg, strMyUid, token, WSADDR, APIADDR)
msgnum := msgNumInOneClient
uidNum := len(allLoginMgr)
var idx string
rand.Seed(time.Now().UnixNano())
if msgnum == 0 {
os.Exit(0)
}
if !isSendMsg {
// Msgwg.Done()
} else {
for i := 0; i < msgnum; i++ {
var r int
time.Sleep(time.Duration(intervalSleepMS) * time.Millisecond)
for {
r = rand.Intn(uidNum)
if r == index {
continue
} else {
break
}
}
idx = strconv.FormatInt(int64(i), 10)
for {
if runtime.NumGoroutine() > MaxNumGoroutine {
time.Sleep(time.Duration(intervalSleepMS) * time.Millisecond)
//log.Warn("", "NumGoroutine > max ", runtime.NumGoroutine(), MaxNumGoroutine)
continue
} else {
break
}
}
DoTestSendMsg(index, strMyUid, "", groupID, idx)
}
//Msgwg.Done()
}
}
func WorkGroupMsgDelayOne(index int, beforeLoginSleep int, isSendMsg bool, intervalSleepMS int, groupID string) {
// time.Sleep(time.Duration(beforeLoginSleep) * time.Second)
strMyUid := allLoginMgr[index].userID
token := allLoginMgr[index].token
ReliabilityInitAndLogin(index, strMyUid, token, WSADDR, APIADDR)
log.ZInfo(ctx, "LoginSuccess", "clientNum", len(allLoginMgr))
//log.Warn("start One", index, beforeLoginSleep, isSendMsg, strMyUid, token, WSADDR, APIADDR)
msgnum := msgNumInOneClient
uidNum := len(allLoginMgr)
var idx string
rand.Seed(time.Now().UnixNano())
if msgnum == 0 {
os.Exit(0)
}
if !isSendMsg {
// Msgwg.Done()
} else {
for i := 0; i < msgnum; i++ {
var r int
time.Sleep(time.Duration(intervalSleepMS) * time.Millisecond)
for {
r = rand.Intn(uidNum)
if r == index {
continue
} else {
break
}
}
idx = strconv.FormatInt(int64(i), 10)
for {
if runtime.NumGoroutine() > MaxNumGoroutine {
time.Sleep(time.Duration(intervalSleepMS) * time.Millisecond)
//log.Warn("", "NumGoroutine > max ", runtime.NumGoroutine(), MaxNumGoroutine)
continue
} else {
break
}
}
DoTestSendMsg(index, strMyUid, "", groupID, idx)
}
//Msgwg.Done()
}
}
//
//funcation WorkGroupMsgDelayOne(sendID1 string, beforeLoginSleep int, isSendMsg bool, intervalSleepMS int, groupID string) {
// // time.Sleep(time.Duration(beforeLoginSleep) * time.Second)
// strMyUid := allLoginMgr[index].userID
// token := allLoginMgr[index].token
// ReliabilityInitAndLogin(index, strMyUid, token, WSADDR, APIADDR)
// log.Info("", "login ok client num: ", len(allLoginMgr))
// log.Warn("start One", index, beforeLoginSleep, isSendMsg, strMyUid, token, WSADDR, APIADDR)
// msgnum := msgNumInOneClient
// uidNum := len(allLoginMgr)
// var idx string
// rand.Seed(time.Now().UnixNano())
// if msgnum == 0 {
// os.Exit(0)
// }
// if !isSendMsg {
// // Msgwg.Done()
// } else {
// for i := 0; i < msgnum; i++ {
// var r int
// time.Sleep(time.Duration(intervalSleepMS) * time.Millisecond)
// for {
// r = rand.Intn(uidNum)
// if r == index {
// continue
// } else {
//
// break
// }
//
// }
//
// idx = strconv.FormatInt(int64(i), 10)
// for {
// if runtime.NumGoroutine() > MaxNumGoroutine {
// time.Sleep(time.Duration(intervalSleepMS) * time.Millisecond)
// log.Warn("", "NumGoroutine > max ", runtime.NumGoroutine(), MaxNumGoroutine)
// continue
// } else {
// break
// }
// }
//
// DoTestSendMsg(index, strMyUid, "", groupID, idx)
//
// }
// //Msgwg.Done()
// }
//}
func PressOne(index int, beforeLoginSleep int, isSendMsg bool, intervalSleepMS int) {
if beforeLoginSleep != 0 {
time.Sleep(time.Duration(beforeLoginSleep) * time.Millisecond)
}
strMyUid := allLoginMgr[index].userID
token := allLoginMgr[index].token
// ReliabilityInitAndLogin(index, strMyUid, token, WSADDR, APIADDR)
log.ZInfo(ctx, "LoginSuccess", "clientNum", len(allLoginMgr))
log.ZInfo(ctx, "StartOne", "index", index, "beforeLoginSleep", beforeLoginSleep, "isSendMsg", isSendMsg, "senderUID", strMyUid, "token", token, "wsAddr", WSADDR, "apiAddr", APIADDR)
msgnum := msgNumInOneClient
uidNum := len(allLoginMgr)
var recvId string
var idx string
rand.Seed(time.Now().UnixNano())
if msgnum == 0 {
os.Exit(0)
}
if !isSendMsg {
// Msgwg.Done()
} else {
for i := 0; i < msgnum; i++ {
var r int
// time.Sleep(time.Duration(intervalSleepMS) * time.Millisecond)
for {
r = rand.Intn(uidNum)
if r == index {
continue
} else {
break
}
}
recvId = allLoginMgr[r].userID
idx = strconv.FormatInt(int64(i), 10)
for {
if runtime.NumGoroutine() > MaxNumGoroutine {
time.Sleep(time.Duration(intervalSleepMS) * time.Millisecond)
//log.Warn("", " NumGoroutine > max ", runtime.NumGoroutine(), MaxNumGoroutine)
continue
} else {
break
}
}
time.Sleep(time.Duration(intervalSleepMS) * time.Millisecond)
//DoTestSendMsg(index, strMyUid, recvId, idx)
if sendPressMsg(index, strMyUid, recvId, "", idx) {
allLoginMgr[index].sendMsgSuccessNum++
} else {
allLoginMgr[index].sendMsgFailedNum++
}
}
//Msgwg.Done()
}
}
func WorkGroupPressOne(index int, beforeLoginSleep int, isSendMsg bool, intervalSleepMS int, groupID string) {
if beforeLoginSleep != 0 {
time.Sleep(time.Duration(beforeLoginSleep) * time.Millisecond)
}
strMyUid := allLoginMgr[index].userID
token := allLoginMgr[index].token
//ReliabilityInitAndLogin(index, strMyUid, token, WSADDR, APIADDR)
log.ZInfo(ctx, "LoginSuccess", "clientNum", len(allLoginMgr))
log.ZInfo(ctx, "StartOne", "index", index, "beforeLoginSleep", beforeLoginSleep, "isSendMsg", isSendMsg, "senderUID", strMyUid, "token", token, "wsAddr", WSADDR, "apiAddr", APIADDR)
msgnum := msgNumInOneClient
var idx string
rand.Seed(time.Now().UnixNano())
if msgnum == 0 {
os.Exit(0)
}
if !isSendMsg {
} else {
for i := 0; i < msgnum; i++ {
idx = strconv.FormatInt(int64(i), 10)
for {
if runtime.NumGoroutine() > MaxNumGoroutine {
time.Sleep(time.Duration(intervalSleepMS) * time.Millisecond)
//log.Warn("", " NumGoroutine > max ", runtime.NumGoroutine(), MaxNumGoroutine)
continue
} else {
break
}
}
log.ZInfo(ctx, "SendPressMsgBegin", "index", index, "senderUID", strMyUid, "groupID", groupID)
if sendPressMsg(index, strMyUid, "", groupID, idx) {
allLoginMgr[index].sendMsgSuccessNum++
} else {
allLoginMgr[index].sendMsgFailedNum++
}
log.ZInfo(ctx, "sendPressMsg end")
time.Sleep(time.Duration(intervalSleepMS) * time.Millisecond)
}
}
}