使用java进行IOS推送,开源的jar包比较有名的主要有两个,一个是 javapns,一个是 notnoop.
对于javapns,之前有介绍过,内存泄漏。这个问题算比较严重,表现在:
1.对于已推送的notify会一直保存,不会回收。
2.默认情况下对应的Vertor保存notify,此数组会自动扩容,大批量时,也会有内存极增的问题。
3.为了避免socket发送过程中,与苹果服务器之间连续失效,从而导致此SOCKET发送的推送都不成功,可以配制一个socket发送一定数量push后,重启此链接,避免重复失败;
另外在重启socket前会轮询已经发送的notify,如果对应的notify推送失败,选择重发,javapns这块的处理有点乱。
以上问题总体来说,通对源码修改,能修复掉相关问题。主要修复是内存泄漏的问题,提前回收,另外feedback服务及时,推送重发问题也不大。
基于javapns修改的服务运行,一直算正常,每天百万级别的推送下来,,稳定运行过几个月没出现过问题。
但是在通过jmap查看进程中未回收的资源还是比较多,,另外最近有出现FULL GC阻塞的情况,导致重启的事件。(另一个原因也可能是推送所有结点切到国外的机器了,内存要很省的用,只有512M-.-)
对于此的评估我大体知道,推送较多时,会出现vector量比较大,自动扩容,然后年老代与sur中对应空间都被塞满了,从而FULL GC没空间了,进而导致服务DOWN机,另外对javapns的代码即使改了以后,看着不是很舒服。
以上背景下,讲讲notnoop!
年前把推送服务基于notnoop进行了扩展,由于上层应用层接口封装足够好,只需要在notnoop在现成接口上实现此推送服务,然后使用中通过配制来选择使用notnoop进行推送即可。
1.notnoop包代码结果比较清晰,主要是com.notnoop.apns.ApnsServiceBuilder类用于控制push对象池的相关组建以及,com.notnoop.apns.internal.ApnsConnectionImpl控制push具体消息的发送。主要有com.notnoop.apns与com.notnoop.apns.internal两个包
结构。对应的单元测试也比较全。
2.notnoop通过构造一个线程池对象(当然也可以单线程),用于跟苹果通信,进行push.
3.notnoop push实现支持基于队列处理,也可以是设置定时任务,一段时间批量处理下队列中的push,一般选第一种方式。
4.notnoop通过队列的方式,然后可以设置一个pools线程对象池,异步处理所有的push.
5.notnoop则只有在第一次发送时创建对应的socket(当然socket为null或者isclosed后,会被重连).之后有单独的线程对socket对象的InputStream流进行monitor,处理对应的发送失败的Notifycation,对于失败的notifycation会存在一个队列里面,会对发送失败的通知进行重发。此处要考虑错误队列的长度问题。
6.notnoop与javapns也一样,对于发送失败的notifycation会进行重发,当然失败分种类,如果是IO异常之类的,会重发三次还不成功就丢弃掉了,中间还会尝试WAIT一段时间,如果是苹果返回的错误码失败之类,才会重新进行发送。
notnoop与javapns有个很大的不同在于对于失败notify的处理问题上,
javapns依赖重连时然后集中遍历所有失败notify,然后进行处理。
notnoop则是开启了一个monitor进程,对于已处理的notify进行实时处理。
以上两种机制,monitor方式明显更合理。
代码情节上来说,以及完整的单元测试,notnoop可以有一个大大的赞,对于内存开销上说,下面是jmap查看到的
num #instances #bytes class name
----------------------------------------------
1: 104004 21613440 [C
2: 36928 8768280 [B
3: 14924 7057840 [I
4: 30776 4193072 <methodKlass>
5: 30776 4132128 <constMethodKlass>
6: 2618 2919376 <constantPoolKlass>
7: 45554 2460160 <symbolKlass>
表现很满意。
以上是使用中的一些心德,希望对各位有帮忙。