使用Pushy 0.15.2+Spring Boot发送APNs通知时预发环境网络不可达问题
问题:预发环境使用Pushy发送APNs推送出现网络不可达错误
在Spring Boot项目中使用Pushy 0.15.2版本向iOS设备发送APNs推送通知,本地运行代码一切正常,但部署到预发环境后出现网络不可达错误。
推送代码:
ApnsClientBuilder clientBuilder = new ApnsClientBuilder(); clientBuilder.setApnsServer(ApnsClientBuilder.DEVELOPMENT_APNS_HOST); clientBuilder.setConnectionTimeout(Duration.ofMillis(60000)); File file = new File(getClass().getClassLoader().getResource("zzzzz").getFile()); clientBuilder.setClientCredentials(file, "yyyyy"); apnsClient = clientBuilder.build(); ApnsPayloadBuilder payloadBuilder = new SimpleApnsPayloadBuilder(); payloadBuilder.setAlertTitle("xxxx"); payloadBuilder.setAlertBody("This is test message"); SimpleApnsPushNotification pushNotification = new SimpleApnsPushNotification(messageDto.getDeviceId(), "com.np.gotprint", payloadBuilder.build()); apnsClient.sendNotification(pushNotification).get(); System.out.println("send successfully");
预发环境报错日志:
Caused by: io.netty.channel.AbstractChannel$AnnotatedSocketException: Network is unreachable: api.sandbox.push.apple.com/2620:149:208:304:0:0:0:1f:443 Caused by: java.net.SocketException: Network is unreachable at sun.nio.ch.Net.connect0(Native Method) at sun.nio.ch.Net.connect(Net.java:454) at sun.nio.ch.Net.connect(Net.java:446) at sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:648) at io.netty.util.internal.SocketUtils$3.run(SocketUtils.java:83) at io.netty.util.internal.SocketUtils$3.run(SocketUtils.java:80) at java.security.AccessController.doPrivileged(Native Method) at io.netty.util.internal.SocketUtils.connect(SocketUtils.java:80)
排查及解决方案
检查预发环境网络连通性
预发服务器无法访问苹果沙箱APNs服务器api.sandbox.push.apple.com:443,需确认:- 服务器防火墙/安全组是否放行对该域名443端口的出站请求;
- 错误日志显示的是IPv6地址,若预发环境未配置IPv6网络,可强制Pushy使用IPv4连接,修改客户端构建代码:
clientBuilder.setPreferredProtocol(Protocol.HTTP_2); clientBuilder.setSocketAddressResolver((host, port) -> { try { InetAddress[] addresses = InetAddress.getAllByName(host); // 筛选IPv4地址 for (InetAddress addr : addresses) { if (addr instanceof Inet4Address) { return new InetSocketAddress(addr, port); } } // fallback到第一个地址 return new InetSocketAddress(addresses[0], port); } catch (UnknownHostException e) { throw new RuntimeException(e); } });
确认APNs环境匹配
若预发环境对接的是生产环境的iOS设备,需将APNs服务器切换为生产环境地址:clientBuilder.setApnsServer(ApnsClientBuilder.PRODUCTION_APNS_HOST);修复证书文件读取逻辑
打包成Jar包后,getResource("zzzzz").getFile()可能无法正确读取资源文件,改用流读取方式:try (InputStream certStream = getClass().getClassLoader().getResourceAsStream("zzzzz")) { clientBuilder.setClientCredentials(certStream, "yyyyy"); } catch (IOException e) { // 处理证书读取异常 throw new RuntimeException("Failed to load APNs certificate", e); }优化异步调用逻辑
代码中使用get()同步阻塞获取结果,容易引发线程阻塞问题,建议改用异步回调:apnsClient.sendNotification(pushNotification) .whenComplete((result, error) -> { if (error != null) { // 处理推送失败 System.err.println("Push failed: " + error.getMessage()); } else { System.out.println("send successfully"); } });
内容的提问来源于stack exchange,提问作者Manish Kumar
相关产品推荐
相关产品推荐

