Sto progettando un server di notifica push (per inviare notifiche tramite APNS e server di Google) e ho creato il seguente design per un server di applicazioni Web basato su Java. Mi piacerebbe molto ricevere commenti da persone che hanno esperienza di tutto ciò che riguarda questo. Si tratta di un progetto di livello abbastanza elevato, quindi potrei mancare alcuni dettagli di implementazione minori.
Sfondo
- Le notifiche push passeranno tramite APNS (per iOS) o GCM (per Android)
- Per spingere su iOS, secondo i consigli di Apple, le connessioni ad APNS (il servizio di notifica push di Apple) devono rimanere sempre aperte
- La connessione APNS avviene tramite un socket TCP binario - se c'è un problema con i server APNS o un problema con una richiesta, il server APNS può interrompere la connessione. Se non ci sono problemi non c'è risposta. Per evitare di perdere messaggi, dopo aver inviato un messaggio ci sarà un periodo di attesa di ~ 1 secondo per garantire che la connessione non sia chiusa.
- Per inviare a Android, puoi solo effettuare richieste HTTP a GCM.
Requisiti
- Vari altri componenti possono inviare ai dispositivi mobili tramite questo server, quindi esporrai un'API (HTTP) tramite un servlet
- Nessun singolo componente dovrebbe essere in grado di negare il servizio ad altri componenti inviando molte richieste di notifiche push da soddisfare
- Eventuali errori durante l'invio delle notifiche push tramite Google o Apple devono essere mantenuti su un database
design
Servlet
Il Servlet esporrà un'interfaccia HTTP che accetterà una richiesta push. La richiesta contiene tutte le informazioni necessarie per effettuare la push con APNS o GCM, nonché la piattaforma su cui deve passare la spinta (APNS o GCM). La richiesta contiene anche informazioni sul componente che ha inviato la richiesta. Quando il servlet riceve una richiesta, la inserisce in una coda JMS e quindi restituisce immediatamente il successo (ovvero la risposta HTTP 200) se il posizionamento in questa coda ha avuto esito positivo.
Demone di sfondo
Il Servlet avrà un singolo daemon in background che inizia con contextInitialized
ServletContextEvent
. Questo demone sarà il "gestore push" e al momento dell'inizializzazione genererà un numero (~ 10) di thread di lavoro persistenti. La metà dei thread sarà per spingere ad Android e metà a iOS.
Il daemon in background si bloccherà su una coda JMS e quando riceverà un messaggio in coda, lo inserirà nella sua coda "round robin" basata sul componente da cui proviene il messaggio. In modo che nessun singolo componente possa dominare questo server, verrà elaborato un messaggio per ciascun componente alla volta.
Il daemon in background assegnerà quindi il messaggio a un thread di lavoro che è gratuito per la piattaforma a cui è destinato il messaggio. Se non ci sono thread di lavoro gratuiti, il demone aspetterà fino a quando uno sarà libero. Prima di inviare un messaggio al thread worker, il daemon controlla innanzitutto se ci sono stati problemi con il messaggio precedente e se ce ne sono stati, li persiste in un database.
Discussioni del lavoratore
Durante l'inizializzazione, i thread iOS apriranno immediatamente una connessione ad APNS.
Entrambi i tipi di thread di lavoro si fermeranno all'infinito, bloccando l'attesa di un messaggio dal demone. Alla ricezione di un messaggio, il thread invierà il messaggio tramite APNS o GCM, verificherà eventuali errori (attendendo la risposta per GCM o in attesa di un periodo impostato per APNS) e quindi blocchi nuovamente in attesa di un messaggio, restituendo l'errore informazioni al demone una volta che il messaggio successivo arriva.
È un piano fattibile? C'è qualche modo migliore per andare su questo? Sto reinventando qualche ruota?