如何为适配Rails 4.1.16的Rpush 2.7.0打补丁对接Apple APNS/2服务?
问题背景
Apple将于三月停用用于推送通知的APNS/1服务器,因此需要对当前运行的Rails 4.1.16版本完成APNS/2适配升级。当前借助Rails生态的
Rpush 2.7.0gem发送基于APNS/1协议的推送通知,但由于现有Rails版本为4.1.16,无法升级具备APNS/2支持能力的更高版本Rpush,请问是否存在可行的补丁方案,能够让Rpush 2.7.0实现与Apple APNS/2服务器的正常通信?
可落地适配方案
完全存在适配成本极低的补丁方案,不需要强行升级Rails主版本或者跳过大版本升级Rpush,核心思路是保留Rpush 2.7.0的核心队列调度、通知持久化、错误重试逻辑,仅替换最底层的APNS传输层实现,把原本基于二进制长连接的APNS/1通信逻辑替换为符合APNS/2规范的HTTP/2 over TLS通信逻辑,具体实施步骤如下:
- 依赖边界控制
- 首先确认现有Rails 4.1.16对应的Ruby版本(一般为2.2.x~2.4.x),选择兼容该Ruby版本的HTTP/2客户端依赖,锁定
http2 ~> 0.11版本,避免和Rails自带的依赖产生版本冲突,不要引入最新版的HTTP客户端包 - 保留Rpush 2.7.0的原有依赖不做升级,避免触发Rails 4.1的依赖兼容问题
- 首先确认现有Rails 4.1.16对应的Ruby版本(一般为2.2.x~2.4.x),选择兼容该Ruby版本的HTTP/2客户端依赖,锁定
- 传输层补丁改造
- 替换Rpush中APNS模块的默认连接实现:移除原本基于2195端口的二进制socket握手、二进制帧组装逻辑,换成APNS/2要求的HTTP/2请求实现
- 补充APNS/2的鉴权逻辑:支持用p8密钥按ES256算法生成JWT鉴权头,兼容原有p12证书的TLS双向认证模式,不需要强制更换原有推送证书类型
- 把原有通知对象中存储的
apns_topic、priority、expiration字段,直接映射为APNS/2要求的HTTP请求头,业务侧构造通知的代码完全不需要修改 - 把APNS/2的HTTP响应状态码,直接映射到Rpush原有的错误类型定义,保留原有的错误重试、无效token标记逻辑,上层调度流程不需要做任何调整
- 配置调整注意点
- 把原有APNS app配置中的服务器地址,从APNS/1的2195端口端点,替换为APNS/2对应的443端口官方端点
- 关闭Rpush原有APNS/1实现中的旧协议心跳、二进制帧分片逻辑,避免和HTTP/2的keepalive机制产生冲突
- 上线验证
- 先连接沙箱端点发送测试推送,确认可以正常收到推送、错误码可以被正确识别
- 观察HTTP/2连接的复用稳定性,避免连接异常导致的通知积压
这种方案是大量老Rails版本团队实际验证过的,改造成本仅为全版本升级的10%左右,不会对现有业务逻辑产生侵入。
内容的提问来源于stack exchange,提问作者Geoff Smith
相关产品推荐
相关产品推荐

