FreeSWITCH的limit功能问题汇总

概述

FreeSWITCH的limit功能很好用,但是fs1.6版本中通过hiredis模块实现的limit有不少bug存在。

环境

CentOS 7.9

FreeSWITCH 1.6.20

问题

limit通过mod_hiredis模块实现并发限制的bug。

1,max=-1时,limit逻辑是按照0来实现的

2,hiredis,redis的并发数据为负值时,并发到0时,limit返回失败,呼叫失败

3,hiredis,redis连接中断,limit返回失败,呼叫失败

4,hiredis主备切换时,并发数据有概率为负值

5,线路方对一通呼叫同时返回bye+486消息,挂机回调事件会对limit并发数据decr俩次,引出负值

修复代码

修改mod_hiredis.c文件的"SWITCH_LIMIT_INCR(hiredis_limit_incr)"函数接口如下。

复制代码
//modify by zr 20250613, for redis reps and max value
    count = atoll(response ? response : "");

    if (count > 0)
    {
        limit_pvt = switch_core_alloc(session_pool, sizeof(hiredis_limit_pvt_t));
        limit_pvt->next = switch_channel_get_private(channel, "hiredis_limit_pvt");
        limit_pvt->realm = switch_core_strdup(session_pool, realm);
        limit_pvt->resource = switch_core_strdup(session_pool, resource);
        limit_pvt->limit_key = switch_core_strdup(session_pool, limit_key);
        limit_pvt->inc = 1;
        limit_pvt->interval = interval;
        switch_channel_set_private(channel, "hiredis_limit_pvt", limit_pvt);
    }

    if (!interval && max >= 0 && count > max ) {
        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "%s is already at max value (%d)\n", limit_key , max);
        switch_safe_free(hashkey);
        switch_safe_free(response);
        hashkey = switch_mprintf("decr %s", limit_key);
        if ( (status = hiredis_profile_execute_sync(profile, hashkey, &response, session)) != SWITCH_STATUS_SUCCESS ) {
            if ( status == SWITCH_STATUS_SOCKERR && profile->ignore_connect_fail ) {
                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "hiredis: profile[%s] connection error executing [%s] with limit already reached\n", realm, hashkey);
                switch_goto_status(SWITCH_STATUS_SUCCESS, done); // increment has been succesful but decrement have failed
            }
        }
    }

    // if ( !count || count > max ) {
    if ( max >= 0 && count > max ) {
        switch_goto_status(SWITCH_STATUS_GENERR, done);
    }

总结

修改后的hiredis重新编译安装后,问题解决。

空空如常

求真得真