提升APNS消息推送质量的一些想法和验证程序
来源:互联网 发布:文华财经模拟交易软件 编辑:程序博客网 时间:2024/06/05 01:03
今天在想用什么样的方式,才能改善提高大级别时APNS的推送质量.有了个初步的想法。
首先简单列一下,APNS常见的一些限制和要注意的地方:
1.频繁建立和断开连接,被当成受到攻击,直接把链接给断了。
2.开发一堆并发,有个消息发生异常推送失败了,apns ack要等一段时间(可能有1sec左右的延迟)才返回,而
这期间,后面发的消息也会被认为有问题,直接被其扔了。
这时麻烦了,要依返回的Identifier,找到出错的消息,跳过它,把后面的消息重发。
3.还有一些如扩展的JSON太长了,超过了长度限制。
4.莫名其妙的连接断开错误,需要时刻做好重连准备。
5. .....
极光推送有篇Blog<<APNs 推送原理及问题>>可以看看.
这其中,有些可以通过发送前先进行效验,提前过滤掉一些问题,毕竟APNS的ACK相对有点慢。
比如: DeviceToken 是否合法? 尽量防止Invalid token (Status code = 8)之类出现
参数是否正确,如推送内容是否为空之类。
包是否太大?
......
另外一些东西就比较麻烦,比如上面的第2条。这时就需要想些别的方法来处理.
首先简单列一下,APNS常见的一些限制和要注意的地方:
1.频繁建立和断开连接,被当成受到攻击,直接把链接给断了。
2.开发一堆并发,有个消息发生异常推送失败了,apns ack要等一段时间(可能有1sec左右的延迟)才返回,而
这期间,后面发的消息也会被认为有问题,直接被其扔了。
这时麻烦了,要依返回的Identifier,找到出错的消息,跳过它,把后面的消息重发。
3.还有一些如扩展的JSON太长了,超过了长度限制。
4.莫名其妙的连接断开错误,需要时刻做好重连准备。
5. .....
极光推送有篇Blog<<APNs 推送原理及问题>>可以看看.
这其中,有些可以通过发送前先进行效验,提前过滤掉一些问题,毕竟APNS的ACK相对有点慢。
比如: DeviceToken 是否合法? 尽量防止Invalid token (Status code = 8)之类出现
参数是否正确,如推送内容是否为空之类。
包是否太大?
......
另外一些东西就比较麻烦,比如上面的第2条。这时就需要想些别的方法来处理.
我想出来的办法如下图:
简单说来是分别建立多个长连接,通过Ring比较平均的分配给长连接去发送推送,
当其中如果有长连接出问题时,也只会影响这个RingNode的List中部分消息,不会影响其它链接,这么做重发消息范围也缩小了。
自已写了个tcp server模拟服务端,用上面的想法,模拟客户端,稍稍验证了下模型:
/*Author: XCL(XiongChuanLiang)Date: 2015-11-11 | RingNode RingNode| | ConnRing |P...| RingNode RingNode(ID|List|...)| C... | Notification| | Notification| | ......|*/package mainimport ("container/list""container/ring""fmt""log""net""runtime""strings""sync""time")var (dialNetwork string = "tcp"dialAddress string = "localhost:6666")func main() {runtime.GOMAXPROCS(runtime.NumCPU())test()}////////////////////////////////////////////func test() {/////////////////////////////////////////////初始化cr := NewConnRing(3)cr.InitConn()cr.ListConnRing()//得到通知环var rn *RingNodevar ok bool//for _ = range time.Tick(time.Second * 1) {for i := 0; i < 5; i++ {v := cr.GetRingNode().Next().Valueif rn, ok = v.(*RingNode); ok {rn.Add(NewNotification(fmt.Sprintf("%d-%s", rn.NodeID, "PushNotification")))rn.ListNotification()log.Println(strings.Repeat("--", 50))}}///////////////////////////////////////////cr.Close()}////////////////////////////////////////////// Ring//////////////////////////////////////////////type ConnRing struct {r *ring.Ring}func NewConnRing(n int) *ConnRing {cr := &ConnRing{}cr.r = ring.New(n)return cr}func (cr *ConnRing) InitConn() {for i := 1; i <= cr.r.Len(); i++ {cr.r.Value = NewRingNode(dialNetwork, dialAddress, i)cr.r = cr.r.Next()//log.Println("[InitConn] i:", i, " conn ok")}}func (cr *ConnRing) GetRingNode() *ring.Ring {cr.r = cr.r.Next()return cr.r}func (cr *ConnRing) ListConnRing() {cr.r.Do(func(p interface{}) {if v, ok := p.(*RingNode); ok {log.Println("[ListConnRing] NodeID:", v.NodeID)}})}func (cr *ConnRing) Close() {for i := 1; i <= cr.r.Len(); i++ {v := cr.r.Value//v := cr.GetRingNode().Next().Valueif rn, ok := v.(*RingNode); ok {(*rn).Close()}}}///////////////////////////////////////////////////////// 环的节点///////////////////////////////////////////////////////type RingNode struct {NodeID intStatus intconnNList *list.List //通知列表}func NewRingNode(dialNetwork, dialAddress string, id int) *RingNode {x := &RingNode{}x.NodeID = idx.NList = list.New()x.Dial(dialNetwork, dialAddress)return x}func (rn *RingNode) Add(v *Notification) {rn.NList.PushBack(v)}func (rn *RingNode) Remove() {//......}func (rn *RingNode) Get() *Notification {x := rn.NList.Front()if v, ok := x.Value.(*Notification); ok {return v} else {return nil}}func (rn *RingNode) ListNotification() {log.Println("节点(", rn.NodeID, ")共有(", rn.NList.Len(), ")笔数据,明细如下:")for e := rn.NList.Front(); e != nil; e = e.Next() {if c, ok := e.Value.(*Notification); ok {log.Println("ID:", rn.NodeID, " Content:", c.Content)} else {log.Println("ID:", rn.NodeID, " Value:", e.Value)}}}///////////////////////////////////////////////////////// 通知///////////////////////////////////////////////////////type Notification struct {Content stringCt time.Time}func NewNotification(v string) *Notification {return &Notification{Content: v, Ct: time.Now()}}///////////////////////////////////////////////////////// 基本的服务器连接处理///////////////////////////////////////////////////////type conn struct {mu sync.Mutexconn net.Connerr error}func (c *conn) Dial(network, address string) {con, err := net.Dial(network, address)if err != nil {log.Fatal(err)}c.conn = conlog.Println(address, "连接成功!")return}func (c *conn) Close() error {c.mu.Lock()addr := c.conn.RemoteAddr()if c.conn != nil {c.conn.Close()}c.mu.Unlock()log.Println(addr, "断开连接!")return nil}////////////////////////////////////////////////////////*2015/11/12 00:25:07 localhost:6666 连接成功!2015/11/12 00:25:07 localhost:6666 连接成功!2015/11/12 00:25:07 localhost:6666 连接成功!2015/11/12 00:25:07 [ListConnRing] NodeID: 12015/11/12 00:25:07 [ListConnRing] NodeID: 22015/11/12 00:25:07 [ListConnRing] NodeID: 32015/11/12 00:25:07 节点( 3 )共有( 1 )笔数据,明细如下:2015/11/12 00:25:07 ID: 3 Content: 3-PushNotification2015/11/12 00:25:07 ------------------------------------2015/11/12 00:25:07 节点( 1 )共有( 1 )笔数据,明细如下:2015/11/12 00:25:07 ID: 1 Content: 1-PushNotification2015/11/12 00:25:07 ------------------------------------2015/11/12 00:25:07 节点( 2 )共有( 1 )笔数据,明细如下:2015/11/12 00:25:07 ID: 2 Content: 2-PushNotification2015/11/12 00:25:07 ------------------------------------2015/11/12 00:25:07 节点( 3 )共有( 2 )笔数据,明细如下:2015/11/12 00:25:07 ID: 3 Content: 3-PushNotification2015/11/12 00:25:07 ID: 3 Content: 3-PushNotification2015/11/12 00:25:07 ------------------------------------2015/11/12 00:25:07 节点( 1 )共有( 2 )笔数据,明细如下:2015/11/12 00:25:07 ID: 1 Content: 1-PushNotification2015/11/12 00:25:07 ID: 1 Content: 1-PushNotification2015/11/12 00:25:07 ------------------------------------2015/11/12 00:25:07 127.0.0.1:6666 断开连接!2015/11/12 00:25:07 127.0.0.1:6666 断开连接!2015/11/12 00:25:07 127.0.0.1:6666 断开连接!*/模型是跑起来了,具体效果要实际测才知道。 不过就算发成功了,也只是初步,后面还有一堆
事情要做,比如,要区分,app是否已被用户删了。消息是否被合并了,发送成功与失败的结果返回与统计等等。
BLOG: http://blog.csdn.net/xcl168
0 0
- 提升APNS消息推送质量的一些想法和验证程序
- PHP的APNS消息推送
- 消息推送(APNS)
- IOS消息推送APNs
- APNS消息推送
- APNS推送消息
- APNs消息推送
- APNs通知与应用内消息(推送通知和透传消息)的区别
- APNS提供了两项基本的服务:消息推送和反馈服务
- APNS消息推送完整讲解
- APNs消息推送完整讲解
- IOS消息推送之APNS
- APNs消息推送完整讲解
- IOS---APNS 消息推送实践
- IOS消息推送之APNS
- IOS---APNS 消息推送实践
- APNs消息推送完整讲解
- iOS消息推送之APNS
- Fragment 和 actionbar
- C语言程序经验贴
- GCC编译的背后( 预处理和编译 汇编和链接 )
- cocos2dx gaf 修改源码,让其默认播放声音
- c语言编译预处理和条件编译执行过程的理解
- 提升APNS消息推送质量的一些想法和验证程序
- 使用 JSON 进行数据的异步传输
- 数据库常用类
- LeetCode Longest Valid Parentheses
- 大型网站之分布式会话管理
- Pavel loves grid mazes(CodeForce 377A)
- Quick-Cocos2d-x初学者游戏教程(二)
- Quick-Cocos2d-x初学者游戏教程(三)
- Ubuntu14安装Nvidia显卡驱动