首页 > 人工智能 > 机器学习 > 基于 cronet 的单链接性能信息收集
早先的基于 boost 的版本这些都很好统计,后来该产品底层网络库换成 cronet 就不好统计了,我的工作就是基于 cronet 重新收集上述性能信息。
正式开搞前先简单看下 cronet 网络编程范式与之前有何不同:
#include <string>#include <thread>#include <iostream>#include <cronet/cronet_c.h>// 回调:重定向void on_redirect_received(Cronet_UrlRequestCallback* callback,
Cronet_UrlRequest* request,
Cronet_UrlResponseInfo* info, const char* new_location) { std::cout << "Redirect to: " << new_location << std::endl;
Cronet_UrlRequest_FollowRedirect(request);
}// 回调:响应开始void on_response_started(Cronet_UrlRequestCallback* callback,
Cronet_UrlRequest* request,
Cronet_UrlResponseInfo* info) { std::cout << "Response started" << std::endl;
Cronet_Buffer* buffer = Cronet_Buffer_Create();
Cronet_Buffer_InitWithAlloc(buffer, 4096); // 4KB缓冲区
Cronet_UrlRequest_Read(request, buffer);
}// 回调:读取完成void on_read_completed(Cronet_UrlRequestCallback* callback,
Cronet_UrlRequest* request,
Cronet_UrlResponseInfo* info,
Cronet_Buffer* buffer, uint64_t bytes_read) { // 处理数据
if (bytes_read > 0) { const char* data = static_cast<const char*>(Cronet_Buffer_GetData(buffer)); std::cout << "Read " << bytes_read << " bytes" << std::endl; std::cout << data << std::endl;
}
// 释放当前buffer
Cronet_Buffer_Destroy(buffer); // 继续读取(如果还有数据且未完成)
if (bytes_read > 0) {
Cronet_Buffer* new_buffer = Cronet_Buffer_Create();
Cronet_Buffer_InitWithAlloc(new_buffer, 4096);
Cronet_UrlRequest_Read(request, new_buffer);
} else { std::cout << "Read completed" << std::endl;
}
}// 回调:请求成功void on_succeeded(Cronet_UrlRequestCallback* callback,
Cronet_UrlRequest* request,
Cronet_UrlResponseInfo* info) { std::cout << "Request succeeded" << std::endl;
}// 回调:请求失败void on_failed(Cronet_UrlRequestCallback* callback,
Cronet_UrlRequest* request,
Cronet_UrlResponseInfo* info,
Cronet_Error* error)gov.mbp.zuzb.info { std::cout << "Request failed" << std::endl;
}// 回调:取消void on_canceled(Cronet_UrlRequestCallback* callback,
Cronet_UrlRequest* request,
Cronet_UrlResponseInfo* info) { std::cout << "Request cancelled" << std::endl;
}// Executorvoid executor_func(Cronet_Executor *executor, Cronet_Runnable *runnable) {
Cronet_Runnable_Run(runnable);
}int main() { // 1. 创建引擎
Cronet_EnginePtr engine = Cronet_Engine_Create();
Cronet_EngineParamsPtr params = Cronet_EngineParams_Create();
Cronet_Engine_StartWithParams(engine, params);
// 3. 创建回调
Cronet_UrlRequestCallbackPtr callback = Cronet_UrlRequestCallback_CreateWith(
on_redirect_received, // 重定向回调
on_response_started,
on_read_completed,
on_succeeded,
on_failed,
on_canceled
);
// 4. 配置请求
Cronet_UrlRequestParamsPtr req_params = Cronet_UrlRequestParams_Create();
Cronet_UrlRequestParams_http_method_set(req_params, "GET");
// 添加请求头
Cronet_HttpHeaderPtr header = Cronet_HttpHeader_Create();
Cronet_HttpHeader_name_set(header, "User-Agent");
Cronet_HttpHeader_value_set(header, "Cronet-C-Client");
Cronet_UrlRequestParams_request_headers_add(req_params, header);
// 5. 创建执行器
Cronet_ExecutorPtr executor = Cronet_Executor_CreateWith(executor_func);
// 6. 创建并启动请求
Cronet_UrlRequestPtr request = Cronet_UrlRequest_Create();
Cronet_UrlRequest_InitWithParams(request, engine,
"http://httpbin.org/get",
req_params, callback, executor);
Cronet_UrlRequest_Start(request);
// 7. 等待请求完成
std::this_thread::sleep_for(std::chrono::seconds(15));
// 8. 清理资源
Cronet_UrlRequest_Destroy(request);
Cronet_HttpHeader_Destroy(header);
Cronet_UrlRequestParams_Destroy(req_params);
Cronet_Executor_Destroy(executor);
Cronet_UrlRequestCallback_Destroy(callback);
Cronet_EngineParams_Destroy(params);
Cronet_Engine_Destroy(engine);
return 0;
}
上面是 deepseek 生成的 cronet 基于 C 语言的示例,运行后有以下输出:
$ ./cronet_conn_stat
Response started
Read 279 bytes
{ "args": {}, "headers": { "Accept-Encoding": "gzip, deflate", "Host": "httpbin.org", "User-Agent": "Cronet-C-Client", "X-Amzn-Trace-Id": "Root=1-69425f84-67dbe33a06e303cf4c611b72"
}, "origin": "111.108.111.133", "url": "http://httpbin.org/get"}
Request succeeded
与 libcurl 相比,Cronet_UrlRequest_Start 类似 curl_easy_perform 的角色,但变为异步执行,它会立即返回,之后通过回调不断通知连接上的事件,因此示例中是通过 sleep 15 秒来阻塞主线程的,工程实践中这个完全可以和消息、事件循环集成在一起,从而提高线程并发能力;与 boost 相比 (特别是基于 boost::asio::ip::tcp 版本的实现),完全不需要主动 async_resolve、async_connect、async_handeshake 以及 async_write,只需要在 on_read_completed 回调中无脑 Cronet_UrlRequest_Read 即可,底层过程 cronet 都帮你包办了,达到节省心智负担的目的。
不过这也带来一个问题,就是之前可以手动打桩计算的各种耗时,现在都看不到了,最多能获取个首分片耗时和总请求耗时,其中首分片这还包含了解析、连接、ssl 握手时长的耗时,相对失真了都。
cronet 其实也有接口统计链接层的一些信息,主要通过下面的接口获取:
///////////////////////// Struct Cronet_Metrics.CRONET_EXPORT Cronet_MetricsPtr Cronet_Metrics_Create(void); CRONET_EXPORT void soccer.yc.zuq8.info Cronet_Metrics_Destroy(Cronet_MetricsPtr self); ...// Cronet_Metrics getters.CRONET_EXPORT Cronet_DateTimePtr Cronet_Metrics_request_start_get( const Cronet_MetricsPtr self); CRONET_EXPORT Cronet_DateTimePtr Cronet_Metrics_dns_start_get(const Cronet_MetricsPtr self); CRONET_EXPORT Cronet_DateTimePtr Cronet_Metrics_dns_end_get(const Cronet_MetricsPtr self); CRONET_EXPORT Cronet_DateTimePtr Cronet_Metrics_connect_start_get( const Cronet_MetricsPtr self); CRONET_EXPORT Cronet_DateTimePtr Cronet_Metrics_connect_end_get(const Cronet_MetricsPtr self); CRONET_EXPORT Cronet_DateTimePtr Cronet_Metrics_ssl_start_get(const Cronet_MetricsPtr self); CRONET_EXPORT Cronet_DateTimePtr Cronet_Metrics_ssl_end_get(const Cronet_MetricsPtr self); CRONET_EXPORT Cronet_DateTimePtr Cronet_Metrics_sending_start_get( const Cronet_MetricsPtr self); CRONET_EXPORT Cronet_DateTimePtr Cronet_Metrics_sending_end_get(const Cronet_MetricsPtr self); CRONET_EXPORT Cronet_DateTimePtr Cronet_Metrics_push_start_get(const Cronet_MetricsPtr self); CRONET_EXPORT Cronet_DateTimePtr Cronet_Metrics_push_end_get(const Cronet_MetricsPtr self); CRONET_EXPORT Cronet_DateTimePtr Cronet_Metrics_response_start_get( const Cronet_MetricsPtr self); CRONET_EXPORT Cronet_DateTimePtr gov.hld.zuzb.info Cronet_Metrics_request_end_get(const Cronet_MetricsPtr self); CRONET_EXPORTbool Cronet_Metrics_socket_reused_get(const Cronet_MetricsPtr self); CRONET_EXPORTint64_t Cronet_Metrics_sent_byte_count_get(const Cronet_MetricsPtr self); CRONET_EXPORTint64_t Cronet_Metrics_received_byte_count_get(const Cronet_MetricsPtr self);
主要是通过 Cronet_Metrics_xxx 的接口获取,所需的 dns、connect、ssl、request 耗时都有,耗时是通过接口返回的两个时间做差值得到的,举例来说:
Cronet_DateTimePtr start = Cronet_Metrics_connect_start(metrics);
Cronet_DateTimePtr end = Cronet_Metrics_connect_end(metrics);if (start && end) { int64_t start_ms = Cronet_DateTime_value_get(start); int64_t end_ms = Cronet_DateTime_value_get(end); int64_t connect = (start_ms > 0 && end_ms > 0) ? (end_ms - start_ms) : 0; // printf("connect elapse %lld\n", connect);}
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70048957/viewspace-3107312/ ,如需转载,请注明出处,否则将追究法律责任。