自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

谈谈1974

空就是空,没有佛系不成猿

  • 博客(282)
  • 收藏
  • 关注

原创 FreeSWITCH 1.10 源码阅读(7)-uuid_bridge 命令原理解析

命令用于将两条腿桥接在一起,以实现双方的通话。命令被下发送到 FreeSWITCH 时,会被。,在核心状态机的调度下,安装在这条腿上的回调函数。函数处理,这个函数将解析命令参数,接着调用。命令的使用实际上有一个时机问题需要格外注意,函数,此处核心是在 b-leg 上执行。函数进行与 a-leg 的媒体交互。将被执行,推动当前腿的状态向。函数会判断当前腿是否为主叫腿,将其写入对端,完成媒体的交换,当 a-leg 状态切换为。当状态发生改变,同理。函数的核心是从当前腿调用。b-leg 状态流转到。

2023-12-21 21:51:09 161 1

原创 FreeSWITCH 使用指北(2)-多段音频顺序播放的设置

前缀不能省略,这个代表的是 FreeSWITCH 中的一个文件管理模块,多个音频文件用!在 FreeSWITCH 中涉及到放音的 APP 有不少,比较典型的是播放录音文件的。这两个 APP 播放录音的功能都依赖于。函数,而该函数可以借助。

2023-10-24 22:00:00 1133 4

原创 OpenSIPS 防扫描处理

OpenSIPS 作为 SIP 注册服务器,通常需要放在公网供公司各地的员工使用,但是这样就会产生外部扫描问题。一般来说外部扫描量不会很大,但是一旦有恶意攻击,裸奔的 OpenSIPS 很容易被击溃,因此一定的防范是必要的。这种方式需要公司的运维或者安全相关部门配合,在 OpenSIPS 侧识别到特定的 IP 较长时间持续性发送请求,则可认为是在进行扫描行为,这种情况下联系网络安全部门在防火墙配置上拒绝该 IP 的网络请求即可。,所以这个场景只要在防火墙上为相应线路商的服务器加白即可防范外部扫描。

2023-10-16 20:00:00 205

原创 OpenSIPS OutOfMemory 崩溃处理

可以看到 OpenSIPS 报出这个异常主要有两个原因,一个是共享内存配置太小,另一个是发生了内存泄漏。OpenSIPS 是开源项目,而笔者项目中使用的又是稳定的发行版本,发生内存泄漏的可能性很小。查阅 OpenSIPS 源码,发现在未配置共享内存参数的情况下,默认分配的共享内存大小只有 32M,推断 OOM 的原因是共享内存太小不够用,那么只要增大共享内存后再次压测即可快速验证。新项目开发结束,为了评估系统容量和性能,在上线前使用 SIPp 模拟客户端对 OpenSIPS 进行了压测。

2023-09-13 17:51:32 200

原创 OpenSIPS 管理接口的对接

是功能完善的开源 SIP 代理服务器,它在支持 SIP 代理的主要功能以外,也为使用者提供了一套。修改配置启动 OpenSIPS 后,直接发送 HTTP 请求即可完成交互,,以下为一个 curl 查看。

2023-09-02 15:21:41 320

原创 RTPEngine 通过 HTTP 获取指标的方式

RTPEngine是常用的媒体代理服务器,通常被集成到 SIP 代理注册服务器中实现媒体传输的功能以减小 SIP 代理服务器的压力,其架构如下图所示。这种使用方式相当于将 RTPEngine 隐藏在 SIP 代理服务器后面,我们虽然可以借助 SIP 代理服务器提供的相关接口有限操作 RTPEngine,但是对 RTPEngine 实例的相关数据缺乏控制。

2023-08-30 15:43:22 868

原创 SIP 协议路由规则详解

SIP 请求必须要经过的 SIP 服务器地址。SIP 协议实际上和 HTTP 类似,都是基于文本、可阅读的应用层协议。,二者的不同之处在于。

2023-08-27 16:20:13 602

原创 OpenSIPS 通话中 UPDATE 请求导致没有声音问题

