C++负载均衡远程调用学习之QPS性能测试
目录
1.昨日回顾
2.QPS_TEST_PROTOBUF协议的集成
3.QPS_TEST_SERVER端实现
4.QPS_TEST_QPS简单介绍
5.QPS_TEST_QPS客户端工具编写和性能测试
1.昨日回顾
2.QPS_TEST_PROTOBUF协议的集成
## 14) Reactor框架QPS性能测试
接下来我们写一个测试用例来测一下我们的Reactor框架的qps。
> qps: (Query Per Second)每秒查询率QPS是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准。
3.QPS_TEST_SERVER端实现
### 14.1 测试用例代码编写
我们首先定义一个proto文件,用来承载客户端和服务端通信媒介的。
> example/qps_test/echoMessage.proto
```protobuf
syntax = "proto3";
package qps_test;
message EchoMessage
{
string content = 1;
int32 id = 2;
};
```
然后生成对应的cc文件和h文件
```bash
protoc --cpp_out=. ./*.proto
```
接下来我们来实现服务端,服务端主要就是简单的回显,客户端发什么数据,回显就可以了。
> example/qps_test/server.cpp
```c
#include <string>
#include <string.h>
#include "config_file.h"
#include "tcp_server.h"
#include "echoMessage.pb.h"
//回显业务的回调函数
void callback_busi(const char *data, uint32_t len, int msgid, net_connection *conn, void *user_data)
{
qps_test::EchoMessage request, response;
//解包,确保data[0-len]是一个完整包
request.ParseFromArray(data, len);
//设置新pb包
response.set_id(request.id());
response.set_content(request.content());
//序列化
std::string responseString;
response.SerializeToString(&responseString);
conn->send_message(responseString.c_str(), responseString.size(), msgid);
}
int main()
{
event_loop loop;
//加载配置文件
config_file::setPath("./serv.conf");
std::string ip = config_file::instance()->GetString("reactor", "ip", "0.0.0.0");
short port = config_file::instance()->GetNumber("reactor", "port", 8888);
printf("ip = %s, port = %d\n", ip.c_str(), port);
tcp_server server(&loop, ip.c_str(), port);
//注册消息业务路由
server.add_msg_router(1, callback_busi);
loop.event_process();
return 0;
}
```
接下来是客户端,客户端我们创建一个Qps结构体,来记录每秒,服务端成功回显数据的次数,来做qps统计,客户端我们可以指定开多少个线程去压测服务端。
> example/qps_test/client.cpp
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <string>
#include "tcp_client.h"
#include "echoMessage.pb.h"
struct Qps
{
Qps() {
last_time = time(NULL);
succ_cnt = 0;
}
long last_time;//最后一次发包时间 ms为单位
int succ_cnt; //成功收到服务器回显的次数
};
//客户端业务
void busi(const char *data, uint32_t len, int msgid, net_connection *conn, void *user_data)
{
Qps *qps = (Qps*)user_data; //用户参数
qps_test::EchoMessage request, response;
//解析服务端传来的pb数据
if (response.ParseFromArray(data, len) == false) {
printf("server call back data error\n");
return;
}
//判断数据内容是否回显一致
if (response.content() == "Hello Lars!!!") {
//服务器请求响应成功一次
qps->succ_cnt ++;
}
long current_time = time(NULL);
if (current_time - qps->last_time >= 1) {
//如果当前时间比最后记录时间大于1秒,那么我们进行记录
printf("---> qps = %d <----\n", qps->succ_cnt);
qps->last_time = current_time;//记录最后时间
qps->succ_cnt = 0;//清空成功次数
}
//给服务端发送新的请求
request.set_id(response.id() + 1);
request.set_content(response.content());
std::string requestString;
request.SerializeToString(&requestString);
conn->send_message(requestString.c_str(), requestString.size(), msgid);
}
//创建链接成功之后
void connection_start(net_connection *client, void *args)
{
qps_test::EchoMessage request;
request.set_id(1);
request.set_content("Hello Lars!!!");
std::string requestString;
request.SerializeToString(&requestString);
int msgid = 1;//与server端的消息路由一致
client->send_message(requestString.c_str(), requestString.size(), msgid);
}
4.QPS_TEST_QPS简单介绍
void *thread_main(void *args)
{
//给服务端发包
event_loop loop;
tcp_client client(&loop, "127.0.0.1", 7777, "qps client");
Qps qps;
//设置回调
client.add_msg_router(1, busi, (void*)&qps);
//设置链接创建成功之后Hook
client.set_conn_start(connection_start);
loop.event_process();
return NULL;
}
int main(int argc, char **argv)
{
if (argc == 1) {
printf("Usage: ./client [threadNum]\n");
return 1;
}
//创建N个线程
int thread_num = atoi(argv[1]);
pthread_t *tids;
tids = new pthread_t[thread_num];
for (int i = 0; i < thread_num; i++) {
pthread_create(&tids[i], NULL, thread_main, NULL);
}
for (int i = 0; i < thread_num; i++) {
pthread_join(tids[i], NULL);
}
return 0;
}
```
5.QPS_TEST_QPS客户端工具编写和性能测试
接下来我们的Makefile
```makefile
CXX=g++
CFLAGS=-g -O2 -Wall -fPIC -Wno-deprecated
INC=-I../../include
LIB=-L../../lib -llreactor -lpthread -lprotobuf
OBJS = $(addsuffix .o, $(basename $(wildcard *.cc)))
all:
$(CXX) -o server $(CFLAGS) server.cpp echoMessage.pb.cc $(INC) $(LIB)
$(CXX) -o client $(CFLAGS) client.cpp echoMessage.pb.cc $(INC) $(LIB)
clean:
-rm -f *.o server client
```
记住编译加上`-lprotobuf` 编译的文件加上`echoMessage.pb.cc`文件。