Tron 节点 性能压测


最近搭建了一个TRON节点,同事不相信我的自建节点比官方更靠谱,咱们给他使用golang写一个压测脚本,测试一下。

本文档详细介绍了一个基于 Go 的并发 HTTP 请求工具,帮助你对 Tron 节点进行压力测试。本文档将从代码简介、环境配置、编译运行以及结果分析等方面进行详细说明。

一、代码说明

该工具通过并发多个 HTTP 请求,对 Tron 节点的处理能力进行压力测试。每个请求都会记录响应时间,并将结果输出。

1.1 主要功能

  • 发送并发 HTTP 请求到指定 Tron 节点。
  • 记录每个请求的响应时间和状态。
  • 支持配置请求超时时间、并发 worker 数量和每个 worker 发送的请求数量。

1.2 代码示例

package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"net/http"
	"sync"
	"time"
)

// worker 函数执行 HTTP 请求并记录响应时间
func worker(id int, wg *sync.WaitGroup, url string, payload string, results chan<- string, numRequests int, timeout time.Duration) {
	defer wg.Done()

	client := &http.Client{
		Timeout: timeout,
	}

	for i := 0; i < numRequests; i++ {
		req, err := http.NewRequest("POST", url, bytes.NewBuffer([]byte(payload)))
		if err != nil {
			results <- fmt.Sprintf("Worker %d: error creating request: %v", id, err)
			return
		}
		req.Header.Set("Content-Type", "application/json")

		start := time.Now()
		resp, err := client.Do(req)
		duration := time.Since(start)

		if err != nil {
			results <- fmt.Sprintf("Worker %d: error making request: %v", id, err)
			return
		}
		defer resp.Body.Close()

		if resp.StatusCode != http.StatusOK {
			body, _ := ioutil.ReadAll(resp.Body)
			results <- fmt.Sprintf("Worker %d: received non-OK status: %s, response body: %s", id, resp.Status, string(body))
			return
		}

		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			results <- fmt.Sprintf("Worker %d: error reading response body: %v", id, err)
			return
		}

		results <- fmt.Sprintf("Worker %d: success in %v, response: %s", id, duration, string(body))
	}
}

func main() {
	// Tron 节点的 URL
	url := "http://节点地址:8090/wallet/getnowblock"
	// 替换为你的实际账户地址
	accountAddress := "your-account-address"
	payload := fmt.Sprintf(`{"address":"%s"}`, accountAddress)

	// 并发请求的 worker 数量
	numWorkers := 200
	// 每个 worker 发送的请求数量
	numRequests := 1
	// HTTP 请求的超时时间
	timeout := 3 * time.Second

	var wg sync.WaitGroup
	results := make(chan string, numWorkers*numRequests)

	// 启动 worker
	for i := 0; i < numWorkers; i++ {
		wg.Add(1)
		go worker(i, &wg, url, payload, results, numRequests, timeout)
	}

	// 等待所有 worker 完成
	wg.Wait()
	close(results)

	// 输出结果
	for result := range results {
		fmt.Println(result)
	}
}

1.3 代码解释

package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"net/http"
	"sync"
	"time"
)

导入包

  • bytes:用于处理字节缓冲区,构造 HTTP 请求的 body。
  • fmt:用于格式化输入输出。
  • ioutil:提供 I/O 实用函数,读取 HTTP 响应的 body。
  • net/http:用于发送 HTTP 请求。
  • sync:提供同步原语,例如 WaitGroup。
  • time:用于处理时间和定时器。