使用硬话机时,在 SDP 协商完成 SIP 会话已经建立的情况下,使用 FreeSWITCH 的 bridge 命令接通坐席和用户时 FreeSWITCH 发出了一个 UPDATE 请求给到 OpenSIPS。问题的切入点显而易见,硬话机的行为肯定和软电话存在不一致,从而导致问题的发生。在 SIP 应用的开发中,通话一端听不到声音是比较常见的问题。一般来说,没有声音意味着 RTP 传输存在障碍,至此问题原因已经清晰,一个简单快速的解决方案是。追根究底就是网络不通或者端口未开放等原因。,经修改后问题不复现。

2023-08-26 15:06:54 532 4

原创 OpenSIPS 注册终端 30s 自动挂断问题

虽然以上分析的终端 30s 自动挂断问题的根因毫无问题,但在实践过程中导致 ACK 丢失的原因千差万别,非常复杂。在笔者的案例中,开发的应用需要保持坐席侧的会话常驻,当坐席的软电话被挂断时,需要自动的重新拨打坐席分机,以实现常驻的特性。在这个前提下,偶现坐席分机软电话 30s 自动挂断的问题,经过长时间的探索,笔者终于找到了必现步骤。在开发呼叫中心应用时,使用 OpenSIPS 作为 SIP 注册服务器,测试发现偶现电话接通后 30s 左右自动挂断的问题。

2023-08-24 19:45:00 356

原创 SpringBoot 三级缓存解决循环依赖源码分析

针对这个问题,解决方式是借助三级缓存提供提前创建代理对象的触发点,并使用缓存标记目标对象的代理已经创建。笔者提到第三级缓存实际是存放到对象工厂,通过对象工厂的函数式接口来实现获取对象,则此处将触发。则证明已经为目标对象创建过代理对象了,不需要再重新创建,从而避免多个代理对象存在造成的不一致问题。,笔者提到从容器中获取对象时首先是从缓存中获取,则对于创建中的对象 A ,首先将调用。的处理流程中,可能创建出两个不同的 A 对象,违反默认的单例原则。需注意该缓存是为了避免重复创建目标对象的代理对象。

2023-06-19 21:00:00 1011

原创 Java 使用 VisualVM 排查内存泄露

这个方法会创建 Trace 上下文对象 TracingContext 并将其设置到 ThreadLocal 中,创建出 TracingContext 对象后还会调用其相关方法创建 LocalSpan 对象,并将创建的 LocalSpan 对象存入 TracingContext 内部的。此时查看该对象的链表的具体元素数据,可以看到总共有1万多个元素,点开第一个节点,查看该 LocalSpan 的名称,确定当前 SkyWalking 的 trace 记录的起点为这个 LocalSpan 的创建。

2023-06-08 14:53:36 4305

原创 OpenSIPS 3.1 负载均衡 MRCP 服务器的实现

在使用 MRCP 功能时,FreeSWITCH 通过 mrcp profile 的名称来指定要使用的 MRCP 客户端,进而决定要连接的 MRCP 服务器。如果在脚本中配置了 dispatcher 模块的数据库地址,则 OpenSIPS 启动时会从数据库中查询数据加载到内存,读者如有兴趣可参考。执行以下 SQL 语句,往 OpenSIPS 数据库的 dispatcher 表中插入目标 MRCP 服务器地址记录。中选择对应的数据库类型目录,查找该目录下相应的表创建文件,例如。在 FreeSWITCH 的。

2023-05-22 18:45:00 970

原创 Java 细节汇总(5)-Comparator#compare() 升降序确定

方法的实现可以决定排序元素的升序降序,但是许多人对升降序的确定依据是比较模糊的。降序的判断分析与此类似,不再赘述。

2023-05-16 15:03:47 1026

原创 Java 8 ConcurrentHashMap 源码分析

