2016-01-22 22 views
5

Sto creando un server di accesso per il mio client all'applicazione server.Autenticazione da server a server per client - Singola filettatura

Fondamentalmente ci sono 5 server e tutti questi server sono collegati a un server di accesso.

Il client può connettersi a uno qualsiasi di questi 5 server, ma è necessario autenticarsi con nome utente e password. L'autenticazione deve essere eseguita nel server di login e il server di login dovrebbe restituire una risposta al server effettivo che dovrebbe restituire la risposta al client.

Così la sua come quella:

client -> Server -> Login-Server -> Server -> Client (codice di risposta)

Ora, io sto usando Netty ed è NIO, non è filettatura per-client. Ora, per autenticarsi con NIO, dobbiamo aspettare che arrivi una risposta dal server di login, e che può richiedere un po 'di tempo e ritardare altri client che vogliono accedere, in realtà non si può semplicemente aspettare una risposta con NIO come quella . Così ho pensato a un'idea su come posso farlo funzionare. La mia idea è stata eseguire la richiesta su un thread diverso e avere un evento con il metodo onResponse(String key, int responseCode) e quindi inserire il canale del cliente in una mappa con una chiave generata, in modo da poter sapere a chi appartiene la risposta. Quindi, quando effettuiamo l'autenticazione, inviamo la chiave e i dati dell'utente.

Ma ritengo che questo sia un brutto modo e che esiste un metodo più efficiente per farlo. Qualche idea?

+0

AFAIK netty supporta il blocco di NIO con un thread per connessione. Nota il comportamento * predefinito * di NIO sta bloccando le operazioni e fino a poco tempo fa solo Socket supportava operazioni non bloccanti come opzione. –

+0

In un ambiente con più server, verrà interrotto quando si utilizza map per mantenere i canali. – eg04lt3r

+0

Solo un suggerimento, dal momento che hai chiesto modi migliori per farlo: se stai usando Java potresti voler cercare in websockets i.e. html 5 + http (s). Quindi si ottiene un thread per modello client con cui lavorare, l'autenticazione con la crittografia è trasparente per l'applicazione e si ottengono tutte le funzionalità di NIO senza l'implementazione del client finale. – MuffinMan

risposta

2

Supponendo di avere il pieno controllo di tutto il sistema:

assegnare un ID per ogni connessione client nel server. Quindi, quando è necessario autenticare l'utente, includere questo ID di connessione nella richiesta dal server al server di login e tornare senza attendere la risposta dal server di login.

In futuro, il server riceverà la risposta di accesso dal server di accesso. Se la risposta di accesso contiene l'ID di connessione client, utilizzare tale ID per trovare una connessione da un server a un client e inoltrare la risposta al client.

1

Ecco come l'ho fatto.

Setup

creare una classe wrapper di canale, in modo da poter identificare quale canale appartiene a quale cliente.

public class CustomChannel implements Channel { 

    private final Channel channel; 
    private final String clientId; 

    ... 
} 

Creare un ChannelMatcher personalizzato per il canale corrispondenza del cliente:

public class CustomChannelMatcher implements ChannelMatcher { 
    private final String clientId; 

    public CustomChannelMatcher(String clientId) { 
     this.clientId = clientId; 
    } 

    @Override 
    public boolean matches(Channel channel) { 
     if (channel instanceof CustomChannel) { 
      return clientId.equals(((CustomChannel) channel).getClientId()); 
     } 
     return false; 
    } 

    ... 
} 

gestione delle richieste

Nel vostro gestore cliente, utilizzare ChannelGroup per tenere traccia dei canali dei vostri clienti.

ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); 

... 

channelGroup.add(new CustomChannel(ctx.channel(), clientId)); 

// send request to another server without blocking 

gestione delle risposte

Nel vostro gestore di server, utilizzare il CustomChannelMatcher per abbinare il canale del cliente.

// when the server responds sometimes later 

channelGroup.writeAndFlush(responseMessage, 
    new CustomChannelMatcher(clientId)); 

Il codice sopra troverà il canale di un client corrispondente e scriverà il messaggio.

1

Si è preoccupati di bloccare un thread di lavoro NIO, ma si fa girare un altro thread per eseguire il login. Hai appena usato un altro thread comunque. Quindi definire più thread nel tuo server per http (s) e farlo con esso. A meno che non si aspettino più di 100 accessi simultanei, non vi è alcun problema qui.

NIO è sopravvalutato; il sistema operativo è ottimo per programmare i thread e il cambio di contesto, molto meglio di quanto farebbe in java facendo backflip con asyn apis. I thread in attesa non consumano CPU.

0

So che hai detto che eri su Netty. Devo solo dire qualcosa sull'api servlet (nel caso sia possibile usarlo):

FYI, questo è il problema affrontato con il servlet api 3.0+ che consente di eseguire esattamente quel lavoro in un AsynContext. Non scherzando, leggi su servlet 3.0, preferibilmente presentazioni e tutorial su javaone youtube, anche le specifiche PDF sono migliori di javadoc.

E se si desidera eseguire anche NIO su servletinputstream/servletoutputstream, è possibile farlo (anche se un po 'coinvolto) con servlet api 3.1. La presentazione javaone (penso che il 2014) sia fantastica.

Problemi correlati