Come configurare un'architettura di microservizi in Ruby: una guida passo passo
Pubblicato: 2022-03-11Cosa sono i microservizi?
I microservizi sono una delle ultime tendenze nella progettazione di software in cui più servizi indipendenti comunicano tra loro e dispongono di processi e risorse propri. Questo approccio è diverso da un tipico progetto di applicazione client-server. La normale applicazione client-server è costituita da uno o più client, un back-end monolitico che include tutti i dati e la logica del dominio e un'API che consente ai client di accedere al back-end e alle sue funzionalità.
In un'architettura di microservizi, il backend monolitico descritto è invece sostituito da una suite di servizi distribuiti. Questo design consente una migliore separazione delle responsabilità, una manutenzione più semplice, una maggiore flessibilità nella scelta delle tecnologie per ciascun servizio e una più facile scalabilità e tolleranza ai guasti. Allo stesso tempo, i sistemi distribuiti complessi hanno la loro serie di sfide. Hanno maggiori possibilità di avere a che fare con condizioni di gara e sono più difficili da eseguire il debug poiché i problemi non sono facilmente individuabili in un singolo servizio, ma sono invece distribuiti attraverso molti. Se non viene fatto uno sforzo per seguire le migliori pratiche durante la costruzione di un tale sistema, potresti trovarti circondato da incendi che non sai come spegnere. È necessario prestare particolare attenzione ai contratti di carico utile dei servizi, poiché le modifiche in un servizio possono influire su tutti i suoi clienti e, di conseguenza, su tutta la suite di servizi del back-end.
Tutte queste considerazioni sono importanti, ma supponiamo che tu le abbia già riflettute. Ora quello che vuoi è trovare un modo per creare un back-end di microservizi da solo. Quindi tuffiamoci dentro.
Come configurare un'architettura di microservizi
Attualmente ci sono molti modi in cui puoi configurare i tuoi microservizi e in questa guida ci concentreremo su un'architettura di broker.
Un'architettura del broker
Un'architettura di broker è uno dei modi in cui puoi far comunicare i tuoi servizi tra loro. In esso, tutti i servizi circondano un server di messaggistica, il broker e tutti sono collegati ad esso. I servizi inviano messaggi al broker, che quindi sa di quale altro servizio o servizi ha bisogno per inoltrare questi messaggi. In questo modo, i servizi non devono conservare le informazioni su altri servizi. Invece, si affidano al broker per prendersi cura di tutta la messaggistica e ciò consente loro di essere isolati e concentrati solo sul loro particolare dominio. Un broker può anche memorizzare i messaggi quando i loro ricevitori sono inattivi, consentendo a mittenti e destinatari di non essere costretti a essere attivi contemporaneamente, consentendo così un isolamento ancora maggiore. Naturalmente, questa soluzione presenta degli svantaggi in quanto il broker può diventare rapidamente un collo di bottiglia poiché tutta la comunicazione deve attraversarlo e può anche diventare un singolo punto di errore per il tuo back-end. Tuttavia, ci sono alcuni modi per mitigare questi problemi. Un modo è avere più istanze del broker in esecuzione in parallelo, il che consentirebbe una migliore tolleranza agli errori del sistema. Un altro modo sarebbe usare altre architetture. Le architetture alternative differiscono dall'architettura che implementeremo in questa guida non utilizzando un broker o utilizzando un'architettura broker diversa o utilizzando un protocollo di messaggistica diverso come HTTP.
Comunicazione tra servizi
In questa guida utilizzeremo ZeroMQ per gestire la comunicazione tra i servizi e il broker.
ZeroMQ fornisce un livello di astrazione del protocollo che gestisce messaggi asincroni multiparte su trasporti casuali. I vantaggi dell'utilizzo di ZeroMQ per la messaggistica tra servizi e broker non rientrano nell'ambito di questa guida, quindi non li esamineremo qui, ma se vuoi saperne di più, dai un'occhiata al seguente articolo di Quora. Se sei interessato a scoprire altri modi per far dialogare i tuoi servizi, ti suggerisco di dare un'occhiata all'articolo Broker vs. Brokerless per vedere cos'altro puoi ottenere.
Creazione della suite di microservizi
Questo articolo ti guiderà attraverso tutti i passaggi necessari per creare la tua suite di microservizi. Il nostro sistema sarà composto da un broker e un servizio. Utilizzeremo anche un piccolo script client per testare le chiamate alla suite di servizi, ma tieni presente che il codice client può essere facilmente utilizzato ovunque.
Quindi, iniziamo a costruire.
Iniziare
Innanzitutto, assicuriamoci di avere tutto il necessario per eseguire il broker e il servizio. Innanzitutto, inizia scaricando e installando Node.js, ZeroMQ e Git sul tuo computer. Se stai usando OSX, ci sono pacchetti homebrew per ciascuno di essi e la maggior parte delle distribuzioni Linux ha un pacchetto anche per ciascuno di essi, quindi non dovresti avere problemi con questo. Gli utenti Windows possono semplicemente utilizzare i collegamenti per il download forniti sopra.
Gestire il broker
Dopo aver installato tutte le dipendenze richieste, mettiamo in funzione il nostro broker. In questa guida utilizziamo un'implementazione Node.js del broker che fa parte della ZMQ Service Oriented Suite. Puoi trovare il codice e la documentazione su GitHub. Per eseguire il broker, clona prima un bootstrap Broker sulla tua macchina. Questo repository è un bootstrap per l'utilizzo della libreria del broker sopra. Nota, questo passaggio non è richiesto poiché la libreria originale è essa stessa eseguibile, ma la differenza tra i due è che nel repository bootstrap è possibile modificare le configurazioni predefinite.
Quindi, per prima cosa, usa il seguente comando Git per scaricare il progetto sul tuo computer:
$ git clone [email protected]:dadah/zmq-broker-bootstrap.git
Dopo averlo fatto, spostati nella directory creata:
$ cd zmq-broker-bootstrap
Ora installa le dipendenze del pacchetto:
$ npm install
Il broker è ora pronto. Per eseguire il tuo broker, esegui il seguente comando:
$ bin/zss-broker run
Puoi trovare i file di configurazione per ogni ambiente nella directory config/
. Questa è la configurazione di sviluppo predefinita:
{ "broker": { "backend": "tcp://127.0.0.1:7776", "frontend": "tcp://127.0.0.1:7777" }, "log": { "consolePlugin": { "level": "debug" } } }
Il parametro backend
definisce l'indirizzo ip:port
del back-end e del front-end del broker. L'indirizzo di back-end è il punto in cui il broker riceve le richieste e risponde ai servizi e l'indirizzo di front-end è il punto in cui riceve e invia ai client del servizio. Puoi anche impostare il livello di registrazione modificando log.consolePlugin.level
. I valori possibili sono trace
, debug
, info
, warn
ed error
e determinano la quantità di informazioni di registrazione che il processo del broker produrrà.
Esecuzione del servizio
Dopo aver attivato il tuo broker, è il momento di sviluppare il tuo primo microservizio Ruby. Inizia aprendo una nuova finestra della console. Quindi, crea una directory in cui verranno archiviati i tuoi servizi e quindi vai a quella directory. In questa guida utilizziamo il client Ruby e il servizio di ZMQ SOA Suite. È disponibile un servizio bootstrap "Hello world", quindi usiamolo per eseguire il nostro primo microservizio.
Vai alla directory dei tuoi servizi e clona il repository bootstrap:
$ git clone [email protected]:dadah/zmq-service-suite-ruby-bootstrap.git
Vai alla directory appena creata:
$ cd zmq-service-suite-ruby-bootstrap
Ora installa tutte le dipendenze:
$ bundle install
Per avviare il servizio, eseguire il comando seguente:
$ bin/zss-service run
Grande. Hai il tuo primo servizio attivo e funzionante.
Se vai alla finestra della console in cui hai lasciato in esecuzione il tuo broker, puoi vedere il seguente output:
2015-12-15 16:45:05 | INFO | BROKER - Async Broker is waiting for messages... 2015-12-15 16:45:14 | DEBUG | BACKEND - received from: hello-word#aaa65374-8585-410a-a41d-c8a5b024553b rid: 76f50741-913a-43b9-94b0-36d8f7bd75b1 2015-12-15 16:45:14 | DEBUG | BACKEND - routing from: hello-word#aaa65374-8585-410a-a41d-c8a5b024553b rid: 76f50741-913a-43b9-94b0-36d8f7bd75b1 to SMI.UP request... 2015-12-15 16:45:14 | INFO | SMI - SMI register for sid: HELLO-WORD instance: hello-word#aaa65374-8585-410a-a41d-c8a5b024553b! 2015-12-15 16:45:14 | DEBUG | BACKEND - reply to: hello-word#aaa65374-8585-410a-a41d-c8a5b024553b rid: 76f50741-913a-43b9-94b0-36d8f7bd75b1 with status: 200 2015-12-15 16:45:15 | DEBUG | BACKEND - received from: hello-word#aaa65374-8585-410a-a41d-c8a5b024553b rid: 3b3a0416-73fa-4fd2-9306-dad18bc0502a 2015-12-15 16:45:15 | DEBUG | BACKEND - routing from: hello-word#aaa65374-8585-410a-a41d-c8a5b024553b rid: 3b3a0416-73fa-4fd2-9306-dad18bc0502a to SMI.HEARTBEAT request... 2015-12-15 16:45:15 | DEBUG | BACKEND - reply to: hello-word#aaa65374-8585-410a-a41d-c8a5b024553b rid: 3b3a0416-73fa-4fd2-9306-dad18bc0502a with status: 200 2015-12-15 16:45:16 | DEBUG | BACKEND - received from: hello-word#aaa65374-8585-410a-a41d-c8a5b024553b rid: b3044c24-c823-4394-8204-1e872f30e909 2015-12-15 16:45:16 | DEBUG | BACKEND - routing from: hello-word#aaa65374-8585-410a-a41d-c8a5b024553b rid: b3044c24-c823-4394-8204-1e872f30e909 to SMI.HEARTBEAT request... 2015-12-15 16:45:16 | DEBUG | BACKEND - reply to: hello-word#aaa65374-8585-410a-a41d-c8a5b024553b rid: b3044c24-c823-4394-8204-1e872f30e909 with status: 200
Questo registro indica che il broker ha riconosciuto l'esistenza di un nuovo servizio e sta ricevendo messaggi di heartbeat da esso. Ogni secondo, il servizio invia un messaggio heartbeat al broker, in modo che sappia che l'istanza del servizio è attiva.
Consumare dal Servizio
Quindi ora abbiamo un servizio in esecuzione, come lo usiamo?
Nel repository bootstrap, c'è un client fittizio che puoi utilizzare per testare il tuo servizio "Hello World". Basta aprire una nuova finestra o scheda della console e andare alla directory del servizio. Una volta che sei lì, esegui il seguente comando:
$ bin/zss-client
Dovresti vedere qualcosa del genere:
15-49-15 16:49:54 | INFO | ZSS::CLIENT - Request 90a88081-3485-45b6-91b3-b0609d64592a sent to HELLO-WORD:*#HELLO/WORLD with 1.0s timeout 15-49-15 16:49:54 | INFO | ZSS::CLIENT - Received response to 90a88081-3485-45b6-91b3-b0609d64592a with status 200 "Hello World"
Se vai alla finestra della console in cui è in esecuzione il tuo servizio, dovresti vedere questo:
Started hello-word daemon... 15-45-15 16:45:14 | INFO | ZSS::SERVICE - Starting SID: 'HELLO-WORD' ID: 'hello-word#aaa65374-8585-410a-a41d-c8a5b024553b' Env: 'development' Broker: 'tcp://127.0.0.1:7776' 15-49-15 16:49:54 | INFO | ZSS::SERVICE - Handle request for HELLO-WORD:*#HELLO/WORLD 15-49-15 16:49:54 | INFO | ZSS::SERVICE - Reply with status: 200
Buona. Hai appena lanciato e consumato il tuo microservizio "Hello World". Questo non è, tuttavia, ciò che ci siamo prefissati di fare. Vogliamo costruire i nostri servizi. Andiamo a questo, allora.
Costruire il tuo servizio
Per prima cosa, interrompiamo il nostro servizio "Hello World". Vai alla finestra della console del servizio e premi Ctrl+C
per interrompere il servizio. Successivamente dobbiamo trasformare il nostro servizio "Hello World" nel servizio "Persona".
Struttura del codice
Iniziamo dando un'occhiata all'albero del codice del progetto. Si presenta così:
- La directory
bin
è dove memorizzi gli script che avviano il tuo servizio. - La directory
config
memorizza tutti i file di configurazione.- Il file
boot.rb
è dove puoi aggiungere tutte le dipendenze del servizio. Se lo apri, puoi notare che ci sono molte dipendenze già elencate lì. Se hai bisogno di aggiungerne altri, è qui che dovresti farlo. - Il file
application.yml
memorizza tutte le impostazioni dell'applicazione. Daremo un'occhiata a questo file più avanti. - Nella directory
config/initializers
puoi aggiungere i tuoi script di inizializzazione. È possibile, ad esempio, aggiungere qui le impostazioni per le connessioni ActiveRecord o Redis. Gli script aggiunti a questa directory verranno eseguiti all'avvio del servizio.
- Il file
- Nella directory
db/migrate
puoi memorizzare le tue migrazioni ActiveRecord o Sequel se ne hai. In caso contrario, è possibile eliminare del tutto questa directory. - La directory
lib
è dove risiede il codice dell'applicazione principale.- Il file
settings.rb
carica semplicemente il fileapplication.yml
e lo rende disponibile in tutto l'ambito del servizio, in modo che tu possa accedere alle tue configurazioni ovunque. Ad esempio,Settings.broker.backend
restituisce l'indirizzo di backend del broker che hai definito nel file YML sopra. - Il file
service_register.rb
è dove registri i tuoi servizi e percorsi di servizio. Lo spiegheremo dopo. - Il file
hello_world_service.rb
definisce gli endpoint del servizio "Hello World". - La directory
lib/daos
è dove memorizzi i tuoi oggetti ActiveModel se stai usando ActiveRecord, o qualsiasi altro oggetto di accesso ai dati che potresti eventualmente creare, come i tuoi modelli Sequel. - La directory
lib/dtos
memorizza gli oggetti di trasferimento dati. Questi oggetti sono quelli che vengono eventualmente restituiti ai client del servizio. - La directory
lib/repositories
memorizza i tuoi repository. I repository sono oggetti che consentono ai servizi di accedere ai dati e sono gli unici oggetti autorizzati a gestire DAO. Quindi, se un servizio desidera un gruppo di istanze "Hello World", le chiederà al repository. Il repository, a sua volta, utilizza i DAO appropriati per recuperare i dati rilevanti dal database. I dati vengono quindi mappati in una raccolta DTO "HelloWorld" o DTO "HelloWorld" adatta che viene restituita al servizio. - La directory
lib/repositories/mappers
è dove memorizzi i tuoi mappatori. I mapper sono oggetti che convertono DAO in DTO e viceversa.
- Il file
Il file application.yml
dalla directory config
il seguente aspetto:

