目錄
?
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`文件。
?
?