JDK 1.8 的 ConcurrentHashMap 底层数据结构与 HashMap 基本相同,二者在容量机制、Entry 的 hash 值计算及数组 index 下标定位等方面几乎完全一致,这部分读者如感兴趣可参考 Java 8 HashMap 详解 方法源码如下,从中可以看到其处理有以下几个关键步骤: 方法逻辑比较简单,重要逻辑如下: 方法逻辑比较简练,首先判断底层数组的长度是否小于 64,如是则调用 方法尝试 2 倍扩容;其次如果当前数组下标的第一个元素仍然是链表节点,则锁住该节点,将

2023-05-12 17:58:41 761

原创 SpringBoot 优先加载指定 Bean 的实现

扫描注册 Bean 之前注册指定 Bean 到容器中就能实现优先加载。但是一些特殊的需求确实需要某个 Bean 优先实例化,要实现这样的需求就要对 Bean 对象的创建顺序有一定了解。SpringBoot 框架在启动时可以自动将托管的 Bean 实例化,一般情况下它的。可以正确处理 Bean 之间的依赖关系,无需手动指定某个 Bean 优先创建实例。首先我们要知道,SpringBoot 源码中 Bean 对象的实例化都是从。那么要想让指定的 Bean 优先加载,只需要在。进行 Bean 实例化,

2023-05-05 15:31:35 2303

原创 算法-二叉搜索树中第K小的元素

二叉搜索树的中序遍历为有序数组,借助栈结构将树的左子树入栈,直到叶节点为空开始出栈,此时对出栈元素进行计数即可。给定一个二叉搜索树的根节点 root 和一个整数 k ,查找树中第 k 个最小元素(从 1 开始计数),输入:root = [3,1,4,null,2], k = 1。

2023-04-28 19:15:00 184

原创 算法-二叉树合并

给定两个二叉树 root1 和 root2,将这两棵树合并成一棵新二叉树。合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 NULL 的节点将直接作为新二叉树的节点,

2023-04-27 15:00:00 481

原创 MRCPv2 服务器的负载分发方案分析

但是只要 SIP 协商成功,后续 MRCP 和 RTP 交互都可以基于协商地址直接进行,因此只要做到 SIP 信令的负载分发就可以实现 MRCP 会话级别的负载。从上一节内容中我们知道 MRCP 服务器虽然要处理 3 种协议,主要用于实现 MRCP 服务端的高可用,并不能保证负载均衡。目前有2个版本,当前最常用的版本是 V2。MRCP(V2)协议。

2023-04-07 18:26:39 568

原创 FreeSWITCH 中的 DTMF 按键采集

封装在 RTP 包中与普通的 RTP 语音包一起传输,检测的唯一方法是实时提取所有 RTP 包音频数据进行频谱分析,得到高频音和低频音的频率然后查表确认对应的按键值。是通话过程中按键信息传输的一种方式,本质上是由高频音和低频音的两个正弦波合成的音频信号。两种方式传输了 DTMF 信号,则在 FreeSWITCH 中会出现按键数据重复的问题,因为 FreeSWITCH 默认开启的。更有效率,但由于 SIP 信令和 RTP 收发采用的是不同的端口,所以可能会造成收到 DTMF 和实际的声音不同步的问题。

2023-03-24 21:30:00 1521

原创 FreeSWITCH 1.10 源码阅读(6)-unimrcp 模块原理

FreeSWITCH 的 unimrcp 模块源码解析

2023-03-17 21:00:00 1067

原创 FreeSWITCH 智能呼叫流程设计

用户与机器人对话通常都是以文本的形式进行,但是借助 ASR 和 TTS 技术,以语音电话为载体的智能呼叫系统成为可能。APP 会先打开 ASR 识别用户语音然后才放音,放音时会被用户的语音流打断。

2023-03-08 21:30:00 1652

原创 FreeSWITCH 呼入系统的简要设计

APP 回一个 180 给到用户终端,然后直接执行 esl 外连将 a-leg 交给目标服务器控制,由业务系统决定在 a-leg 上的响应行为。APP 桥接坐席,是因为坐席可能暂时忙其他事情直接挂断电话,这样用户会感知到对方挂断但自己这一端的电话还没有挂,影响体验。用户呼入的拨号计划示例如下,当用户呼入到 FreeSWITCH 时可以先执行。这里之所以不在 a-leg 的 outbound 连接上直接执行。

