# ipcc-fs-esl **Repository Path**: wwooncom/ipcc-fs-esl ## Basic Information - **Project Name**: ipcc-fs-esl - **Description**: 独立的 FreeSWITCH ESL 客户端库,基于 Netty 4.x 重写,完全替代第三方库 `org.freeswitch.esl.client:0.9.2`,提供 多ESL 连接管理、事件路由、分布式监听权协调能力,不含业务逻辑。 - **Primary Language**: Java - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2026-08-28 - **Last Updated**: 2026-08-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ipcc-fs-esl [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) [![Java](https://img.shields.io/badge/Java-17-orange.svg)](https://openjdk.java.net/projects/jdk/17/) [![Spring Boot](https://img.shields.io/badge/Spring%20Boot-3.5.x-green.svg)](https://spring.io/projects/spring-boot) [![Netty](https://img.shields.io/badge/Netty-4.1.x-red.svg)](https://netty.io/) > 独立的 FreeSWITCH ESL 客户端库,基于 Netty 4.x 重写,完全替代第三方库 `org.freeswitch.esl.client:0.9.2`,提供 ESL 连接管理、事件路由、分布式监听权协调能力,不含业务逻辑。 ## 目录 - [背景](#背景) - [核心特性](#核心特性) - [软件架构](#软件架构) - [快速开始](#快速开始) - [配置项](#配置项) - [扩展点](#扩展点) - [示例工程](#示例工程) - [参与贡献](#参与贡献) - [开源协议](#开源协议) ## 背景 ESL 通信原依赖第三方库 `org.freeswitch.esl.client:0.9.2`(2010 年 david varnes 开发),存在以下致命问题: | 问题 | 影响 | | --- | --- | | 依赖 `org.jboss.netty`(Netty 3.x,已停止维护) | 与 JDK 17 + Spring Boot 3.x 兼容性差,存在已知安全漏洞 | | 单实例连接,无自动重连 | FS 断连后需人工重启 | | 无连接健康检查 | 无法及时发现连接假死 | | `connect()` 用 `Thread.sleep(250)` 轮询等待认证 | 阻塞调用线程 | | 同步命令无超时控制 | FS 无响应时调用线程永久阻塞 | | `EslFrameDecoder` 逐字节读取 + `(char) nextByte` 强转 | 性能低,不支持 UTF-8 多字节字符 | | 事件通知使用硬编码线程池 | 事件高并发时成为瓶颈 | | 无连接状态回调机制 | 上层无法感知连接生命周期事件 | **ipcc-fs-esl** 定位为传输层 + 连接层 + 事件路由层 + 分布式协调层,业务逻辑(命令封装、流程编排)由父程序实现。 ## 核心特性 - **Netty 4.x 重写**:兼容 JDK 17 + Spring Boot 3.x,解决安全漏洞与兼容性问题 - **完整连接管理**:单连接(`EslConnection`)+ 多节点管理(`EslConnectionManager`)、自动重连(指数退避)、健康检查、完整状态机 - **注解驱动事件路由**:`@EslEventName` 按事件名自动分发,支持多处理器和通道一致性哈希保证事件顺序 - **分布式监听权竞争**:基于 Redis 的多实例协调,防止重复处理事件,支持监听权切换回调 - **事件拦截器链**:前置/后置处理,支持监控、链路追踪、事件过滤等扩展 - **可观测性**:连接、命令、事件、线程池四类监控指标,内置默认实现 - **Spring Boot 自动配置**:引入依赖即激活,配置前缀 `ipcc.fs.esl.*` - **非 Spring 环境可用**:核心类为纯 POJO,可作为普通 jar 使用 ## 软件架构 采用分层架构设计(自底向上): ``` ┌──────────────────────────────────────────────────────────────────────┐ │ 业务层(父程序实现) │ │ 命令封装、缓存、队列、流程编排、路由、通知 │ ├──────────────────────────────────────────────────────────────────────┤ │ ⑤ 分布式协调层(EslMonitorCoordinator) │ │ 多实例监听权竞争、心跳续期、监听权切换回调 │ ├──────────────────────────────────────────────────────────────────────┤ │ ④ 事件路由层(EslEventRouter) │ │ @EslEventName 注解扫描 → 事件名路由分发 → 拦截器链 │ │ 通道一致性哈希保证同通道事件顺序 │ ├──────────────────────────────────────────────────────────────────────┤ │ ③ 连接管理层(EslConnection / EslConnectionManager) │ │ 单连接管理、多节点管理、自动重连、健康检查、认证握手、生命周期回调 │ ├──────────────────────────────────────────────────────────────────────┤ │ ② 传输层(Netty 4.x Pipeline) │ │ EslFrameDecoder ←→ EslMessageEncoder ←→ EslProtocolHandler │ │ 协议编解码、同步命令/响应、消息分发 │ ├──────────────────────────────────────────────────────────────────────┤ │ ① 基础设施层 │ │ EslClientConfig、EslMetrics、异常体系、线程池管理 │ └──────────────────────────────────────────────────────────────────────┘ ``` 模块结构: ``` src/main/java/cn/ipcc/fs/esl/ ├── EslConnection.java # 单连接客户端:连接管理 + 命令发送 ├── EslConnectionManager.java # 多节点连接管理器 ├── EslClientConfig.java # 客户端配置(纯 POJO) ├── annotation/EslEventName.java # 事件处理器注解 ├── coordinator/ # 分布式协调层 │ ├── EslMonitorCoordinator.java │ ├── EslMonitorListener.java │ └── redis/RedisEslMonitorCoordinator.java ├── exception/ # 异常体系 ├── interceptor/ # 事件拦截器 ├── listener/ # 事件/连接监听接口 ├── metrics/ # 监控指标 ├── netty/ # 传输层(Netty Pipeline) ├── router/ # 事件路由层 ├── spring/ # Spring Boot 自动配置 └── transport/ # 协议消息对象 ``` 详细设计请参考 [fs-esl-client组件架构设计.md](fs-esl-client组件架构设计.md)。 ## 快速开始 ### 环境要求 - JDK 17+ - Maven 3.6+ - FreeSWITCH(开启 ESL 8021 端口) - Redis(启用分布式协调时需要,单实例部署可关闭) ### 安装 将 ipcc-fs-esl 安装到本地 Maven 仓库: ```bash mvn clean install ``` ### 添加依赖 在项目 `pom.xml` 中添加: ```xml cn.ipcc.fs ipcc-fs-esl 1.0.0 ``` 若使用 Spring Boot 自动配置,需确保已引入 `spring-boot-starter`;若启用分布式协调,需引入 `spring-boot-starter-data-redis`。 ### 最小配置 在 `application.yml` 中配置: ```yaml ipcc: fs: esl: # 静态节点(也可通过 EslConnectionManager.registerNode 动态注册) nodes: - host: 192.168.1.10 esl-port: 8021 password: ClueCon # 分布式协调(单实例可设为 false) monitor-enabled: true monitor-group: my-app ``` 引入依赖并配置后,`EslAutoConfiguration` 会自动激活,创建 `EslConnectionManager`、`EslEventRouter`、`RedisEslMonitorCoordinator` 等 Bean。 ## 配置项 配置前缀 `ipcc.fs.esl.*`,完整配置项见 [EslClientProperties.java](src/main/java/cn/ipcc/fs/esl/spring/EslClientProperties.java)。 | 配置项 | 默认值 | 说明 | | --- | --- | --- | | `connect-timeout-seconds` | 5 | 连接超时(秒) | | `command-timeout-seconds` | 10 | 同步命令响应超时(秒) | | `max-frame-size` | 1048576 | 最大帧大小(字节),防止 OOM | | `max-header-lines` | 256 | 消息头最大行数,防止 header 放大攻击 | | `netty-worker-threads` | 4 | Netty worker 线程数 | | `max-reconnect-attempts` | 0 | 最大重连次数(0=无限重试) | | `reconnect-base-delay-seconds` | 1 | 重连基础延迟(秒),指数退避底数 | | `reconnect-max-delay-seconds` | 60 | 重连最大延迟(秒) | | `health-check-interval-seconds` | 30 | 健康检查间隔(秒,0=关闭) | | `health-check-failure-threshold` | 3 | 健康检查连续失败阈值,达到后触发重连 | | `event-executor-mode` | CHANNEL_HASH | 事件执行策略:CHANNEL_HASH / SINGLE_THREAD / FULL_CONCURRENT | | `event-thread-pool-size` | 64 | 事件线程池大小(CHANNEL_HASH 模式下为哈希桶数量) | | `event-queue-capacity` | 10000 | 事件队列容量 | | `event-rejected-policy` | CALLER_RUNS | 事件拒绝策略:CALLER_RUNS / ABORT / DISCARD | | `monitor-enabled` | true | 是否启用分布式监听权竞争 | | `monitor-group` | all | 监听组标识,同组内竞争监听权 | | `monitor-compete-interval-seconds` | 10 | 竞争间隔(秒),未持权时定期尝试竞争 | | `monitor-lock-expire-seconds` | 30 | 锁过期时间(秒) | | `monitor-heartbeat-interval-seconds` | 10 | 心跳续期间隔(秒) | > **注意**:`monitor-enabled` 默认 `true`,引入本库即默认参与监听权竞争(需提供 Redis)。单实例部署或无需分布式协调时,显式设置为 `false`。 ## 扩展点 所有扩展点实现注册为 Spring Bean 即被自动收集,无需额外配置。 ### 事件处理器 实现 `EslEventHandler` 接口,标注 `@EslEventName` 指定事件名,可用 `@Order` 控制多处理器执行顺序: ```java @Component @EslEventName("HEARTBEAT") @Order(1) public class HeartbeatHandler implements EslEventHandler { @Override public void handle(EslEvent event) { // 处理 HEARTBEAT 事件 } } ``` ### 事件拦截器 实现 `EslEventInterceptor` 接口,注册为 Spring Bean 即自动加入拦截器链: ```java @Component public class TraceLoggingInterceptor implements EslEventInterceptor { @Override public boolean beforeHandle(EslEvent event) { // 前置处理:返回 false 中断后续处理 return true; } @Override public void afterHandle(EslEvent event) { // 后置处理 } } ``` ### 连接生命周期回调 实现 `EslConnectionListener`,感知连接建立、断开、认证成功/失败等事件: ```java @Component public class ExampleConnectionListener implements EslConnectionListener { @Override public void onConnected(String address) { /* ... */ } @Override public void onDisconnected(String address, DisconnectReason reason) { /* ... */ } // ... } ``` ### 监听权变化回调 实现 `EslMonitorListener`,在获取/失去监听权时执行自定义逻辑(如动态注册/断开 FS 节点): ```java @Component public class ExampleMonitorListener implements EslMonitorListener { @Override public void onAcquire() { /* 获取监听权:连接 FS 节点 */ } @Override public void onRelease() { /* 失去监听权:断开 FS 节点 */ } } ``` ### 指标扩展 覆盖 `EslMetrics` Bean 可对接 Micrometer 等监控系统,默认实现 `DefaultEslMetrics` 基于 LongAdder: ```java @Bean public EslMetrics eslMetrics(MeterRegistry registry) { return new MicrometerEslMetrics(registry); } ``` ### 回调式事件监听 实现 `EslEventListener` 接口(`onEvent` + `onBackgroundJob`)。**注意**:业务方自定义 `EslEventListener` 时,默认的 `EslEventRouterListener` 桥接不再注册,事件不再走 `EslEventRouter` 路由分发。 ## 示例工程 完整的集成示例见 [example/example-java](example/example-java),演示了全部扩展接口的合理实现,并连接真实 FreeSWITCH 节点验证功能。 运行步骤: ```bash # 1. 安装 ipcc-fs-esl 到本地仓库 mvn clean install # 2. 启动本地 Redis(分布式协调需要) docker run -d -p 6379:6379 redis # 3. 运行示例工程 cd example/example-java mvn spring-boot:run ``` ## 关键约束 - **仅支持 Inbound 模式**(应用 → FS 8021 端口);原库 Outbound 模式未实现。 - **事件订阅必须异步**:`EslConnection` 认证由 `EslProtocolHandler` 在 Netty IO 线程异步完成,事件订阅不能 `.get()` 阻塞,否则死锁 eventLoop。 - **API 命令前缀**:`sendApiCommand` 自动添加 `api ` 前缀(`EslHeaders.CMD_API_PREFIX`);`bgapi` 是平级独立命令,需走 `sendBgapiCommand`。 - **模块定位**:传输层 + 连接层 + 路由层 + 协调层,业务逻辑(命令封装、流程编排)由父程序实现。 ## 参与贡献 1. Fork 本仓库 2. 新建特性分支(`git checkout -b feature/your-feature`) 3. 提交代码(`git commit -m 'Add some feature'`) 4. 推送分支(`git push origin feature/your-feature`) 5. 新建 Pull Request ## 开源协议 [MIT License](LICENSE),Copyright (c) 2026 Moqi