Implementa RPC tramite SIP

1

Guarda il seguente caso d'uso.

Ho un'applicazione client (Java), che vuole ottenere / impostare lo stato di un'altra applicazione remota (C). La comunicazione tra di loro avviene tramite SIP, che viene eseguito in un altro thread.

L'interfaccia SIP può fare quanto segue:

sendMessage onRequest

Ho due idee per l'architettura:

RPC (JSON-RPC)

Definisci una classe che esegue il marshalling / unmarshalling per JSONRPCRequests e JSONRPCResponse ( link )

Definisci una classe Invoker, che ha qualcosa come un metodo call (server, name, arguments) .

Nella classe Invoker, il nome e gli argomenti vengono inseriti in un JSONRPCRequest e inviati tramite il messaggio SIP sendMessage

Ora arriva il mio problema. Come faccio a restituire il diritto al chiamante? Il flusso di controllo è ora:

Il metodo onRequest viene chiamato, ma ora so se è la risposta alla mia precedente chiamata. Quello che faccio è mettere tutte le risposte che raggiungono il mio server in una mappa, e basta interrogare quell'elenco in Invoker.

Potrebbe essere uno schizzo approssimativo;

Invoker (fornisce l'API al client)

class Invoker {

    private Channel channel;

    public Invoker(Channel channel) { this.channel = channel; }

    public Object call(String server, String name, Object .. args) {
        JSONRPCRequest req = ...;
        channel.sendMessage(server, req.toString());
        while( ! channel.hasResponse(req.id()) {
            Thread.sleep(42);
        }
        return channel.getResponse(req.id()).result();        
    }

}

Canale (interfaccia a messenger):

class Channel {

    private Map<Object, JSONRPCResponse> responses = new //;

    private Sip sip = new Sip() {
        public void onRequest(String msg) {
            JSONRPCResponse response = JSONRPCResponse.parse(msg);
            responses.put(msg.id(), response);
        }
    };

    public void sendMessage(String server, String message) {
        sip.sendMessage();
    }

    public boolean hasResponse onRequest(Object id) {
        responses.hasKey(id);
    }

    public JSONRPCResponse getResponse(Object id) {
        responses.get(id);
        responses.delete(id);
    }

}

SIP (messenger stesso):

abstract class Sip {

    public void sendMessage(String msg) {
        // SIP magic
    }

    public abstract void onRequest(String msg);    
}

C'è un modo migliore per farlo? I miei più grandi problemi / odori di codice sono:

  • il blocco in Invoker
  • il protocollo è in Invoker, forse voglio passare il marshalling a qualcos'altro
  • la mappa come media per ottenere la risposta corretta per una richiesta
  • il metodo astratto SIP sembra strano
  • Nessuna gestione degli errori
  • Nessun timeout

Passaggio del messaggio

C'è un modo semplice per sbarazzarsi di RPC e implementare qualcosa come RPC con il semplice passaggio del messaggio? Qualsiasi suggerimento per il pattern è benvenuto. Non ho bisogno del codice stesso, sto completamente bene solo con l'architettura. Ho provato a google per le implementazioni di passaggio dei messaggi e in che modo hanno effettivamente cambiato lo stato con esso, ma non ho trovato nulla di utile. Come implementare il timeout / gestione degli errori?

Qualsiasi buon libro / letteratura su questo argomento è anche il benvenuto, dato che non ho mai programmato materiale così distribuito.

Qualche altra idea su quale protocollo usare all'interno di SIP per cambiare stato è benvenuta, dato che RPC era il mio pensiero iniziale, e non ho trovato nulla di utile.

Il codice non verrà compilato, immagino, era solo per visualizzare la mia idea.

    
posta reindeer 24.06.2014 - 21:38
fonte

1 risposta

1
  • the blocking in Invoker
  • the protocol is in Invoker, maybe I want to
  • switch marshalling to something else the map as mean to get the
  • correct response for a request the SIP abstract method looks strange
  • No error handling No timeout

Il tuo canale in base alla progettazione è NON BLOCCANTE. La tua implementazione con il ciclo while () non lo rende. L'utilizzo di callback potrebbe renderlo molto più carino. In C i callback possono essere i puntatori dei metodi o Java un gestore associato all'interfaccia.

interface AsyncResponder
void result( Object o );
void error( Object o );

Crea un ID / NUMERO DI SEQUENZA per ogni messaggio e archivia in una mappa l'ID e il riferimento al gestore di callback. Esegui il gestore di callback quando ottieni una risposta.

I timeout di blocco sono molto più semplici. hasResponse (id) potrebbe essere adattato molto facilmente a un intervallo in congiunzione con il meccanismo di timeout.

I timeout non bloccanti hanno il compito di rimuovere la richiamata della richiesta dalla mappa di callback. Se / quando si verifica una risposta, non dovrebbe esserci alcuna callback da eseguire.

La gestione degli errori dovrebbe essere eseguita solo nel gestore richieste. Non globalmente.

Nulla di sbagliato nell'avere il protocollo nell'invocatore a meno che non ti aspetti che l'invocatore cambi continuamente.

Le chiamate RPC devono avere un NUMERO DI SEQUENZA, NOME COMANDO, LUNGHEZZA DEL MESSAGGIO, MESSAGGIO DEL CORPO. Per le risposte il COMMAND NAME potrebbe essere "_result" / "_error". (come fatto in RTMP)

    
risposta data 25.06.2014 - 14:58
fonte

Leggi altre domande sui tag