func worker(id int, wg *sync.WaitGroup, url string, payload string, results chan<- string, numRequests int, timeout time.Duration) {
	defer wg.Done()
  1. 参数:
  • id:worker 的 ID,用于标识日志中的具体 worker。
  • wg:WaitGroup,用于等待所有 worker 完成。
  • url:HTTP 请求的目标 URL。
  • payload:请求体数据。
  • results:用于存储结果的通道。
  • numRequests:每个 worker 发送的请求数量。
  • timeout:每个 HTTP 请求的超时时间。
  1. defer wg.Done():确保函数结束时调用 wg.Done(),通知 WaitGroup 当前 worker 已完成。
	client := &http.Client{
		Timeout: timeout,
	}

创建 HTTP 客户端

  • 创建一个带有超时设置的 HTTP 客户端。
	for i := 0; i < numRequests; i++ {
		req, err := http.NewRequest("POST", url, bytes.NewBuffer([]byte(payload)))
		if err != nil {
			results <- fmt.Sprintf("Worker %d:error creating request: %v", id, err)
			return
		}
		req.Header.Set("Content-Type","application/json")

发送 HTTP 请求

  • 循环发送 numRequests 个请求。
  • 使用 http.NewRequest 创建新的 POST 请求。
  • 设置请求头 Content-Type 为 application/json。
start := time.Now()
resp, err := client.Do(req)
duration := time.Since(start)

记录请求时间

  • 记录请求开始时间。
  • 发送请求并接收响应。
  • 计算请求的总持续时间。
		if err != nil {
			results <- fmt.Sprintf("Worker %d: error making request: %v", id, err)
			return
		}
		defer resp.Body.Close()

处理请求错误和响应

  • 如果请求错误,记录错误信息并返回。
  • 确保在函数结束时关闭响应体。
		if resp.StatusCode != http.StatusOK {
			body, _ := ioutil.ReadAll(resp.Body)
			results <- fmt.Sprintf("Worker %d: received non-OK status: %s, response body: %s", id, resp.Status, string(body))
			return
		}

检查响应状态码

  • 检查响应状态码是否为 200 (OK)。
  • 如果不是 200,读取响应体并记录错误信息。
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			results <- fmt.Sprintf("Worker %d: error reading response body: %v", id, err)
			return
		}

读取响应体

  • 读取响应体,如果读取错误,记录错误信息。
		results <- fmt.Sprintf("Worker %d: success in %v, response: %s", id, duration, string(body))
	}
}

记录成功请求

  • 将成功请求的结果、持续时间和响应体发送到结果通道。
func main() {
	// Tron 节点的 URL
	url := "http://tron节点地址:8090/wallet/getnowblock"
	// 替换为你的实际账户地址
	accountAddress := "your-account-address"
	payload := fmt.Sprintf(`{"address":"%s"}`, accountAddress)

main 函数

  • 定义 Tron 节点的 URL 和请求体数据。
// 并发请求的 worker 数量
numWorkers := 200
// 每个 worker 发送的请求数量
numRequests := 1
// HTTP 请求的超时时间
timeout := 3 * time.Second

配置参数

  • numWorkers:并发 worker 的数量。
  • numRequests:每个 worker 发送的请求数量。
  • timeout:HTTP 请求的超时时间。
var wg sync.WaitGroup
results := make(chan string,numWorkers*numRequests)

初始化 WaitGroup 和结果通道

  • 创建一个 WaitGroup,用于同步所有 worker。
  • 创建一个结果通道,用于存储每个请求的结果。
	// 启动 worker
	for i := 0; i < numWorkers; i++ {
		wg.Add(1)
		go worker(i, &wg, url, payload, results, numRequests, timeout)
	}

启动并发 worker

  • 启动 numWorkers 个并发 worker,每个 worker 在独立的 goroutine 中运行。
	// 等待所有 worker 完成
	wg.Wait()
	close(results)

等待所有 worker 完成

  • 使用 wg.Wait() 等待所有 worker 完成。
  • 关闭结果通道,表示所有结果已经写入完成。
	// 输出结果
	for result := range results {
		fmt.Println(result)
	}
}
  • 输出结果
    迭代结果通道,打印每个请求的结果。

1.4 执行流程

  • 初始化和配置:导入必要的包并定义 worker 函数和 main 函数中的参数。
  • 创建并启动 worker:在 main 函数中,根据配置启动并发的 worker。
  • 发送请求:每个 worker 根据 numRequests 发送指定数量的请求。
  • 处理响应:每个请求记录开始时间、发送请求、接收响应并记录结束时间。处理请求的错误和响应状态码,并读取响应体。
  • 记录结果:将每个请求的结果、持续时间和响应体发送到结果通道。
  • 等待完成:等待所有 worker 完成,并关闭结果通道。
  • 输出结果:迭代结果通道,打印每个请求的结果。

二、结果分析

程序的输出包括每个请求的响应时间和响应内容。以下是输出示例:

Worker 0: success in 150ms, response: {...}
Worker 1: success in 145ms, response: {...}
Worker 2: received non-OK status: 500 Internal Server Error, response body: {...}
...
Average request duration: 147ms

输出说明

  • Worker X: success in Yms, response: {…}:表示 worker X 成功发送了请求,响应时间为 Y 毫秒,响应内容为 {…}。
  • Worker X: received non-OK status: …:表示 worker X 收到了非 200 状态码的响应,响应内容显示在 {…} 中。
  • Average request duration: …:表示所有请求的平均响应时间。

三、参数解释

