Hyperledger Fabric使用Golang SDK测试网络吞吐量

1. 使用github.com/panjf2000/ants

func getContract() *gateway.Contract {

	wallet, _ := gateway.NewFileSystemWallet("resources/wallet-whu-cloud-org1")

	networkConfig := filepath.Join("resources", "connection-whu-cloud-org1.yaml")
	gw, err := gateway.Connect(
		gateway.WithConfig(config.FromFile(filepath.Clean(networkConfig))),
		gateway.WithIdentity(wallet, "admin"),
	)
	if err != nil {
		log.Panicf("Failed to create new Gateway: " + err.Error())
	}
	defer gw.Close()

	nw, err := gw.GetNetwork("mychannel")
	if err != nil {
		log.Panicf("Failed to get network: " + err.Error())
	}

	contract := nw.GetContract("abstore")
	return contract
}

func TestGatewayWithAnts() {

	poolSize := 1300	//并发数
	txCount : 10000		//交易数
	
	contract := getContract()
	start := time.Now()
	
	var wg sync.WaitGroup
	p, _ := ants.NewPoolWithFunc(poolSize , func(i interface{}) {
		n := i.(int)
		resp, _ := contract.SubmitTransaction("Set", "key_" + strconv.Itoa(int(start.Unix())) + strconv.Itoa(n), "1")
		//log.Printf("NumGoroutine[%d]-Resp: %s\n", runtime.NumGoroutine(), resp)
		wg.Done()
	})
	defer p.Release()
	
	start = time.Now()
	for i := 0; i < txCount; i++ {
		wg.Add(1)
		_ = p.Invoke(i)
	}
	wg.Wait()
	
	duration:= time.Since(start)
	log.Printf("Time: %s\n", duration)
	log.Printf("TPS: %f\n", float64(txCount) / duration.Seconds())
}

执行结果:

2020/12/22 15:11:44 Time: 6.5174183s
2020/12/22 15:11:44 TPS: 1534.349882

2. 自定义WorkerPool

var(
	channelBufferSize = 10		//chan的缓冲大小
	workerPoolSize = 500		//worker数量
	txCount = 10000				//发送交易数量
)

type Tx struct {
	id int
	args []string	//交易参数,args[0]为函数名
}

type Output struct {	//交易执行的输出
	tx Tx
	result []byte
}

//待发送的交易池
var txs = make(chan Tx, channelBufferSize)
//交易执行的结果池
var outputs = make(chan Output, channelBufferSize)

var contract = getContract()	//不同worker共用contract对象

//发送交易,返回执行结果
func sendTx(tx Tx) Output {
	resp, _ := contract.SubmitTransaction(tx.args[0], tx.args[1:]...)
	//resp, _ := contract.EvaluateTransaction(tx.args[0], tx.args[1:]...)
	return Output{
		tx,
		resp,
	}
}

//单个worker,从交易池中拿交易发送
func worker(wg *sync.WaitGroup) {
	for tx := range txs{
		outputs <- sendTx(tx)
	}
	wg.Done()
}

//创建指定数量的worker,让它们同时工作,并等待所有worker工作完成
func createWorkerPool(workerPoolSize int) {
	var wg sync.WaitGroup
	for i := 0; i < workerPoolSize; i++ {
		wg.Add(1)
		go worker(&wg)
	}
	wg.Wait()
	close(outputs)
}

// 产生交易,发送到交易队池
func createTxs(txCount int) {
	//t := int(time.Now().Unix())
	for i := 0; i < txCount; i++ {
		tx := Tx{
			i,
			[]string{"Set", "key_xxx_" + strconv.Itoa(i), "1"},
		}
		txs <- tx
	}
	close(txs)
}

//从交易执行输出队列中取出交易输出
func getOutputs(ch chan bool) {
	for output := range outputs {//outputs没有close的话,会一直尝试读取,造成阻塞
		//log.Printf("runing routines: %d, tx intput: %+v, tx output: %s\n", runtime.NumGoroutine(), output.tx, output.result)
	}
	ch <- true
}

func TestWorkerPool() {
	startTime := time.Now()
	go createTxs(txCount)
	done := make(chan bool)
	go getOutputs(done)
	createWorkerPool(workerPoolSize)
	<-done
	duration := time.Since(startTime)
	log.Println("Time ", duration.Seconds(), "seconds")
	log.Printf("TPS: %f\n", float64(txCount) / duration.Seconds())
}

执行结果:

2020/12/22 15:13:20 Time: 6.0987865s
2020/12/22 15:13:20 TPS: 1639.670449

3. 测试环境

Hyperledger Fabric使用Golang SDK测试网络吞吐量_第1张图片

4. 总结

  • 两种方式性能差不多
  • 都支持并发协程数量的控制

你可能感兴趣的:(Fabric,区块链,Golang,golang,区块链,多线程)