defaults: &defaults broker: backend: tcp://127.0.0.1:7776 frontend: tcp://127.0.0.1:7777 logging: console: level: info development: <<: *defaults test: <<: *defaults production: <<: *defaults
Questa impostazione imposta semplicemente l'indirizzo back-end e front-end del broker e il livello di registrazione.
Se tutto questo sembra confuso finora, non preoccuparti perché diventerà più chiaro man mano che andiamo avanti.
Servizio “Persona”.
Quindi, continuiamo con il nostro servizio “Persona”. Iniziamo configurando la connessione al database. Apri il file config/initializers/active_record.rb
e decommenta l'unica riga lì. Quindi, aggiungi la seguente voce alla tua configurazione di sviluppo in application.yml
in modo che assomigli a questa:
defaults: &defaults broker: backend: tcp://127.0.0.1:7776 frontend: tcp://127.0.0.1:7777 logging: console: level: info database: adapter: postgresql database: zss-tutorial-development
Ora che hai aggiunto la configurazione del database, devi creare il database. Al momento, non c'è modo di farlo automaticamente a meno che tu non stia utilizzando un database PostgreSQL predefinito, nel qual caso puoi semplicemente eseguire:
$ rake db:create
Se preferisci un altro database, devi aggiungere la gem appropriata al gemfile e quindi installare il progetto in bundle.
La prossima è la migrazione. Per questo, crea semplicemente il file db/migrate
chiamato 000_creates_persons.rb
:
$ touch db/migrate/000_creates_persons_table.rb
Apri il file e crea la migrazione come faresti con una normale migrazione Rails:
class CreatesPersons < ActiveRecord::Migration def change create_table :persons do |t| t.name t.timestamps end end end
Quindi, eseguilo:
$ rake db:migrate == 0 CreatesPersons: migrating ================================================ -- create_table(:persons) DEPRECATION WARNING: `#timestamp` was called without specifying an option for `null`. In Rails 5, this behavior will change to `null: false`. You should manually specify `null: true` to prevent the behavior of your existing migrations from changing. (called from block in change at /Users/francisco/Code/microservices-tutorial/db/migrate/000_creates_persons.rb:6) -> 0.0012s == 0 CreatesPersons: migrated (0.0013s) =======================================
Ora che abbiamo creato la nostra tabella, creiamo un modello per essa. Crea il file lib/daos/person.rb
:
$ touch lib/daos/person.rb
Modificalo in questo modo:
module DAO class Person < ActiveRecord::Base end end
C'è il tuo modello Ora devi creare un modello DTO per una "Persona" in modo da poterlo restituire al cliente. Crea il file lib/dtos/person.rb
:
$ touch lib/dtos/person.rb
Modificalo in questo modo:
module DTO class Person < Base attr_reader :id, :name end end
Successivamente devi creare un Mapper per convertire il DAO "Persona" in un DTO "Persona". Crea il file lib/repositories/mappers/person.rb
e modificalo in questo modo:
module Mapper class Person < Mapper::Base def self.to_dao dto_instance DAO::Person.new id: dto_instance.id, name: dto_instance.name end def self.to_dto dao_instance DTO::Person.new id: dao_instance.id, name: dao_instance.name end end end
Qui, Mapper::Base
richiede di implementare self.to_dao
e self.to_dto
. Se non desideri farlo, puoi invece implementare self.map
e sovrascrivere Mapper::Base.map
che chiama to_dao
o to_dto
, a seconda che l'attributo che riceve sia un DAO o un DTO.
Ora hai un DAO per accedere al tuo database, un DTO per inviarlo al client e un Mapper per convertirlo nell'altro. È ora possibile utilizzare queste tre classi all'interno di un repository per creare la logica che consente di ottenere persone dal database e restituire una raccolta corrispondente di DTO.
Creiamo allora il repository. Crea il file lib/repositories/person.rb
:
$ touch lib/dtos/person.rb
Modificalo in questo modo:
module Repository class Person < Repository::Base def get DAO::Person.all.map do |person| Mapper::Person.map(person) end end end end
Questo repository ha solo il metodo dell'istanza get
che semplicemente ottiene tutte le persone dal database e le mappa in una raccolta di DTO persona - abbastanza semplice. Mettiamo insieme tutto questo ora. Non resta che creare il servizio e l'endpoint che chiama questo repository. Per farlo, creiamo il file lib/person_service.rb
:
$ touch lib/person_service.rb
Modificalo in questo modo:
class PersonService < BaseService attr_reader :person_repo def initialize @person_repo = Repository::Person.new end def get payload, headers persons = person_repo.get() if persons.empty? raise ZSS::Error.new(404, "No people here") else persons.map &:serialize end end end
Il servizio "Persona" inizializza il repository nel suo inizializzatore. Tutti i metodi di istanza pubblica del servizio "Persona" hanno payload e intestazioni che puoi omettere se non ne hai bisogno. Entrambe sono Hashie::Mash
e memorizzano le variabili inviate all'endpoint, come attributi o intestazioni, e le loro risposte imitano le risposte HTTP poiché ogni risposta ha un codice di stato che i client possono utilizzare per scoprire il risultato delle richieste inviate al servizio, insieme al carico utile di risposta del servizio. I codici di risposta sono gli stessi che ti aspetteresti da un server HTTP. Ad esempio, una richiesta riuscita restituirà un codice di stato 200, insieme al payload della risposta. Se si verifica un errore del servizio, il codice di stato sarà 500 e se c'è qualcosa di sbagliato nei parametri inviati al server, il codice di stato sarà 400. Il servizio può rispondere con la maggior parte dei codici di stato HTTP insieme al suo carico utile. Quindi, se ad esempio desideri che il tuo servizio comunichi ai suoi clienti quando non sono autorizzati ad accedere a un determinato endpoint, puoi farlo rispondendo con un codice 403. Puoi vedere un altro esempio di codici di risposta se guardi indietro al nostro codice di servizio sopra. Nell'endpoint get
, stiamo restituendo il codice di stato 404 insieme al messaggio facoltativo "Nessuna persona qui" quando non vengono trovate persone, proprio come un server HTTP restituirebbe un 404 se non ci sono risorse disponibili. Se il repository restituisce effettivamente persone, il servizio serializza i DTO e li restituisce al client. Ogni DTO ha un serializzatore predefinito che restituisce un oggetto JSON con le chiavi e i valori corrispondenti definiti come attr_reader
o attr_accessible
nella definizione DTO. Ovviamente puoi sovrascrivere il serializzatore definendo il tuo metodo serialize nelle tue classi DTO.
Ora che abbiamo un servizio definito, dobbiamo registrarlo. Questo è il passo finale. Apri il file lib/service_register.rb
e sostituisci tutte le occorrenze di "HelloWorld" con "Person", in modo che il file alla fine assomigli in qualche modo a questo:
module ZSS class ServiceRegister def self.get_service config = Hashie::Mash.new( backend: Settings.broker.backend ) service = ZSS::Service.new(:person, config) personInstance = PersonService.new service.add_route(personInstance, :get) return service end end end
Come probabilmente avrai notato, c'è un piccolo cambiamento nella chiamata add_route
. Abbiamo rimosso la stringa "HELLO/WORLD". Questo perché la stringa è necessaria solo se il verbo di servizio non corrisponde al metodo che lo implementa. Nel nostro caso, quando si chiama il servizio persona con il verbo GET, il metodo da chiamare è get
, quindi possiamo omettere la stringa.
La classe ServiceRegister
è dove devi definire il metodo self.get_service
. Questo metodo inizializza il servizio e lo connette al back-end del broker. Quindi abbina le route su quel servizio ai metodi in una o più definizioni di servizio. Ad esempio, nel seguente caso, crea il servizio e lo lega al broker:
config = Hashie::Mash.new( backend: Settings.broker.backend ) service = ZSS::Service.new(:person, config)
Quindi istanzia un gestore del servizio:
personInstance = PersonService.new
Successivamente, il gestore del servizio è associato al servizio:
service.add_route(personInstance, :get)
Infine, deve restituire l'istanza del servizio.
return service
Ora, c'è solo un ultimo passaggio prima di poter lanciare il nostro servizio "Persona"; dobbiamo creare uno script eseguibile per questo. Ne abbiamo già uno per "HelloService". Quindi, apri il file bin/zss-service
, sostituisci "hello-word" con "person" e salva il file. Torna alla console ed esegui:
$ bin/zss-service run Starting person: PID: ./log LOGS: ./log Started person daemon... 15-29-15 19:29:54 | INFO | ZSS::SERVICE - Starting SID: 'PERSON' ID: 'person#d3ca7e1f-e229-4502-ac2d-0c01d8c285f8' Env: 'development' Broker: 'tcp://127.0.0.1:7776'
Questo è tutto. Hai appena avviato per la prima volta il tuo servizio "Persona". Ora proviamolo. Apri il file bin/zss-client
, cambia la variabile sid
in "person" e cambia la chiamata del client da hello_world()
a get()
. Una volta fatto, esegui il client in una nuova finestra:
$ bin/zss-client /Users/francisco/.rvm/gems/ruby-2.1.2/gems/zss-0.3.4/lib/zss/client.rb:41:in `new': No people here (ZSS::Error) from /Users/francisco/.rvm/gems/ruby-2.1.2/gems/zss-0.3.4/lib/zss/client.rb:41:in `call' from /Users/francisco/.rvm/gems/ruby-2.1.2/gems/zss-0.3.4/lib/zss/client.rb:55:in `method_missing' from bin/zss-client:12:in `<main>'
Come puoi vedere, hai rilevato un ZSS::Error
. Questo perché generiamo un errore quando non vengono trovate persone dal servizio e non abbiamo ancora persone nel database del nostro servizio.
Gestiamo questo errore allora. Apri zss-client
e modificalo in questo modo:
begin client = ZSS::Client.new(sid, config) p client.get() rescue ZSS::Client => e if e.code == 404 p e.message else raise e end end
Ora stiamo stampando il messaggio di errore quando il codice di errore è 404, sollevando l'errore se è diverso. Vediamolo in azione eseguendo nuovamente il nostro client:
$ bin/zss-client "No people here"
Eccellente. Ora aggiungiamo alcune persone al nostro tavolo e vediamo se vengono restituite dal servizio al nostro cliente. Per fare ciò, apri semplicemente una console di servizio:
$ rake service:console
Aggiungi alcune persone:
$ rake service:console [1] pry(main)> DAO::Person.create name: 'John' => #<DAO::Person:0x007fe51bbe9d00 id: 1, name: "John", created_at: 2015-12-16 13:22:37 UTC, updated_at: 2015-12-16 13:22:37 UTC> [2] pry(main)> DAO::Person.create name: 'Mary' => #<DAO::Person:0x007fe51c1dafe8 id: 2, name: "Mary", created_at: 2015-12-16 13:22:42 UTC, updated_at: 2015-12-16 13:22:42 UTC> [3] pry(main)> DAO::Person.create name: 'Francis' => #<DAO::Person:0x007fe51bc11698 id: 3, name: "Francis", created_at: 2015-12-16 13:22:53 UTC, updated_at: 2015-12-16 13:22:53 UTC> [4] pry(main)> exit
Ora, esegui di nuovo il tuo client.
$ bin/zss-client [{"id"=>1, "name"=>"John"}, {"id"=>2, "name"=>"Mary"}, {"id"=>3, "name"=>"Francis"}]
Ecco qua.
Considerazioni finali
Esaminando il codice fornito in questa guida, potresti pensare che ci siano molti passaggi non necessari, come la creazione di repository o DTO, e avresti ragione. Tutto ciò di cui hai bisogno per avere un servizio "Persona" funzionante sarebbe la tua classe di servizio e il tuo DAO, che potresti chiamare direttamente dalla classe di servizio. Tuttavia, è buona norma seguire lo schema descritto in questo articolo, poiché consente di mantenere la logica del servizio separata dalla manipolazione dell'archiviazione dei dati. I servizi dovrebbero concentrarsi solo sulla loro logica e i repository dovrebbero gestire tutte le interazioni con l'archiviazione dei dati. I DTO determinano i payload e la serializzazione dei tuoi servizi e i DAO si occupano solo di ottenere i dati dall'archiviazione. Le convenzioni e le tecniche descritte in questa guida sono note come pattern di repository, che puoi controllare nell'immagine seguente.
Vorrei concludere chiedendo a chiunque lo abbia trovato utile di contribuire alla suite di servizi SOA, ampliandola e potenziandola in qualsiasi modo. Tutte le vostre richieste di fork e pull sono benvenute.
Spero che questo ti aiuterà a iniziare con i microservizi. Se vuoi controllare il codice del servizio, una versione completa è disponibile su GitHub.