内容简介:最近对业务里发送 apple APNS, google FCM 部分的代码进行了重构, 抽出了一个单独的 service, 本文记录下过程.我们有好几个 mobile app, 每个 app 会有一套对应的 server 端 service 做业务逻辑, 因为历史原因, 每个 service 里面其实有很多重复代码, 大多只是一些配置和错误处理上有差异.给 app 发推送是个典型, 原来的做法是当要发推送的时候, 往 python 的 celery 队列里扔一个 task, 由 celery 异步得去发.
最近对业务里发送 apple APNS, google FCM 部分的代码进行了重构, 抽出了一个单独的 service, 本文记录下过程.
存在的问题
我们有好几个 mobile app, 每个 app 会有一套对应的 server 端 service 做业务逻辑, 因为历史原因, 每个 service 里面其实有很多重复代码, 大多只是一些配置和错误处理上有差异.
给 app 发推送是个典型, 原来的做法是当要发推送的时候, 往 python 的 celery 队列里扔一个 task, 由 celery 异步得去发.
有如下问题:
- celery 性能不佳, worker class 用的是 gevent, 但在高峰时候任务队列里还是有大量 pending, 代码上之前做过多次优化, 但收效甚微.
- 当 pending 了大量发推送的 task 之后, 会导致其他异步 task 跟着延时, 造成用户体验上的一些问题.
- 历史代码的问题, 每个 app 里对接 APNS/FCM 都有一套单独的代码, 在部分错误处理和统计 metrics 上有差异.
解决方案
- 问题1, 目前已经迁移到 k8s, 其实可以无脑开 HPA, 做 auto scaling, 来提高发送效率. 问题是 python 性能实在太差, 峰值时候估计会 scale 到原先的好多倍, 而 celery 里除了发推送还有很多 task 有 db 操作, scale 过多, 会带来其他问题, 那是另一个问题, 不想在当前这个问题里解决.
- 问题2, celery 里可以设 routing, 简单说可以用单独的 celery instance 来专门处理推送相关 task, 也可以规避1里的 db 问题.
- 问题3, 单纯代码问题, 统一用一套代码重构就行了.
讲真, 碰到的 celery 的 bug 实在太多了, 存量代码用用就行了, 新做业务实在不想用. 而发推送是个很独立的业务, 最后打算拿 go 来单独跑推送.
有现成的项目: https://github.com/appleboy/gorush , 但不太符合我的需求:
- 业务和它交互的时候用的是 rest 或 grpc, 我更倾向中间走个任务队列, 减少业务端的 latency.
- 根据 apple/google 的响应, 有些业务代码还是需要的.
也考察过 nsq , 问题是, 我的发送端还是 python, nsq 的 python client 又是基于 tornado 的, 而线上用的是 gevent 的, 不是说不能用, python 的几套异步方案谁都没比谁强多少, 混在一起够你折腾的, 算了吧.
最后基于 https://github.com/adjust/rmq 这个 lib 单独做了个 service, 原理其实和 celery 用 redis 做 broker 是一样的, 基于 redis 的 list 类型做了个任务队列, 正好也能复用现成的 redis. 发送端就是一个简单的 redis lpush, 任何语言都不用复杂包装.
上线
基于 rmq 的开发过程没什么好讲的, 也就是对接了下 APNS/FCM 的 api, 调试下, 两三天就完事了. 过下在 k8s 上跑一个完整的 stateless service, 除了开发完业务逻辑之外还有那些是需要的, 熟悉 k8s 生态的这些应该都是常规.
Visibility
- error report 发送到 sentry: https://github.com/getsentry/sentry-go
- prometheus 的 metrics endpoint. prometheus 是用 prometheus-operator 搭建的, 只需要创建对应的 ServiceMonitor 就能让 prometheus 自动 pull metrics.
- grafana dashboard 可视化 prometheus 中数据.
- 通过 redis-exporter 监控 redis 中 pending task 数目, alert manager 中建立对应报警.
Scalability
- scalability: 根据 CPU 设定好 k8s 的 HPA, 开始上线可以宽松点, 后续看负载调整策略.
Deployment
- 编写 Dockerfile(runtime 不需要 golang, 可以用 docker 的 multi-stage builds)
- 编写 helm chart, 创建对应的 k8s deployment, hpa, servicemonitor...
- jenkins pipeline 做后续的镜像更新, 改了代码可以在 jenkins 上部署, 不需要有权限操作 kubectl.
效果
原先 celery 处峰值时候 pending 的 task 减少了一大半. 新上的 go service, 常规内存占用不到 10M, 峰值时候 CPU 占用不过 15%, 基本没来不及发的推送, 效果非常好.
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 高性能监控系统 WGCLOUD 更新,重构告警消息推送机制
- iOS 推送通知及推送扩展
- 安卓统一推送联盟明日开启推送通道测试
- 《Web 推送通知》系列翻译 | 第五篇:使用 Web 推送库发送消息 && 第六篇:Web 推送协议
- 推送系统从0到1(七):推送用户画像建立
- 推送系统从0到1(八):个性化精准推送的实现
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Beginning XML with DOM and Ajax
Sas Jacobs / Apress / 2006-06-05 / USD 39.99
Don't waste time on 1,000-page tomes full of syntax; this book is all you need to get ahead in XML development. Renowned web developer Sas Jacobs presents an essential guide to XML. Beginning XML with......一起来看看 《Beginning XML with DOM and Ajax》 这本书的介绍吧!