FreeSwitch中mod_dptools和mod_easyroute两个模块及应用场景
- 软件开发
- 2025-08-26 17:18:01

FreeSWITCH 中的 mod_dptools 和 mod_easyroute 是两个功能不同的模块,分别服务于呼叫控制和动态路由场景。以下是详细介绍:
mod_dptools 功能概述 mod_dptools(Dialplan Tools)是 FreeSWITCH 最核心的模块之一,提供了丰富的 Application(App) 和工具,用于在拨号计划(Dialplan)中实现呼叫控制逻辑14。主要功能包括: 基础呼叫操作:如 answer(接听)、bridge(桥接)、hangup(挂断)等。媒体处理:如 playback(播放音频)、record(录音)、set_audio_level(调节音量)。DTMF 交互:通过 read、capture 等应用捕获用户按键输入^2。资源限制:通过 limit 应用限制并发呼叫数(Capacity)或每秒呼叫数(CPS)^5。虚拟端点:提供 user 端点,简化呼叫字符串配置(如 user/1000 映射到 SIP 地址)^1。应用场景
IVR 系统:结合 playback 和 read 实现语音菜单交互。呼叫中心:通过 bridge 转接呼叫,利用 limit 控制并发量。会议系统:管理多方通话的媒体流和权限。资源限制:限制特定 IP 或线路的呼叫频率,防止过载^5。mod_easyroute 功能概述 mod_easyroute 是一个轻量级的 动态路由引擎,通过数据库查询实现基于 DID(直接拨入号码)的路由决策69。核心特性包括: 数据库驱动:从数据库(如 MySQL、PostgreSQL)中查询路由规则。灵活路由:根据来电号码动态选择目标(如 SIP 地址、网关)。简化配置:替代复杂的拨号计划逻辑,适合多租户或动态路由需求。
应用场景
多运营商线路:根据 DID 选择成本最优的运营商网关^9。企业分机路由:将不同 DID 映射到内部用户或部门。动态号码分配:结合外部系统实现按需路由(如临时号码池)。对比与协作
互补性:mod_dptools 提供底层呼叫控制能力,而 mod_easyroute 专注于高层路由逻辑。例如,可通过 mod_easyroute 查询数据库确定目标,再通过 mod_dptools 的 bridge 发起呼叫。典型用例: 来电进入后,mod_easyroute 查询数据库获取目标地址。mod_dptools 的 bridge 执行呼叫桥接,并通过 limit 限制并发量59。总结
mod_dptools:是 FreeSWITCH 的“瑞士军刀”,适用于基础呼叫控制、媒体操作和资源管理12^5。mod_easyroute:简化动态路由配置,适合需要灵活 DID 路由的场景69。 两者结合可构建高效、可扩展的 VoIP 系统。在高并发低延迟毫秒级场景下王者组合
在高并发、低延迟场景下,结合 mod_dptools 和 mod_easyroute 实现动态路由的核心思路是:通过 mod_easyroute 快速查询 MySQL 路由表,再通过 mod_dptools 的 bridge 和 limit 实现高效呼叫控制。以下是具体实现方法:
一、模块协作方法
mod_easyroute: 动态查询 MySQL 路由表,根据主叫/被叫号码、时间、地区等条件筛选最优路由。支持主叫号码的完全匹配(=)和前缀匹配(LIKE),被叫前缀的规则匹配。 mod_dptools: 使用 limit 控制并发呼叫量,避免过载。通过 bridge 快速桥接呼叫,减少延迟。二、MySQL 表结构示例 sql CREATE TABLE route_rules ( id INT PRIMARY KEY AUTO_INCREMENT, ip VARCHAR(15) NOT NULL, – 目标服务器 IP port INT NOT NULL, – 目标端口 caller_match_type ENUM(‘exact’, ‘prefix’), – 主叫匹配类型 caller_pattern VARCHAR(32), – 主叫号码(完全匹配或前缀) callee_prefix VARCHAR(16), – 被叫前缀 callee_rewrite_rule VARCHAR(64), – 被叫重写规则(如 ^(\d+)$ → 1\1) outbound_time_start TIME, – 外呼时间范围(起始) outbound_time_end TIME, – 外呼时间范围(结束) region VARCHAR(32), – 外呼地区(如 us-east) priority INT DEFAULT 10, – 路由优先级(数值越小优先级越高) created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP );
三、配置文件示例
MySQL 连接配置(vars.xml) xml
mod_easyroute 路由查询(easyroute.conf.xml) xml SELECT ip, port, callee_rewrite_rule FROM route_rules WHERE (caller_match_type = ‘exact’ AND caller_pattern = ‘ c a l l e r i d n u m b e r ′ ) O R ( c a l l e r m a t c h t y p e = ′ p r e f i x ′ A N D ′ {caller_id_number}') OR (caller_match_type = 'prefix' AND ' calleridnumber′)OR(callermatchtype=′prefix′AND′{caller_id_number}’ LIKE CONCAT(caller_pattern, ‘%’)) AND ‘ d e s t i n a t i o n n u m b e r ′ L I K E C O N C A T ( c a l l e e p r e f i x , ′ A N D T I M E ( N O W ( ) ) B E T W E E N o u t b o u n d t i m e s t a r t A N D o u t b o u n d t i m e e n d A N D r e g i o n = ′ {destination_number}' LIKE CONCAT(callee_prefix, '%') AND TIME(NOW()) BETWEEN outbound_time_start AND outbound_time_end AND region = ' destinationnumber′LIKECONCAT(calleeprefix,′ANDTIME(NOW())BETWEENoutboundtimestartANDoutboundtimeendANDregion=′{region}’ – 假设地区信息通过变量传递 ORDER BY priority ASC LIMIT 1
拨号计划(dialplan.xml) xml
四、优化建议
索引优化: 对 caller_pattern、callee_prefix、region 字段建立复合索引。 缓存路由: 使用 Redis 缓存高频路由规则,减少 MySQL 查询次数17。 连接池配置: 在 mod_db 中启用连接池,避免频繁建立数据库连接。 系统参数调优: 调整 ulimit -n 和 UDP 缓冲区大小,提升并发处理能力13。五、典型场景 外呼系统动态路由:
主叫号码 10123456789 匹配前缀 101,被叫前缀 +86,当前时间在允许范围内。mod_easyroute 查询到目标 IP 10.0.0.5:5060,并应用被叫重写规则。mod_dptools 的 limit 确保并发不超过 1000,bridge 完成低延迟呼叫。通过上述配置,可实现 毫秒级路由决策 + 高并发控制,满足严苛的实时性要求16^7。
easyroute.conf.xml 文件通常位于 FreeSWITCH 的配置目录下的 conf/autoload_configs/ 子目录中^3。完整路径示例如下: /usr/local/freeswitch/conf/autoload_configs/easyroute.conf.xml
说明:
FreeSWITCH 配置结构: FreeSWITCH 的配置文件默认集中在 conf/ 目录下,模块的配置文件(如 mod_easyroute)一般存放在 conf/autoload_configs/ 中^3。模块加载逻辑: FreeSWITCH 在启动时会自动加载 autoload_configs/ 中的模块配置,确保 mod_easyroute 的路由规则生效。验证方法:
通过命令行查看路径: bash 进入 FreeSWITCH 配置目录 cd /usr/local/freeswitch/conf/autoload_configs/ 检查文件是否存在 ls -l easyroute.conf.xml如果未找到文件,可能需要手动创建该配置文件并启用模块。
实现动态控制并发
要实现动态并发限制,需结合 mod_dptools 的 limit 应用与 mod_easyroute 的路由查询功能,并通过 MySQL 动态获取限制值。以下是具体步骤和配置示例:
修改 MySQL 表结构 在 route_rules 表中新增 concurrency_limit 字段: sql ALTER TABLE route_rules ADD COLUMN concurrency_limit INT DEFAULT 1000;
调整 mod_easyroute 查询 更新 easyroute.conf.xml 的 SQL 查询,返回 concurrency_limit 字段: xml SELECT ip, port, callee_rewrite_rule, concurrency_limit FROM route_rules WHERE (caller_match_type = ‘exact’ AND caller_pattern = ‘ c a l l e r i d n u m b e r ′ ) O R ( c a l l e r m a t c h t y p e = ′ p r e f i x ′ A N D ′ {caller_id_number}') OR (caller_match_type = 'prefix' AND ' calleridnumber′)OR(callermatchtype=′prefix′AND′{caller_id_number}’ LIKE CONCAT(caller_pattern, ‘%’)) AND ‘${destination_number}’ LIKE CONCAT(callee_prefix, ‘%’) AND TIME(NOW()) BETWEEN outbound_time_start AND outbound_time_end ORDER BY priority ASC LIMIT 1
动态设置并发限制 在拨号计划中,通过 set 应用将 concurrency_limit 保存为通道变量,并在 limit 中引用: xml
关键点说明
动态变量传递: easyroute_result(concurrency_limit) 从路由查询结果中提取 concurrency_limit 字段^2。expr() 函数用于处理空值,若数据库未返回限制值,则默认使用 1000^2。 高并发优化: 结合文献1的建议,确保系统已调整文件描述符(ulimit -n 65535)和 UDP 缓冲区^1。 路由匹配逻辑: 主叫号码支持完全匹配和前缀匹配,被叫号码支持前缀规则^3。验证方法
数据库写入测试值: sql INSERT INTO route_rules (ip, port, caller_pattern, callee_prefix, concurrency_limit) VALUES (‘10.0.0.5’, 5060, ‘101’, ‘+86’, 500);查看日志: 检查 FreeSWITCH 日志,确认 dynamic_limit 是否正确加载: bash freeswitch -nc -nonat -rp通过上述配置,可实现 基于路由规则的动态并发控制,满足高并发场景的灵活需求23。
场景一 如果将mysql数据表缓存到redis的8号库,动态路由先查询redis,不存在,再查询mysql,依旧不存在,返回404报错,问题一:缓存到redis是键值对该如何配置?问题二:给出添加redis后的配置文件代码
问题一:Redis 键值对配置方法 在 Redis 8 号库中,键值对设计需包含路由规则的核心字段,建议采用以下格式:
键(Key):route:${caller_id_number}:${destination_number} 其中 ${caller_id_number} 为主叫号码,${destination_number} 为被叫号码。若需支持前缀匹配,可扩展为: plaintext route:exact: c a l l e r i d n u m b e r : {caller_id_number}: calleridnumber:{callee_prefix} 完全匹配 route:prefix: c a l l e r p r e f i x : {caller_prefix}: callerprefix:{callee_prefix} 前缀匹配值(Value):存储 JSON 格式的路由信息,包含 ip、port、callee_rewrite_rule 等字段,例如: json { “ip”: “10.0.0.5”, “port”: 5060, “callee_rewrite_rule”: “^\d+$”, “concurrency_limit”: 500 }问题二:添加 Redis 后的配置文件代码
Redis 连接配置(vars.xml) xml
拨号计划(dialplan.xml) xml
Lua 脚本示例(redis_query.lua) lua local caller = argv1 local callee = argv2 local redis = require “redis” local client = redis.connect(os.getenv(“redis_host”), os.getenv(“redis_port”)) client:auth(os.getenv(“redis_password”)) client:select(8) – 选择 8 号库– 尝试完全匹配 local key_exact = “route:exact:” … caller … “:” … callee local result = client:get(key_exact)
– 若未命中,尝试前缀匹配 if not result then local key_prefix = “route:prefix:” … string.sub(caller, 1, 3) … “:” … callee result = client:get(key_prefix) end
if result then session:setVariable(“easyroute_result”, result) session:answer() else session:setVariable(“skip_easyroute”, “false”) – 继续执行后续动作 end
缓存写入脚本(redis_set.lua) lua local caller = argv1 local callee = argv2 local route_data = argv3 local redis = require “redis” local client = redis.connect(os.getenv(“redis_host”), os.getenv(“redis_port”)) client:auth(os.getenv(“redis_password”)) client:select(8)– 根据匹配类型设置键(示例仅存储完全匹配) local key = “route:exact:” … caller … “:” … callee client:setex(key, 3600, route_data) – 缓存 1 小时
关键点说明
键设计:支持完全匹配和前缀匹配,通过不同键前缀区分逻辑67。性能优化:使用 Lua 脚本减少网络往返,结合 setex 设置过期时间避免内存泄漏45。高并发适配:通过 mod_dptools 的 limit 动态控制并发量,确保系统稳定性^2。1456^7
场景二 还要考虑主叫号码/被叫前缀可能没限制,只限制/主叫号码/被叫号码这种情况,请重新分析
在 FreeSWITCH 中处理主叫/被叫号码的灵活限制,需结合 拨号计划动态匹配 和 数据库规则设计,以下是具体方案:
数据库表结构设计 在 route_rules 表中新增限制标识字段,支持独立控制主叫/被叫限制: sql ALTER TABLE route_rules ADD COLUMN caller_restricted BOOLEAN DEFAULT FALSE, ADD COLUMN callee_restricted BOOLEAN DEFAULT FALSE; caller_restricted:TRUE 时启用主叫号码匹配,FALSE 时忽略主叫限制。callee_restricted:TRUE 时启用被叫前缀匹配,FALSE 时忽略被叫限制13。
动态 SQL 查询优化 修改 mod_easyroute 的查询逻辑,支持条件组合: xml SELECT ip, port, concurrency_limit FROM route_rules WHERE (caller_restricted = FALSE OR (caller_match_type = ‘exact’ AND caller_pattern = ‘ c a l l e r i d n u m b e r ′ ) O R ( c a l l e r m a t c h t y p e = ′ p r e f i x ′ A N D ′ {caller_id_number}') OR (caller_match_type = 'prefix' AND ' calleridnumber′)OR(callermatchtype=′prefix′AND′{caller_id_number}’ LIKE CONCAT(caller_pattern, ‘%’))) AND (callee_restricted = FALSE OR ‘${destination_number}’ LIKE CONCAT(callee_prefix, ‘%’)) AND TIME(NOW()) BETWEEN outbound_time_start AND outbound_time_end ORDER BY priority ASC LIMIT 1 逻辑说明: 当 caller_restricted=FALSE 时,跳过主叫匹配条件。当 callee_restricted=FALSE 时,跳过被叫前缀匹配14。
拨号计划动态适配 在 dialplan.xml 中通过变量控制路由逻辑: xml
场景示例 限制类型 caller_restricted callee_restricted 匹配逻辑
仅主叫限制 TRUE FALSE 匹配主叫号码,忽略被叫前缀 仅被叫限制 FALSE TRUE 匹配被叫前缀,忽略主叫号码 双重限制 TRUE TRUE 同时匹配主叫号码和被叫前缀 无限制 FALSE FALSE 匹配所有呼叫
性能优化建议 索引优化:对 caller_restricted 和 callee_restricted 建立复合索引^1。缓存策略:结合 Redis 缓存高频路由规则,减少数据库查询压力13。
通过上述配置,可实现 主叫/被叫独立限制 的灵活路由控制,满足复杂业务场景需求13^4。
给出缓存到redis的键值对情况
在 Redis 中缓存键值对时,需根据业务场景设计键结构和存储格式。以下是典型配置方案:
键(Key)设计层级结构:使用冒号分隔业务标识和参数,例如: route:caller:主叫号码:被叫前缀 或 route:callee:被叫号码^3 示例:route:exact:10086:+86137(主叫 10086,被叫前缀 +86137)
动态组合:根据限制条件动态生成键:
仅主叫限制:route:caller:${caller_id_number}仅被叫限制:route:callee:${destination_number}双重限制:route:exact:${caller_id_number}:${destination_number}^3 值(Value)格式JSON 字符串:存储路由规则详情,例如: json { “ip”: “10.0.0.5”, “port”: 5060, “concurrency_limit”: 500, “callee_rewrite_rule”: “^\+86\d+$” }13
哈希表(Hash):使用 HSET 存储独立字段: bash HSET route:exact:10086:+86137 ip 10.0.0.5 port 5060 limit 500^1
操作示例 python import redis连接 Redis r = redis.Redis(host=‘localhost’, port=6379, db=8)
设置键值对(JSON 格式) route_data = { “ip”: “10.0.0.5”, “port”: 5060, “concurrency_limit”: 500 } r.set(“route:exact:10086:+86137”, json.dumps(route_data))
获取值 result = r.get(“route:exact:10086:+86137”) print(json.loads(result)) 输出路由信息^1
性能优化建议 批量操作:使用 MSET 或 Pipeline 减少网络往返次数^2过期时间:通过 SETEX 设置 TTL 避免内存泄漏^1通过合理设计键结构和存储格式,可高效管理路由规则缓存31。
换一种思路,以ip和端口号为redis的键,主叫号码及被叫前缀和同等规则为一组,以json缓存到redis中,这个方案可行吗
以IP和端口号为Redis键,主叫号码及被叫前缀规则为JSON值的方案可行但需优化。具体分析如下:
方案可行性分析
键设计合理性
使用${ip}:${port}作为键(如10.0.0.5:5060)能唯一标识路由目标服务器14。但需注意:同一IP端口可能对应多组主叫/被叫规则,此时需在值中存储规则集合而非单条规则。值存储方式
JSON格式:适合存储结构化规则数据,例如: json { “rules”: {“caller_prefix”: “10086”, “callee_prefix”: “+86”, “concurrency_limit”: 500}, {“caller_prefix”: “138”, “callee_prefix”: “+1”, “callee_rewrite_rule”: “^\d+$”}
} 通过JSON可灵活扩展字段14。
查询效率
优势:直接通过IP端口定位路由目标,适合反向查询场景(已知目标服务器时获取规则)^4。劣势:若需根据主叫/被叫前缀正向查询IP端口,需遍历所有键,时间复杂度为 O ( n ) O(n) O(n)27。优化建议
复合键设计 结合主叫/被叫前缀生成辅助键,建立双向映射: python 主键:存储规则集合 redis.set(“10.0.0.5:5060”, json.dumps(rules))
辅助键:支持正向查询 redis.hset(“route:caller:10086”, “callee:+86”, “10.0.0.5:5060”) 通过哈希表实现 O ( 1 ) O(1) O(1)复杂度查询27。
缓存更新策略
主动更新:规则变更时同步更新Redis^2。过期时间:对低频规则设置TTL(如SETEX key 3600 value)15。配置示例 python import redis import json
连接Redis r = redis.Redis(host=‘localhost’, port=6379, db=8)
存储规则 rules = {“caller_prefix”: “10086”, “callee_prefix”: “+86”, “limit”: 500}, {“caller_prefix”: “138”, “callee_prefix”: “+1”, “rewrite_rule”: “^\d+$”}
r.set(“10.0.0.5:5060”, json.dumps(rules))
建立辅助索引 for rule in rules: hash_key = f"route:caller:{rule’caller_prefix’}" r.hset(hash_key, f"callee:{rule’callee_prefix’}", “10.0.0.5:5060”)
适用场景
反向路由查询:已知目标服务器IP端口,快速获取关联规则。低频规则管理:结合TTL避免内存浪费25。若需高频正向查询(主叫/被叫→IP端口),建议采用双向键设计或结合关系型数据库78。
在FreeSWITCH中,mod_dptools 和 mod_easyroute 是两个功能不同的模块,分别用于呼叫流程控制和路由管理。以下是它们的详细介绍和应用场景分析:
1. mod_dptools:核心工具模块
mod_dptools 是FreeSWITCH的核心模块之一,默认自动加载。它提供了大量Dialplan应用(Application)和API命令,用于控制呼叫流程、操作通道变量、播放媒体文件等基础功能。
主要功能及常用指令呼叫控制:
answer:应答呼叫(触发媒体协商)。hangup:挂断呼叫,可指定挂机原因(如 hangup NORMAL_CLEARING)。transfer:将呼叫转移到其他分机或拨号方案上下文。媒体操作:
playback:播放音频文件(如 playback /path/to/file.wav)。record_session:录制通话音频(支持多种格式)。speak:使用TTS引擎合成语音。变量操作:
set:设置通道变量(如 set my_var=123)。export:将变量传递到后续的桥接通道。逻辑控制:
bridge:桥接两个终端(如 bridge user/1001)。park:将通话暂存到停车场,等待后续处理。信息获取:
info:打印当前通道的详细信息(调试用途)。 应用场景 IVR系统:通过playback和read实现交互式语音菜单。呼叫转接:使用transfer或bridge将通话转接到其他分机。录音功能:record_session用于合规性录音或语音信箱。动态路由:结合set和条件判断,根据变量调整路由逻辑。调试工具:info或log帮助实时查看通道状态。示例 Dialplan 配置:
<extension name="example"> <condition field="destination_number" expression="^1234$"> <action application="answer"/> <action application="playback" data="/sounds/welcome.wav"/> <action application="bridge" data="user/1001"/> </condition> </extension>2. mod_easyroute:动态路由模块
mod_easyroute 并非FreeSWITCH的官方模块,而是一个第三方或社区贡献模块(需确认具体来源),其设计目的是简化复杂路由规则的配置,通常通过外部数据源(如数据库、API)实现动态路由决策。
核心功能动态路由规则:
基于数据库查询、HTTP API响应或脚本结果动态选择路由目标。支持按主叫号码、被叫号码、时间、地理位置等条件路由。集成外部系统:
与CRM或业务系统对接,实现客户专属路由(如VIP客户直连专属坐席)。负载均衡:
根据坐席忙闲状态或技能组分配呼叫。 应用场景 多租户呼叫中心:根据租户ID从数据库加载不同路由策略。智能路由:基于时间规则路由到夜间服务或节假日语音提示。故障转移:主线路繁忙时自动切换到备用网关。全球化部署:根据呼叫来源国家选择本地网关降低成本。示例配置思路(假设模块存在):
<extension name="dynamic_route"> <condition field="destination_number" expression="^.+$"> <action application="easyroute" data="mysql://user:pass@host/db?query=SELECT route FROM rules WHERE dst=${dst_number}"/> </condition> </extension>模块对比与协作 特性mod_dptoolsmod_easyroute定位基础工具集高级路由扩展配置方式内联Dialplan XML外部数据源(DB/API)灵活性依赖硬编码逻辑动态实时更新规则适用场景简单、静态路由复杂、业务耦合路由
协作示例: 通过mod_easyroute从数据库获取目标号码,再使用mod_dptools的bridge发起呼叫,结合set传递变量记录路由信息。
注意事项
mod_easyroute的可用性: 需确认模块是否存在或是否更名(如社区模块可能命名为mod_lcr、mod_http_routing等)。若无此模块,可通过以下替代方案实现类似功能:
mod_curl:通过HTTP API获取路由信息。mod_lua:编写Lua脚本实现动态逻辑。mod_v8:使用JavaScript定义路由规则。性能考量: 频繁查询外部数据可能增加延迟,建议缓存路由结果或使用内存数据库(如Redis)。
总结 mod_dptools 是FreeSWITCH的“瑞士军刀”,用于实现基础呼叫控制功能。mod_easyroute(或类似模块)适合需要业务逻辑深度集成的动态路由场景,需依赖外部数据源增强灵活性。 开发者可根据需求选择原生工具或扩展模块,或通过脚本语言(Lua/JavaScript)实现自定义路由逻辑。
在高并发,低延迟,毫秒级响应的需求下,给出这两个模块同时使用的方法,场景及配置文件的示例代码,假设路由信息存储在mysql数据表中,表结构有ip,端口号,主叫号码【完全匹配及前缀匹配动态选择】,被叫前缀,被叫前缀还写规则,外呼时间,外呼地区等基础信息,如果存在多个相同ip及端口号的不同主叫/被叫,会在数据表中存储多条记录。
高并发低延迟场景下 mod_dptools 与 mod_easyroute 协同方案
在高并发、低延迟(毫秒级响应)需求下,需通过 动态路由缓存、异步查询 和 高效SQL设计 优化性能。以下是实现方法及配置示例。
1. 数据表设计(MySQL) CREATE TABLE route_rules ( id INT AUTO_INCREMENT PRIMARY KEY, caller_match_type ENUM('exact', 'prefix') NOT NULL, -- 主叫匹配类型:完全匹配或前缀 caller_pattern VARCHAR(32) NOT NULL, -- 主叫号码规则 callee_prefix VARCHAR(16) NOT NULL, -- 被叫号码前缀 ip VARCHAR(15) NOT NULL, -- 目标IP port INT NOT NULL, -- 目标端口 priority INT DEFAULT 10, -- 优先级(数值越小优先级越高) region VARCHAR(32), -- 外呼地区(如CN/US) valid_time TIME, -- 外呼有效时间段(如09:00-18:00) created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- 创建索引加速查询 CREATE INDEX idx_callee_prefix ON route_rules(callee_prefix); CREATE INDEX idx_caller ON route_rules(caller_match_type, caller_pattern); CREATE INDEX idx_region_time ON route_rules(region, valid_time);
2. 配置 mod_easyroute 动态路由
假设 mod_easyroute 支持从MySQL动态查询路由(若需替代方案,可用 mod_lua 或 mod_curl)。
模块配置(easyroute.conf.xml) <configuration name="easyroute.conf"> <routes> <route name="mysql_route" enabled="true" driver="mysql" host="localhost" port="3306" database="freeswitch" user="fs_user" password="password" query="SELECT ip, port, priority FROM route_rules WHERE (caller_match_type = 'exact' AND caller_pattern = '${caller_id_number}') OR (caller_match_type = 'prefix' AND '${caller_id_number}' LIKE CONCAT(caller_pattern, '%')) AND callee_prefix = LEFT('${destination_number}', LENGTH(callee_prefix)) AND region = '${region}' AND (valid_time IS NULL OR CURTIME() BETWEEN valid_time_start AND valid_time_end) ORDER BY priority ASC LIMIT 1"/> </routes> </configuration>3. 高并发优化策略 3.1 路由缓存(Redis)
使用Redis缓存查询结果,减少数据库压力:
键设计:route:${caller}:${callee}:${region}:${time}。过期时间:5秒(平衡实时性与缓存有效性)。 3.2 异步查询通过FreeSWITCH的 异步模式 避免阻塞呼叫线程:
<action application="easyroute_async" data="mysql_route"/> <action application="park"/> 3.3 连接池优化 MySQL连接池:配置 mod_easyroute 使用至少20个连接。查询超时:设置超时时间100ms,超时后触发备用路由。4. 拨号计划(dialplan.xml) <context name="dynamic_routing"> <extension name="dynamic_route"> <condition field="destination_number" expression="^(\d+)$"> <!-- 设置必要变量 --> <action application="set" data="region=CN"/> <!-- 从IP或数据库获取实际地区 --> <!-- 异步查询路由(非阻塞) --> <action application="easyroute_async" data="mysql_route"/> <action application="park"/> <!-- 结果处理(从通道变量读取路由) --> <action application="bridge" data="${if( ${easyroute_status} == success ? sofia/gateway/${easyroute_ip}:${easyroute_port}/${destination_number} : error/NO_ROUTE)}"/> <!-- 失败处理 --> <action application="log" data="WARNING Route failed: ${easyroute_error}"/> <action application="hangup"/> </condition> </extension> </context>
5. 场景示例 场景:国际外呼动态选路 主叫:+8613812345678被叫:+447712345678流程: 根据被叫前缀 +44 匹配英国路由。主叫完全匹配 +8613812345678 或前缀匹配 +86。根据当前时间(如14:00)筛选有效路由。按优先级选择IP:Port组合(如 gw_uk1:5060)。
6. 性能保障措施 数据库优化: 使用内存表(MEMORY引擎)存储热点路由。定期清理过期规则。 FreeSWITCH调优:<!-- settings.conf.xml --> <param name="max-sessions" value="10000"/> <param name="session-per-sec" value="1000"/> <param name="enable-async-park" value="true"/> 监控: 实时监控MySQL查询延迟(Prometheus + Grafana)。告警规则:路由查询超时率 > 1% 或错误率 > 0.5%。
7. 容灾与降级方案 本地缓存文件:当MySQL不可用时,加载静态路由规则。<route name="fallback_route" driver="csv" file="/etc/freeswitch/fallback_routes.csv"/> 默认网关:无路由时转发至默认网关(如SIP中继)。
总结
通过 mod_easyroute 实现动态路由决策,结合 mod_dptools 完成最终呼叫控制,配合缓存、异步查询和数据库优化,可满足高并发低延迟需求。关键点在于减少实时数据库访问、优先内存操作,并通过合理索引提升SQL效率。
FreeSwitch中mod_dptools和mod_easyroute两个模块及应用场景由讯客互联软件开发栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“FreeSwitch中mod_dptools和mod_easyroute两个模块及应用场景”
上一篇
Java基础面试