开源软交换系统:freeSwitch架构设计分析
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
mod_sofia.so)来实现, 每个 mod 在被加载后可以提供 API 或者 APP 进一步增强 FS 的功能。 Core 和 mod 之间通过 mod 调用 core 的 API 实现交互。下图 1 是 FS 的基本逻辑视图。
图 1. FS 逻辑视图 三 FS 开发视图 (Development View) 如上所述, fs 分为 core 和外围 mod 模块。 Core 大部分功能依赖于第三方的库所提供的功能, 特别是 APR 库。 FS 在代码开发上,把整个软件分为 3 大部分: 1. Freeswitch 启动模块,是由 freeswitch.c 来编译生成; 2. Freeswitch core 模块, 由组成 fs core 功能的各源代码块组成, core 最后被编译为静态库, 和启动模块一起链接为可执行程序 3. 可动态加载的外围 mod 模块, 这些是动态库, 可以在 fs 启动运行后动态地加载和卸载。 如下图 2 是 fs 的开发视图。
4.
来挂接任务到 core 中, 挂接成功后, core 会把挂接的任务加入到 core 的 globals.task_list 链表中, 然后在该线程中被轮询执行 当各个动态库模块被加载后, 各 mod 也可以有自己的独立的线程, 那个就属于业务范畴了, 不属于 core 管理的范畴,本文不做讨论。 图 3 是 fs 的系统进程并发视图(不含各 mod 的任务)
3. 事件的产生 可以调用 core API switch_event_create(…)来产生系统定义的事件, 该 API 将生成的事件压入 到系统的事件队列中 EVENT_QUEUE[0…3]; 如在系统进程视图中描述的那三个 EVENT 队
列。 4. 事件的获取及分发线程 switch_event_thread(…) Fs 定义了 3 个 EVENT 队列,EVENT_QUEUE,分别对应三个线程:
2. 事件的注册绑定与去绑定 可以调用 core 的 API: switch_event_bind_removable(const char *id, switch_event_types_t event, const char *subclass_name, switch_event_callback_t callback, void *user_data, switch_event_node_t **node) 来注册系统事件和对应的 event callback 的关联,任何模块都可 以调用该模块来注册系统定义的事件。 去绑定可以调用 core API:
5. 事件的处理 switch_event_dispatch_thread(…)
该线程从队列 EVENT_DISPATCH_QUEUE[]中取得事件(其实就是消息),该事件是在 4 的线程中转过来的; 通过调用 core API switch_queue_pop(…)取得事件,最后调用 core API switch_event_deliver(event) 找到该事件对应的 event callback,从而最终处理该事件; 图 5 是 fs 的事件处理流程:
软交换 FreeSwitch 架构设计分析(v1.0.6)
更多相关内容请参见:IT丫挨踢: 关怀IT人内心,关注IT人 职业发展的第一门户
可任意转载/引用,请说明出处:IT 丫挨踢网: 一 引言: freeSwitch 是一款开源的 softswitch,其号称是世界上第一款跨平台的软交换系统,呵呵,这 个有点夸大了, 其实业界巨头比如爱立信/诺基亚/华为/中兴的软交换系统肯定是支持跨平台 的,不过他们的系统大都运行在 Unix/Linux 系统上居多,不过作为一个小团队开发出来这 款软件,也已经很不错了。 本文是作者业余时间分析的结果,目的是希望抛个砖头,和大家互通有无,加深对其整个架 构极其核心的设计理解, 这样当大家在做业务侧时, 如果能够对其整个架构的设计有所了解 的话,那么在做业务时可以会更好地驾轻就熟地设计业务系统,甚至去尝试扩展新的功能。 希望和各位共同讨论,理解不到之处,也请各位指出,共同提高。 开源软交换系统freeSwitch: . 本文将以 RUP 的 4+1 视图来描述 freeSwitch 的架构设计。以 freeswitch 1.0.6 版本为基础。 二 FS 逻辑视图 (Logical View) FS 在总体逻辑视图设计上大体上可分为核心 core 和外围两大块,外围就是各个可以动态加 载/卸载的动态库,比如 mod_sofia/mod_socket 等等。 其 core 和外围之间通过 API 通信, 因为二者运行在同一个地址空间, 所以可以直接通过 API 的调用方式进行通信。 Core 的主要功能: 1. Core 利用了 APR 库来完成很多的工作(APR 库是 Apache Portable Runtime Library,是 Apache 提供的一个跨平台的 C 库) ,完成内存管理/文件管理/线程管理/常用算法和数据 结构等等,让程序员从底层工作中解脱出来,类似于 C++的 STL,大家也可以在自己的 项目中利用 ARP 库, 可以大大节省工作, 其实类似的还有一个比较出名的 C 库: Glib; (我 比较奇怪,fs 好像没看到定时器管理机制,比如应用程序要启动定时器,好像 core 没有 提供类似机制) 2. Event 事件的管理机制(其实就是消息通信机制)及对应的任务 3. 动态模块库(mod)的加载/卸载管理 4. 呼叫控制及 session 的管理 5. 日志管理/时间管理/ NAT/config 管理/数据库存储管理/基本编解码能力等基本能力 6. 内核任务调度管理 (比如 heatbeat 任务) 7. 其他库所提供的机制,为外围模块提供基本能力,比如基本的算法和数据结构等 外围模块(Mod_xxx): 可加载和卸载的外围动态库模块是 fs 设计上的一个特色,fs 的功能扩展主要是依靠外围动 态模块的增加来实现,core 提供基本的管理功能(内存/线程/文件/事件等) ,外围模块则提 供 对 应 的 可 扩 展 的 业 务 功 能 , 比 如 SIP 模 块 就 是 通 过 加 载 mod_sofia.dll(linux 下 是
switch_event_thread(…),他们分别调用 core API switch_queue_pop(…)读取对应的事件队列中的事件: EVENT_QUEUE[0…3]; 然后将事件通过调用 core API switch_event_fire()及 switch_queue_trypush(…)再压入 fs 系统队列 EVENT_DISPATCH_QUEUE[index]队列中,等待另外的线程去真正处理对应的事件
图 5 FS 事件的处理流程 了解了上述原理,那么我们自己也可以定义事件。
七 如何扩展 fs core ?
如何把自己的代码扩展到 fs 的 core 中?目前看有两种方式(个人意见,大家可以补充) 1. 直接在 core 中加入自己的代码 就如在开发视图中所描述的,你自己可以把自己的代码直接加入到 core 的源程序中,和 core 的其他部分 一起生成静态库,然后在.h 中把自己的接口公布出去即可 2. 通过把自己的代码写成任务的形式 如在进程视图中所描述的,可以通过调用 core API switch_scheduler_add_task(…)将自己的代码作为 core 的任务的一部分,由 core 线程进行调度,从而完成把自己的代码变成 core 的一部分。
该线程允许独立的线程任务挂接到内核中,由内核去轮询调度,在目前的实现中,该内核任务只有一 个:void send_heartbeat(),该任务不断地生成 EVENT(消息)SWITCH_EVENT_HEARTBEAT,以表示系统 在处于活动状态; 但可以自己增加任务挂接到内核中, 调用 core API switch_scheduler_add_task(…)
八 其他
1. 我认为 fs 在呼叫控制以及线程处理上可以进一步优化,比如我个人不太赞同当前 fs 的实现,对于每
个 sip 呼叫,都会产生两个线程,分别对应 caller 和 callee,目前的 v1.0.6 支持 1000 个 sessions,也 就是说,单 1000 个呼叫就要产生 2000 个线程,这个我个人认为开销有点大。 2. 我认为 fs 的消息通信机制有待于优化和加强,如前所述,我没有看到事件(消息)的发送及接收标志 (也可能是我自己没搞清楚,大家告诉下),要清楚事件的产生者和接收者是谁。 3. 没看到定时器机制, 比如业务程序里, 如何生成一个 20 秒的定时器, 然后超时后调用对应的回调函数? 4. dial plan 的描述,xml 方式,我个人认为太难维护了,如果 dial plan 有成千上万项,采用目前的这 种正则表达式的方式来维护,我觉得实在太难了,稍微不注意就会出错。 当然可能我理解得并不太对,如果有谁了解的清楚,一并告知 ! 5. 后续再补充下 mod 模块的编写,分析下如何自己写一个可以被 fs 加载的动态库模块。
SWITCH_DECLARE(switch_status_t) switch_event_unbind(switch_event_node_t **node); SWITCH_DECLARE(switch_status_t) callback); switch_event_unbind_callback(switch_event_callback_t
Freeswitch.exe
Linking to ee
静态库 比如 mod_sofia/mod_socket etc动态库
Switch.c
Library
图 2 fs 开发视图 四 FS 进程视图 (Process View) 实际上,FS 设计为单节点/单进程的系统,非分布式应用。其只有一个进程 freeswitch.exe (windows 下);但其 core 中有几个比较重要的独立的线程任务: 1. 主线程: 1) 该线程负责启动整个系统, 初始化内核以及加载各个 module; (执行各 module 的 load function(…)) 2) 负责通过命令行窗口和维护人员交互,接收维护人员的命令并执行(包括退出系统 操作命令) 2. 事件获取及分发线程 switch_event_thread(…) 该线程总共有 3 个,分别负责不断地从 3 个对应的事件队列中获取事件,然后发送给最 终处理事件的线程消息队列 EVENT_DISPATCH_QUEUE[],后面会详细讲解 fs 的事件 处理机制
六 事件机制 Fs 的事件机制其实就是消息通讯的一种机制;在 fs 中,通过事先定义一系列的 EVENT 以 及对应的事件处理函数(event callback function), 任何模块都可以通过 switch_create_event(…) 来生成事先定义的事件,然后通过在进程视图中所描述的各个线程任务,来获取/分析以及 处理这些事件。 在 fs 中,没有消息通信,消息通讯,其实就是通过 EVENT 机制来实现的。 (个人认为 fs 的 事件机制并不太完善,在生成 EVENT 时,并不标识该事件来自何方以及发往何方,只是生 成后扔进消息队列,其实事件或者消息是有状态机的,同一事件,对不同的发送者/接收者 以及在不同的状态下,处理方式并不相同,但在 fs 里,看不出这些差异。是不是我没有看 清楚?) 1. 事件的定义: Fs 在 switch_types.h 中定义了系统的事件 EVENTS: (下图是其中的一部分)
3.
事件处理线程 switch_event_dispatch_thread(…) 该线程获取分析从线程 2 中发送过来的事件,然后真正去处理所发生的事件。该事件在 EVENT_DISPATCH_QUEUE[]队列中 Core 任务调度线程 switch_scheduler_task_thread(…)
图 3 fs core 进程视图 五 部署视图 (Deployment View)
Fs 的部署视图很简单,因为是单节点单进程的应用,因此每个节点只有一个 fs 进程在运行 (理论上 当然一个节点可以运行多个 fs 进程,但本质上这些运行在同一节点的 fs 进程之间没有任何关系)。
图 4 Fs 部署视图