2017-05-03 130 views
1

我在發送iOS設備的批量通知時遇到問題,當我發送一些設備(多於或少於1-20個)時,它可以正常工作,但是當我必須發送批量發送3000+),它給我以下錯誤:發送批量iOS通知的問題

[2017-04-27 15:12:07] ERROR (Notificaciones:347) - IOS: Error en envio notificaciones - CommunicationException: javapns.communication.exceptions.CommunicationException: Communication exception: java.net.ConnectException: Expir tiempo de conexiConnection timed out) at javapns.communication.ConnectionToAppleServer.getSSLSocket(ConnectionToAppleServer.java:156) at javapns.notification.PushNotificationManager.initializeConnection(PushNotificationManager.java:106) at javapns.notification.transmission.NotificationThread.runList(NotificationThread.java:215) at javapns.notification.transmission.NotificationThread.run(NotificationThread.java:199) at java.lang.Thread.run(Thread.java:745) Caused by: java.net.ConnectException: Expir tiempo de conexiConnection timed out) at java.net.PlainSocketImpl.socketConnect(Native Method) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339) at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200) at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) at java.net.Socket.connect(Socket.java:576) at sun.security.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:635) at sun.security.ssl.SSLSocketImpl.(SSLSocketImpl.java:423) at sun.security.ssl.SSLSocketFactoryImpl.createSocket(SSLSocketFactoryImpl.java:88) at javapns.communication.ConnectionToAppleServer.getSSLSocket(ConnectionToAppleServer.java:153) ... 4 more

我的代碼如下:

private static void realizaEnvioIOSLista (final List<DispositivoDto> dispositivos, final String textoES, final String textoCA, final String textoEN, final String tipoNotificacion){  

     Thread thread = new Thread(){ 
      public void run(){    
       try {   
        final List<String> idsDispositivos = new ArrayList<String>();     

        final String keystore = XmlUtils.dirCertIOS + XmlUtils.nomCertificado; 
        final String password = XmlUtils.password; 
        final boolean production = XmlUtils.production; 

        //Obtenemos los ids de los dispositivos 
        for(DispositivoDto r : dispositivos) 
         idsDispositivos.add(r.getIdDispositivo());     

        PushNotificationPayload payload = PushNotificationBigPayload.complex(); 

        /* Customize the payload */ 
        payload.addAlert(textoES);  
//     payload.addSound('default'); 
        payload.setContentAvailable(true); 

        payload.addCustomDictionary("es", textoES); 
        payload.addCustomDictionary("en", textoCA); 
        payload.addCustomDictionary("ca", textoEN); 
        payload.addCustomDictionary("tiponotificacion", tipoNotificacion); 

        List<PushedNotification> notifications = new ArrayList<PushedNotification>(); 

        if(idsDispositivos.size()<= 200){ 
         notifications = Push.payload(payload, keystore, password, production, idsDispositivos); 

        } else { 
         int threads = 1; 

         if(dispositivos.size() > 200) { 
          threads = (int) Math.ceil(dispositivos.size()/200); 
         } 

         notifications = Push.payload(payload, keystore, password, production, threads, idsDispositivos); 
        } 

        int dispEliminados = 0; 
        int dispNotificados = 0; 

        for (PushedNotification notification : notifications) { 
         if (notification.isSuccessful()) { 
          dispNotificados ++; 
         } else { 
          String invalidToken = notification.getDevice().getToken(); 

          int index = idsDispositivos.indexOf(invalidToken); 

          Integer usuario = dispositivos.get(index).getUsuario(); 
          String idHardware = dispositivos.get(index).getIdHardwareDis(); 

          aBD.unregisterDispositivo(usuario, invalidToken,idHardware); 
          dispEliminados ++; 

     //     Exception theProblem = notification.getException(); 
     //     theProblem.printStackTrace(); 

          //If the problem was an error-response packet returned by Apple, get it 
          ResponsePacket theErrorResponse = notification.getResponse(); 

          if (theErrorResponse != null){ 
           logNot.info("IOS: " +theErrorResponse.getMessage()); 
          } 
         } 
        } 
        logNot.info("IOS: Dispositivos Notificados correctamente: " + dispNotificados); 
        logNot.info("IOS: Dispositivos Eliminados: " +dispEliminados); 

       } catch (CommunicationException e) { 
        logNot.error("IOS: Error en envio notificaciones - CommunicationException: ",e); 
       } catch (KeystoreException e) { 
        logNot.error("IOS: Error en envio notificaciones - KeystoreException: ",e); 
       } catch (JSONException e) { 
        logNot.error("IOS: Error en envio notificaciones - JSONException: ",e); 
       } catch (Exception e) { 
        logNot.error("IOS: Error en envio notificaciones",e); 
       } 
      } 
     }; 

     thread.start(); 
    } 

出問題了嗎?蘋果服務器的最大設備數量和連接數量是多少?歡迎任何幫助。

回答

0

我發現我的問題的解決方案,代碼工作正常,與系統管理員交談後,我們可以看到,這是一個服務器配置問題,因爲根據此鏈接apple能夠發送通知,以下必須考慮:

To use Apple Push Notification service (APNs), your Mac and iOS clients need a direct and persistent connection to Apple's servers.

這樣:

If you use Wi-Fi behind a firewall, or private Access Point Name for cellular data, connect to specific ports. You need a direct, unproxied connection to the APNs servers on these ports:

  • TCP port 5223 to communicate with APNs.
  • TCP port 2195 to send notifications to APNs.
  • TCP port 2196 for the APNs feedback service.
  • TCP port 443 is required during device activation, and afterwards for fallback (on Wi-Fi only) if devices can't reach APNs on port 5223.

此外:

The APNs servers use load balancing, so your devices don't always connect to the same public IP address for notifications. It's best to let your device access these ports on the entire 17.0.0.0/8 address block, which is assigned to Apple.

因此,通過由系統管理員配置防火牆來允許這些連接解決了所有問題。我希望它能幫助別人。