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.