Come gestire l'interazione dell'utente in microservizi basati su eventi

2

Prima di tutto, è difficile per me spiegare i problemi in modo chiaro, ho cercato di renderlo il più chiaro possibile, ma se hai bisogno di maggiori informazioni, chiedi e cercherò di spiegare come meglio come posso

Sto provando a utilizzare i microservizi, estraendo funzionalità da un monolite nel proprio servizio (multi-tenant). Tuttavia, una delle cose che non riesco a capire come affrontare è questa:

Che cosa succede se un microservizio (attivato da un evento) richiede l'interazione dell'utente?

Ad esempio, al momento abbiamo il seguente flusso (semplificato):

Abbiamo un modulo di donazione in cui qualcuno può fare una donazione. L'utente inserisce le informazioni (importo, metodo di pagamento ecc.). I dati vengono salvati in un database e verrà effettuata una chiamata a una API esterna (fornitore di servizi di pagamento). L'API restituisce un URL in cui l'utente può completare il pagamento effettivo. Reindirizziamo l'utente a tale URL e quando il pagamento è stato completato, l'utente verrà reindirizzato a noi. In tal caso, in caso di successo, attiviamo la donazione, inviamo un'email di conferma e mostriamo un messaggio in caso di esito positivo o negativo.

Problemi

C'è una serie di problemi con cui vorrei liberarmi:

  1. Accoppiamento stretto: la donazione è a conoscenza del pagamento e il pagamento è a conoscenza della donazione
  2. Non possiamo cambiare facilmente i fornitori di pagamento perché i diversi provider hanno bisogno di parametri diversi (il provider I.E. supporta diversi metodi di pagamento rispetto al fornitore b)
  3. Risolvere bug è davvero difficile perché è necessario implementare la correzione a molti clienti diversi.

Quindi quello che penso dovrebbe succedere è dividere questa funzionalità in due servizi separati :

Quando un utente inserisce le proprie informazioni, viene attivato un evento creato da una donazione.

servizio di donazione

Il servizio di donazione crea la donazione (ovviamente nel proprio data store, ecc.) e poi licenzia un evento "pagamento richiesto" con l'importo che deve essere pagato. Si abbona anche a "pagamento riuscito" e "pagamento non riuscito" (e gestisce la logica di conseguenza).

Servizio di pagamento

Il servizio di pagamento si abbona a "payment_requested", chiama l'api esterna, salva i dati necessari per completare il pagamento (URL I.E., ID esterno, ecc.). Quando il pagamento è stato completato (manteniamo fuori dal campo di applicazione la logica effettiva), viene generato l'evento "pagamento riuscito" o "pagamento non riuscito".

Ciò disaccoppia le implementazioni di donazione e pagamento, tuttavia, poiché ciò è asincrono, non ho idea di come reindirizzare l'utente al servizio di pagamento per completare il processo.

Soluzione 1

Una delle soluzioni potrebbe essere che il client è in attesa di un evento tramite polling lungo o websocket, ma probabilmente migliaia di questi potrebbero non essere una grande idea.

Soluzione 2

Un altro potrebbe essere dimenticare l'evento basato e utilizzare le chiamate sincrone a questi servizi, ma ciò significa che le prestazioni del servizio di donazione dipendono dal servizio di pagamento che a sua volta dipende dalle API esterne.

Domanda

Come puoi vedere, trovo difficile trovare una buona soluzione per questo. Forse alcuni di voi possono dare la tua opinione su come questo potrebbe essere implementato.

    
posta LangeJan 10.07.2018 - 12:54
fonte

3 risposte

0

Un buon modo per gestire i servizi di solito veloce ma a volte lento è passare un limite di tempo per la risposta sincrona come parametro aggiuntivo.

Se il servizio può terminare l'intera operazione entro il tempo limite, risponde con 200 OK e il contenuto della risposta. Altrimenti il servizio risponde con 202 - Accettato e restituisce un URL su cui è possibile eseguire il polling dello stato della transazione. Ciò velocizzerà le solite transazioni per una singola chiamata sincrona e gestirà con garbo le lunghe istanze eccezionali nei momenti di pressione e fornirà un meccanismo di polling.

Normalmente il polling non consuma troppe risorse, poiché solo i client che hanno avviato attivamente una transazione eseguiranno il polling del suo stato e non utilizzeranno molte più risorse rispetto all'elaborazione sincrona.

E avrai comunque bisogno di un'implementazione compatibile con browser-refresh, dato che il client può cambiare rete, entrare in una zona radio-morta, cambiare dispositivo, aggiornare il suo browser ... Il che comporterà una richiesta con una nuova connessione (possibilmente da un nuovo indirizzo IP)

    
risposta data 10.07.2018 - 14:36
fonte
0

Non hai bisogno di web socket o lunghi polling per questo.

Servizio di pagamento:

  • CreatePayment (paymentDetails) restituisce l'ID di pagamento e l'URL di reindirizzamento
  • CompletePayment (stringa paymentId, string confirmationCode) controlla il codice di conferma con il provider di pagamento di terze parti e contrassegna il pagamento completo. restituisce il risultato

Iscriviti a / pubblica eventi (CreatePayment, PaymentmentCreated, CompletePayment, PaymentCompleted) o chiama direttamente

    
risposta data 10.07.2018 - 13:32
fonte
0

Tre consigli:

  1. Stuzzica il front-end dal back-end. I microservizi sono interfacce database di back-end migliori. Non confondere con l'interazione front-end.
  2. Mantieni fermamente l'orchestrazione nell'interazione front-end / utente. I componenti back-end dovrebbero essere completamente indipendenti dall'orchestrazione.
  3. Non utilizzare eventi inter-sistema per l'interazione / orchestrazione dell'utente. Gli eventi sono soggetti a latenza e non sono affidabili. Latenza e inaffidabilità per interfacce utente molto scarse.
risposta data 10.07.2018 - 15:22
fonte

Leggi altre domande sui tag