2023-03-03 18:15:00 1336 2

原创 2022,在水一方

1. 工作与生活。

2023-03-01 21:15:00 394 3

原创 CentOS 环境 OpneSIPS 3.1 版本安装及使用

在本地机器上编译 OpenSIPS 源码可能会有许多工具缺失,根据笔者的经验可以先执行以下命令下载相关工具。使用以下命令即可下载 OpenSIPS 的源码,笔者下载的是比较稳定的 3.1 版本,读者有兴趣也可前往。连接到 OpenSIPS,在命令界面查看 OpenSIPS 实例信息,读者如有兴趣可前往。经过以上步骤,OpenSIPS 依赖的数据库表已经建好,接下来使用命令。以上命令执行完成,执行下面的命令安装 opensips-cli 工具。命令,则如下进入编译时配置界面,该界面使用。

2023-02-25 17:46:05 1013

原创 FreeSWITCH 使用指北(1)-回铃音设置

在呼叫场景中,常见的需求是坐席作为 a 腿常驻,用户作为 b 腿接入,桥接两条腿即可进行通话。坐席接待完一个用户之后需要继续等待下一个用户,如果不做任何设置,b 腿挂断之后默认 a 腿也会挂断,下次需要重新拉起坐席的 a 腿,非常不便。命令统计结果异常,因为即便通话 UA 挂断,底层 SIP 会话已经结束,但在 FreeSWITCH 层面上这个 channel 依然存在。网络通畅的情况下使用。二者的功能类似,都是将两个会话桥接在一起进行媒体交换实现通话,但实际上有相当的区别。FreeSWITCH 的。

2023-02-24 19:30:00 1932

原创 MyBatis-plus 代码生成器的使用

MyBatis-plus 提供了许多开箱即用的工具,其中就包括了将数据库表映射为实体类的代码生成器。该工具可以便捷快速地生成体现 ORM 思想的 Entity、Mapper 等模块代码,大大提高开发效率。

2023-02-08 22:15:00 462

原创 算法-不同二叉搜索树总数

【代码】算法-不同二叉搜索树总数。

2023-01-31 18:10:07 391

原创 人生角色变化

本文最初写于 2022 年 5 月,几经延宕,直至疫情防控彻底放开的今日才发布,稍显唏嘘2022年4月16日凌晨4点35分,笔者的第一个孩子出生了,是个6斤9两的虎宝宝。写完这行字的时候,我不知道自己为什么用了“第一个”这种字眼,或许是因为“第一个”蕴藏着初始、开端的含义,新生命的降临意味着人生开始了新的阶段,也增添了新的未知。夜深人静,小朋友在床上睡得正香,我在老家的书桌上写下这篇文章,聊作记录。

2023-01-30 21:45:00 859 2

原创 算法-轮转数组

给定一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。输入: nums = [1,2,3,4,5,6,7], k = 3。向右轮转 1 步: [7,1,2,3,4,5,6]向右轮转 2 步: [6,7,1,2,3,4,5]向右轮转 3 步: [5,6,7,1,2,3,4]输出: [5,6,7,1,2,3,4]

2023-01-29 15:28:12 198

原创 Java 脚本引擎的使用

Java 6 版本就已经引入了 Rhino 引擎用以支持脚本代码运行,而从 Java 8 开始 Nashorn 取代 Rhino 成为 Java 内嵌的 JavaScript 引擎。Nashorn 引擎允许开发人员将 JavaScript 代码嵌入到 Java 中执行,这个特性在复杂的配置系统中有比较大的应用价值,可以满足特定场景下的灵活性要求。

2023-01-10 15:05:47 1050 1

原创 算法-复原 IP 地址

回溯法,使用额外数组作为解空间,循环处理输入字符串的各个部分,确定一个有效 IP 整数段则将其加入解空间递归深入,直到处理至字符串末尾,最终确定一组 IP 整数段则递归返回。一个有效的 IP 地址由四个整数组成,每个整数位于 0 到 255 之间,且不能含有前导 0,整数之间用。给定一个只包含数字的字符串 s ,用以表示一个 IP 地址候选,返回所有可能的有效 IP 地址,输出:[“255.255.11.135”,“255.255.111.35”]输入:s = “25525511135”