3.1 numWorkers 和 numRequests 说明

numWorkers

  • 定义:numWorkers 代表并发执行的 worker 数量。
  • 作用:控制并发请求的数量。每个 worker 是一个独立的 goroutine,它会发送 HTTP 请求到指定的 URL。
  • 作用机制:当程序运行时,会启动 numWorkers 个并发的 goroutine,每个 goroutine 都会执行 worker 函数。

numRequests

  • 定义:numRequests 代表每个 worker 需要发送的请求数量。
  • 作用:控制每个 worker 发送的请求总数。一个 worker 会在一个循环中发送多个请求,直到达到numRequests 的数量。
  • 作用机制:每个 worker 启动后,会在一个循环中发送 numRequests 个 HTTP 请求。

两个参数的关系

  • 并发度:numWorkers 决定了程序的并发度。更多的 workers 意味着更多的并发请求。
  • 总请求数:总的请求数由 numWorkers 和 numRequests 的乘积决定。总请求数 = numWorkers × numRequests。

关系示例

numWorkers = 200
numRequests = 10

那么:

  • 将启动 200 个并发的 worker。
  • 每个 worker 发送 10 个请求。
  • 总请求数为 200 × 10 = 2000 个请求。

3.2 使用场景

高并发测试

  • 增大 numWorkers 可以增加并发请求的数量,用于测试服务器在高并发情况下的表现。
  • 适用于需要模拟大量用户同时访问服务器的场景。

高负载测试

  • 增大 numRequests 可以增加每个 worker 发送的请求总数,用于测试服务器在高负载情况下的表现。
  • 适用于需要模拟少量用户频繁访问服务器的场景。

可以调整 numWorkers 和 numRequests 来模拟不同的压力场景。

  • 如需模拟高并发但请求数少的情况,可以增加 numWorkers 并减少 numRequests。
  • 如需模拟低并发但请求数多的情况,可以减少 numWorkers 并增加 numRequests。

通过合理配置 numWorkers 和 numRequests,可以有效地测试服务器在不同负载和并发条件下的性能表现。

四、注意事项

  • 请确保 Tron节点可以处理大量并发请求,以避免节点过载。

  • 调整超时时间以适应你的网络环境,避免因网络延迟导致的不必要错误。

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
ava实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),可运行高分资源 Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。下面详细介绍C语言的基本概念和语法。 1. 变量和数据类型 在C语言中,变量用于存储数据,数据类型用于定义变量的类型和范围。C语言支持多种数据类型,包括基本数据类型(如int、float、char等)和复合数据类型(如结构体、联合等)。 2. 运算符 C语言中常用的运算符包括算术运算符(如+、、、/等)、关系运算符(如==、!=、、=、<、<=等)、逻辑运算符(如&&、||、!等)。此外,还有位运算符(如&、|、^等)和指针运算符(如、等)。 3. 控制结构 C语言中常用的控制结构包括if语句、循环语句(如for、while等)和switch语句。通过这些控制结构,可以实现程序的分支、循环和多路选择等功能。 4. 函数 函数是C语言中用于封装代码的单元,可以实现代码的复用和模块化。C语言中定义函数使用关键字“void”或返回值类型(如int、float等),并通过“{”和“}”括起来的代码块来实现函数的功能。 5. 指针 指针是C语言中用于存储变量地址的变量。通过指针,可以实现对内存的间接访问和修改。C语言中定义指针使用星号()符号,指向数组、字符串和结构体等数据结构时,还需要注意数组名和字符串常量的特殊性质。 6. 数组和字符串 数组是C语言中用于存储同类型数据的结构,可以通过索引访问和修改数组中的元素。字符串是C语言中用于存储文本数据的特殊类型,通常以字符串常量的形式出现,用双引号("...")括起来,末尾自动添加'\0'字符。 7. 结构体和联合 结构体和联合是C语言中用于存储不同类型数据的复合数据类型。结构体由多个成员组成,每个成员可以是不同的数据类型;联合由多个变量组成,它们共用同一块内存空间。通过结构体和联合,可以实现数据的封装和抽象。 8. 文件操作 C语言中通过文件操作函数(如fopen、fclose、fread、fwrite等)实现对文件的读写操作。文件操作函数通常返回文件指针,用于表示打开的文件。通过文件指针,可以进行文件的定位、读写等操作。 总之,C语言是一种功能强大、灵活高效的编程语言,广泛应用于各种领域。掌握C语言的基本语法和数据结构,可以为编程学习和实践打下坚实的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杰哥的技术杂货铺

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值