前言
Apple APNS PUSH是最能保证iOS系统上PUSH到达率的一种途径(考虑到iOS app的后台存活时间不长);几乎可以这样说,只要用户启动过APP,并且没有在系统设置里关闭其通知栏,在联网的情况下,APNS PUSH可以近乎实时送达客户系统通知栏。非联网情况下,APNS亦可以保留最后一条离线通知(重新联网时离线会下发)。这些APNS的特点,可直接查看:
苹果APNS PUSH的历史到现在
第一版 APNS PUSH应该是应用最早,也是最广泛的方式。APP服务端与APNS服务器之间建立SSLSocket连接,且是基于客户端证书认证的SSL方式。比较好的客户端实现举个例子 https://github.com/RamosLi/dbay-apns-for-java。第一版APNS PUSH虽然是长连接,但并未定义完善的心跳等协议规范。另外一个缺点是,客户认证证书有有效期一般是一年,在互联网企业开发运营人员更新频繁的节奏下,很容易将证书更换环节遗忘,就会导致暂时性iOS PUSH不可用。如果想要在这一版中获得PUSH推送结果,还需要单开feedback接口做PUSH状态回执。
第二版 APNS PUSH建立于HTTP2.0协议之上。提供了非证书方式的,且没有失效期(自己不主动撤销)的token认证方式。更好的一点是,可以在同一个信道接收PUSH回执状态,错误码定义亦非常全面,可见 APNS HTTP2推送错误码表 其中的Table 8-6。
基于HTTP2.0 APNS PUSH 推送sdk(jar)开源项目选择
1、https://github.com/CleverTap/apns-http2(不是最终选择)
A Java library for sending notifications via APNS using Apple's new HTTP/2 API. This library uses OkHttp. Previous versions included support for Jetty's client, however, we've removed that due to instability of the Jetty client.
Note: Ensure that you have Jetty's ALPN JAR (OkHttp requires it) in your boot classpath. See here for more information. This is required until Java 9 is released, as Java 8 does not have native support for HTTP/2.
总结的来说就是,当下这个客户端依赖OkHttp来建立与APNS服务器的连接,并且如果你的jvm低于1.9,还需要在jvm启动的boot classpath里配置ALPN这个jar的依赖来支持java8不支持的http2。
-Xbootclasspath/p:/home/xxxxxxx/www/yourapp/webapps/ROOT/WEB-INF/lib/alpn-boot-8.1.7.v20160121.jar
//上下两位的版本的对应关系比较紧密(上下两个版本的搭配是OK的,经过验证,版本关系)
java version "1.8.0_91"Java(TM) SE Runtime Environment (build 1.8.0_91-b14)Java HotSpot(TM) 64-Bit Server VM (build 25.91-b14, mixed mode)
使用方式(maven):
<dependency>
<groupId>com.clevertap.apns</groupId>
<artifactId>apns-http2</artifactId>
<version>1.0.3</version>
<type>pom</type>
</dependency>
Create a client
FileInputStream cert = new FileInputStream("/path/to/certificate.p12");
final ApnsClient client = new ApnsClientBuilder()
.withProductionGateway()
.inSynchronousMode()
.withCertificate(cert)
.withPassword("")
.withDefaultTopic("<your app's topic>")
.build();
Using provider authentication tokens
final ApnsClient client = new ApnsClientBuilder()
.inSynchronousMode()
.withProductionGateway()
.withApnsAuthKey("<your APNS auth key, excluding -----BEGIN PRIVATE KEY----- and -----END PRIVATE KEY----->") //注意这里的key不包含前后那个分隔串!
.withTeamID("<your team ID here>")
.withKeyID("<your key ID here, present in the auth key file name>")
.withDefaultTopic("<your app's topic>")
.build();
The notification builder supports several other features (such as badge, category, etc). The minimal is shown below:
Notification n = new Notification.Builder("<the device token>")
.alertBody("Hello").build();
client.push(n, new NotificationResponseListener() {
@Override
public void onSuccess(Notification notification) {
System.out.println("success!");
}
@Override
public void onFailure(Notification notification, NotificationResponse nr) {
System.out.println("failure: " + nr);
}
});
NotificationResponse result = client.push(n);
System.out.println(result);
总结:基本推送都OK,但是QPS能力不足,环境绑定苛刻,且单机只能提供5 QPS,原因下边会说明。
支持认证方式:token认证和证书认证
OkHttp本身更多应用于Android等用户有限能力端做http访问,并不要求高并发,证据如下。
okhttp3.Dispatcher
public final class Dispatcher {
private int maxRequests = 64;
private int maxRequestsPerHost = 5; //此处限制了单机并发数!!!!!
2、https://github.com/relayrides/pushy(我们的最后选择)
总结:实现基于Netty,支持推送QPS良好。
支持认证方式:token认证和证书认证
集成:
<dependency>
<groupId>com.turo</groupId>
<artifactId>pushy</artifactId>
<version>0.13.10</version>
</dependency>
基于token的认证方式:
final ApnsClient apnsClient=newApnsClientBuilder() .setApnsServer(ApnsClientBuilder.DEVELOPMENT_APNS_HOST) .setSigningKey(ApnsSigningKey.loadFromPkcs8File(newFile("/path/to/key.p8"),"TEAMID1234","KEYID67890")) .build();
// key.p8中存储的就是苹果开发者后台申请的token认证文件,可以取出来其中的值当成认证串来使用。
发送回执都很简单,可直接参考https://github.com/relayrides/pushy 这里的示例
有任何问题可以留言,不吝赐教谢谢!
网友评论