ITPub博客

首页 > 人工智能 > 机器学习 > 基于 cronet 的单链接性能信息收集

基于 cronet 的单链接性能信息收集

投稿 机器学习 作者:ecclw459 时间:2026-01-07 19:31:35 0 删除 编辑

早先的基于 boost 的版本这些都很好统计,后来该产品底层网络库换成 cronet 就不好统计了,我的工作就是基于 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 对链接性能信息的支持

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/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2026-01-07

  • 博文量
    108
  • 访问量
    102111