2022-12-31 15:51:13 222

原创 Spring 自动配置过滤器 Filter 的自定义实现

在 SpringBoot 中,开发者可以使用@WebFilter注解来实现过滤器 Filter 的定义,但是这个注解功能并不完善,其在日常使用中至少有以下几个缺陷,有鉴于此笔者打算自行定义实现一个功能更为完善的注解@WebFilter注解想要正常生效必须在启动类上添加注解,手动开启扫描注册@WebFilter注解不能指定过滤器 Filter 的拦截顺序注解的定义如下所示,其使用方式与@WebFilter注解完全一致,但是可以通过order 属性指定拦截器的执行顺序/***/**

2022-12-27 16:44:09 994

原创 Java Aho Corasick 自动机的使用

AC 自动机是一种用于字符串多模式匹配的算法,其算法实现的底层数据结构多为字典树,其中一种实现的具体信息读者可参考Aho Corasick 自动机结合 DoubleArrayTrie 极速多模式匹配。在实际开发中 AC 自动机常用于关键词识别提取的场景,以下是相关使用示例。

2022-12-24 15:28:03 581

原创 Java 使用 FreeMarker 模版动态生成内容

FreeMarker是一款模板引擎,可用来生成输出形式丰富的文本内容,其模板编写语言为,非常简单易用。日常开发时常会有邮件发送特定表格的需求,这样的需求就非常适合使用 FreeMarker 来完成,以下内容是一个使用示例。

2022-12-20 15:29:31 1198

原创 算法-链表环判断

给定一个链表的头节点 head ,判断链表中是否有环,如果链表中存在环则返回 true ,否则返回 false。示例链表如下:链表中有一个环,其尾部连接到第二个节点。

2022-11-29 18:15:00 223

原创 算法-打家劫舍

从递推公式 dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]) 可看出递推的基础就是dp[0] 和 dp[1]。此时从 dp[i] 的定义来看,dp[0] 一定是 nums[0],dp[1] 则是 nums[0] 和 nums[1] 的最大值。解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3),偷窃到的最高金额 = 1 + 3 = 4。dp[i]:表示下标 i 以内的房屋最多可以偷窃的金额。输入:[1,2,3,1]

2022-11-26 15:27:44 671

原创 算法-子数组和大于等于目标值的最小长度

双指针组成窗口,前指针不断往后移动,叠加其经过的元素的值。当统计值大于等于目标值时,后指针向后移动,并减去后指针对应元素值,计算取前后指针下标相差最小的值。给定一个正整数的数组 nums 和一个正整数 target ,找出该数组中满足其。输入:target = 7, nums = [2,3,1,2,4,3]如果不存在符合条件的子数组,返回 0,解释:子数组 [4,3] 是该条件下的长度最小的子数组。

2022-11-20 15:24:02 484

原创 Java 线上机器 CPU 100% 的一次排查过程

CPU 100 的一次排查过程

2022-11-19 18:38:06 999

原创 算法-移除有序数组重复项

给定有序数组 nums ,原地删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度,

2022-10-31 15:00:00 291

原创 FreeSWITCH 1.10 源码阅读(5)-外呼命令 originate 单腿呼出的处理

在 FreeSWITCH 1.10 源码阅读(4)-从呼入处理分析核心状态机 中笔者大致分析了上层状态机流转推进呼叫进程的处理过程,FreeSWITCH 中外呼和呼入的处理相当类似,但也有许多细节的区别,其单腿呼出时 channel 状态的流转如下图所示: 外呼命令的源码时序如下,图中状态机流转的部分步骤有所省略,读者可结合 FreeSWITCH 1.10 源码阅读(4)-从呼入处理分析核心状态机 中的内容补充理解。从源码来看, 呼叫一个内部注册用户的流程大致分为以下几个部分,笔者将据此进行分析:以外呼命令

2022-10-24 15:58:24 1924

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除