注册

详解MongoDB的begin_request()函数:开始一个新的请求

MongoDB中的begin_request()函数

begin_request() 是 MongoDB 中的 C 库的一个函数,主要作用是在操作 MongoDB 数据库时生成或初始化一个请求,用于执行请求并获取相应的响应结果。

该函数是 MongoDB C 库中的一个请求级别的回调函数,它会在发起任何请求之前被调用,并可以对即将发生的请求进行修改或拦截,并在收到回复时执行必要的清理操作。

使用方法

函数原型: void (*begin_request)(void *);

  • 参数:void类型的指针,可以指向任意类型的数据;
  • 返回值:void,无返回值。

在 MongoDB C 库中,使用 begin_request() 函数主要是通过在创建 MongoDB 数据库连接时设置回调函数,例如:

mongoc_client_t *client = mongoc_client_new("mongodb://127.0.0.1:27017");
mongoc_client_set_apm_callbacks(client, 
                                (mongoc_apm_callbacks_t *) &callbacks,NULL);

当该连接使用时,如执行查询、写入等操作,将会调用设置的回调函数,进而调用 begin_request() 函数。

在 begin_request() 函数内,可以执行一系列的操作。例如,可以记录当前请求相关信息,如请求开始时间、请求 ID,还可以执行权限检查、统计分析等。

static void request_started(const mongoc_apm_command_started_t *event) {
    bson_iter_t iter;
    bool r;

    mongoc_log(MONGOC_LOG_INFO, "request_id=%d began %s",
            _request_counter++, event->command_name);

    r = mongoc_apm_command_started_get_request_id(event, &iter);
    if (r) {
        mongoc_log(MONGOC_LOG_INFO, "request_id=%d request_id=%"BSON_PRId64,
                _request_counter++, bson_iter_int64(&iter));
    }
    //权限检查、统计分析等代码...
}

示例

以下是两个关于 begin_request() 函数的使用示例:

示例一:判断 MongoDB 查询语句中是否包含敏感关键词

简要说明:

在数据库中搜索和查询过程中,为了确保数据的安全和信息的保密性,通常采取了一些限制和保护措施。比如,查询语句中不能包含特定的敏感关键词。这些关键词通常与一些主题、事件、组织、人物等相关联。如果查询语句包含这些关键词,查询操作将被拒绝,防止数据泄漏。这个示例是通过 begin_request() 函数来实现查询关键词的判断。

完整代码:

static void begin_request_callback (void* context) {
    bson_t* query = (bson_t*)context;

    bson_iter_t iter;
    bson_iter_init(&iter, query);

    while (bson_iter_next(&iter)) {
        if (BSON_ITER_HOLDS_UTF8(&iter)) {
            char* str = bson_iter_dup_utf8(&iter, NULL);
            if (strstr(str, "敏感关键词") != NULL) {
                fprintf(stderr, "query contains sensitive keyword\n");
                abort(); // 这里可以进行拒绝操作或者终止请求的操作。
            }
            bson_free(str);
        }
    }
}

mongoc_client_t *client = mongoc_client_new(uri);
mongoc_apm_callbacks_t *callbacks = mongoc_apm_callbacks_new();
mongoc_apm_set_callbacks(callbacks, begin_request_callback, NULL, ...);
mongoc_client_set_apm_callbacks(client, callbacks, NULL);

示例二:记录 MongoDB 查询请求的执行时间

简要说明:

在 MongoDB 数据库系统中,通常需要统计每个查询语句的执行时间,并进行对比和评估。对于耗时超过阈值的查询操作,需要进行优化。查看每个请求的执行时间,可以帮助我们更好地了解查询性能,从而进一步优化 MongoDB 数据库系统。下面是一个使用 begin_request() 函数来记录请求执行时间的示例。

完整代码:

mongoc_apm_callbacks_t* apm_callbacks = NULL;
apm_callbacks = mongoc_apm_callbacks_new ();

static void begin_request (const mongoc_apm_command_started_t *event)
{
    // 纪录请求开始时间
    my_request_t *request = my_request_data_new ();
    request->begin_micro = bson_get_monotonic_time ();
    bson_oid_t oid;
    bson_oid_init_from_string(&oid, test_framework_get_tid());
    bson_oid_to_string(&oid, request->request_id_string);
    mongoc_apm_command_started_get_command(event, &request->command);
    mongoc_apm_command_started_get_command_name(event, &request->command_name);
    mongoc_apm_command_started_get_request_id(event, &request->request_id);
    mongoc_apm_command_started_set_duration (event, request->begin_micro, 0);
    // 添加记录到请求列表
    my_request_list_insert(request);
}

static void end_request (const mongoc_apm_command_succeeded_t *event)
{ 
    my_request_t *request = my_request_list_find(event);
    if (request) {
        struct timeval tv;
        gettimeofday(&tv, NULL);
        request->elapsed_micro = bson_get_monotonic_time () - request->begin_micro;
        request->end_micro = (int64_t)(tv.tv_sec) * (1000 * 1000) + (int64_t)(tv.tv_usec);
        my_request_list_erase(request);
        // 记录时间信息
        add_process_time(request->command_name, request->command_typeString, request->elapsed_micro, request->end_micro, request->request_id_string);
        my_request_free(request);   
    }
}

mongoc_apm_set_command_started_cb(apm_callbacks, _apm_command_started);
mongoc_apm_set_command_succeeded_cb(apm_callbacks, _apm_command_succeeded);
mongoc_client_set_apm_callbacks(client, apm_callbacks, NULL);

结论

总之,begin_request() 函数是 MongoDB C 库的一个重要组成部分,可以在查询、更新等操作中增加一些额外的操作和控制,从而帮助进一步优化 MongoDB 数据库性能。