前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >FreeSWITCH TDengine模块

FreeSWITCH TDengine模块

作者头像
Seven Du
发布2022-03-31 09:34:14
1K0
发布2022-03-31 09:34:14
举报

FreeSWITCH TDengine模块,用于存储话单,日志等。

FreeSWITCH是一个开源、高性能的多协议的媒体引擎和通信平台。TDengine是一个开源、高性能、分布式,支持SQL的时序数据库。

1.1. 背景

作为开源爱好者,最初看到TDengine,心里就有些痒痒。简单试用后,更是由衷地喜欢。FreeSWITCH的话单、日志等,最适合使用时序数据库存储。后来,混进了TDengine的微信群交流,陶总(Jeff Tao)也明确说运营商和话单也是他们明确支持的方向。但琐事繁忙我却一直没有动手,不过却一直关注TDengine的发展。

期间也分析过TDengine,即使有一万种好也必然有几处不好。它有它适用的场景,从关系数据库世界来的人就得换脑子去理解它。比如用TDengine写话单,其实我一直没有想明白,所以也一直没有动手。

再后来,一次偶然的机会在深圳一次开源大会上遇到陶总,我们躲在嘈杂的晚会大厅一角愣是聊起了TDengine,就话单这个问题做了深入的探讨。

再再后来,原融云杨攀也加入了TDengine,就有了更多交流和探讨,我也终于下定决心写一个开源的FreeSWITCH TDengine模块。

关于TDengine,我也是小白,希望跟大家共同学习。

1.2. 设计

1.2.1. 话单

在此,我们先讨论话单。对TDengine不了解的可以先阅读TDengine的模型相关文档。

https://www.taosdata.com/docs/cn/v2.0/architecture#model

话单具有时序数据库的特点:数据量大、总体上按时间有序、只读。

TDengine是一个时序数据库,因此所有数据必须有一个时间戳,相同的时间戳是无法插入的。这跟关系数据库天然的不同。在关系数据库中,话单使用一张表,直接将数据插入就OK了。但在TDengine中,可能会并行插入很多话单,时间戳就有可能重复,导致无法插入。解决办法是将话单分拆。但是,怎么拆?

我们先来看一下一张典型的话单:

  • uuid:通话的唯一ID,使用UUID格式,也可以是任意字符串(在应用中可以强制使用UUID字符串)。
  • caller_id_name:字符串,主叫名称
  • caller_id_number:字符串,主叫号码
  • dest_number:字符串,被叫号码
  • username:经过鉴权的用户名
  • start_time:时间戳,通话开始时间
  • answer_time:时间戳,应答时间,可能为空(电话可能不应答)
  • end_time:时间戳,结束时间
  • direction:字符串,来话还是去话(inbound|outbound),参照物是FreeSWITCH
  • duration:整数,通话时长,等于end_time - start_time
  • billsec:整数,计费时长,等于answer_time - start_time,如果无应答则为0
  • cause:字符串,挂机原因
  • 其它字符串字段可以自定义

所有时间戳均可达微秒级(1/10^6),但一般秒级就够了。FreeSWITCH为了提高性能,内部有自己的时钟,分辨率通常在20毫秒。

话单数据的特点:

  • 总体有序,挂机时写话单,即end_time >= start_time(暂不考虑时钟飘移)。
  • 整数和时间戳字段相对较少,更多的是通话相关的字符串型数据(主、被叫号码和其它属性)
  • 获取一张话单的操作相对较少,更多的是统计一段时间内的通话量,但在查问题时通话会查看一张话单的所有属性
  • 同一用户名或主、被叫号码可能同时会有多个通话(FreeSWITCH并不限制同一主、被叫的并发通话,而且,在某些场景中可能很常见,如同振,即来话后,多个终端同时响铃)
  • 本地用户(本地终端,即用于通话的账号)通常是有限的
  • FreeSWITCH作为汇接局或关口局使用时,号码可能是无限的(即FreeSWITCH只做通话转发,主、被叫号码都不在本机管辖范围内)

理解FreeSWITCH:

理解了话单,我们还需要理解一下FreeSWITCH。FreeSWITCH是一个B2BUA,常用于转发呼叫,典型的有以下几种模式:

终端呼叫FreeSWITCH,FreeSWITCH放音,将终端加入会议等。每一通电话产生一张话单。如下图:

终端 --------> FreeSWITCH

终端A呼FreeSWITCH,FreeSWITCH将电话转发到终端B,产生两张话单(或一张合并后的话单)。如下图:

终端A --------> FreeSWITCH ---------> 终端B

上面,我们认为所有的终端都是自己业务范围内的,都有自己的ID。下面,通过运营商的呼叫,运营商侧的号码不在本地管辖范围内,只能通过运营商中继号或IP地址进行区分计费。

代码语言:javascript
复制
终端A  --> FreeSWITCH --> 电信运营商T --> 手机号C

终端A  <-- FreeSWITCH <-- 电信运营商T <-- 手机号C

代码语言:javascript
复制
FreeSWITCH <-- 电信运营商T1 <-- 手机号C
   \-------------> 电信运营商T2 --> 手机号D

经过上述分析,我们有如下拆分方案:

  • 本地终端,每个终端一张表,有一个超级表
  • A呼B的情况,计两张话单,分别计入A/B两张表
  • A呼C,计入A表,运营商表T表
  • C呼A,计入A表,运营商表T表
  • C呼D,计入T1表,T2表

第一列时间戳使用自然时间NOW,而不使用话单中的时间戳。

本方案可以解决以下问题:

  • 针对不同的本地用户计费

本方案有以下遗留问题:

  • 同时有同号码的并发呼叫时,T表中时间戳可能重复
  • 同终端并发有多个呼叫时,A/B表也可能有重复,进一步拆分?

由于终端通话话单不需要更细的拆分粒度,但是TDengine底层需要,TDengine有没有方法解决时间戳冲突的插入问题(不能丢话单!)。

我们将与TDengine工程师团队深入交流解决这些问题。

1.2.2. 日志

TDengine是否适合存储应用程序日志?典型的,日志是一个时间戳加上一段文本。如何保证并发写入时间戳不重复?

1.3. 开发计划

不管上述问题是否解决,我相信TDengine在FreeSWITCH中一定有它的用处。我们先将数据写写入,再研究遗留问题解决方案。

  • 写模块
  • 建表
  • 写话单
  • 写日志
  • 使用C语言写
  • 使用Go语言写

本项目是开源项目,使用与FreeSWITCH一致的MPL1.1开源许可证,欢迎加入我们一起玩。你将会学到:

  • TDengine
  • 如何写一步一步写FreeSWITCH模块
  • 如何取话单
  • 如何编译以及解决问题
  • 如何做一个开源项目
  • 如何向开源项目做贡献
  • 如何连接两个优秀的开源项目
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-03-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FreeSWITCH中文社区 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.1. 背景
  • 1.2. 设计
    • 1.2.1. 话单
      • 1.2.2. 日志
      • 1.3. 开发计划
      相关产品与服务
      数据库
      云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档