Cum să configurați o arhitectură de microservicii în Ruby: un ghid pas cu pas

Publicat: 2022-03-11

Ce sunt microserviciile?

Microserviciile sunt una dintre cele mai recente tendințe în proiectarea software-ului în care mai multe servicii independente comunică între ele și au propriile procese și resurse. Această abordare diferă de un design tipic de aplicație client-server. Aplicația obișnuită client-server constă dintr-unul sau mai mulți clienți, un back-end monolitic care include toate datele și logica domeniului și un API care permite clienților să acceseze back-end-ul și funcționalitatea acestuia.

Microserviciile înlocuiesc serverele back-end monolitice clasice
Tweet

Într-o arhitectură de microservicii, backend-ul monolitic descris este în schimb înlocuit de o suită de servicii distribuite. Acest design permite o mai bună separare a responsabilităților, o întreținere mai ușoară, o flexibilitate mai mare în alegerea tehnologiilor pentru fiecare serviciu și o scalabilitate mai ușoară și toleranță la erori. În același timp, sistemele complexe distribuite au setul lor de provocări. Au o șansă mai mare de a face față condițiilor de cursă și sunt mai greu de depanat, deoarece problemele nu sunt ușor identificate la un singur serviciu, ci sunt distribuite prin mai multe. Dacă nu se depune eforturi pentru a respecta cele mai bune practici în timpul construirii unui astfel de sistem, s-ar putea să te trezești înconjurat de incendii pe care nu știi cum să le stingi. O atenție deosebită trebuie acordată contractelor de sarcină utilă a serviciilor, deoarece modificările unui serviciu pot afecta toți clienții săi și, în consecință, toată suita de servicii a back-end-ului.

Toate aceste considerații sunt importante, dar să presupunem că te-ai gândit deja la ele. Acum ceea ce doriți este să găsiți o modalitate de a construi un back-end de microservicii pe cont propriu. Așa că haideți să ne aruncăm direct în asta.

Cum se configurează o arhitectură de microservicii

În prezent, există multe moduri în care vă puteți configura microservicii, iar în acest ghid ne vom concentra pe o arhitectură de broker.

O arhitectură de broker

Arhitectura brokerului, cu un broker (B) în mijloc și patru microservicii înconjurătoare, le numesc N, S, E, W. Calea cerere/răspuns începe la o intrare din afara arhitecturii, apoi urmează calea N, B, E, B, S, B, W, B, E, B, N, înainte de a ieși în sfârșit ca ieșire.

O arhitectură de broker este una dintre modalitățile prin care puteți face ca serviciile dvs. să comunice între ele
Tweet

O arhitectură de broker este una dintre modalitățile prin care puteți face ca serviciile dvs. să comunice între ele. În el, toate serviciile înconjoară un server de mesagerie, brokerul și toate sunt conectate la acesta. Serviciile trimit mesaje brokerului, care știe apoi de ce alt serviciu sau servicii are nevoie pentru a redirecționa aceste mesaje. În acest fel, serviciile nu trebuie să păstreze informații despre alte servicii. În schimb, se bazează pe broker pentru a avea grijă de toate mesajele și le permite să fie izolate și concentrate doar pe domeniul lor particular. Un broker poate stoca, de asemenea, mesaje atunci când receptorii lor sunt în jos, permițând expeditorilor și receptorilor să nu fie forțați să fie activi simultan, permițând astfel o izolare și mai mare. Desigur, această soluție are dezavantaje, deoarece brokerul poate deveni rapid un blocaj, deoarece toată comunicarea trebuie să treacă prin ele și poate deveni, de asemenea, un singur punct de eșec pentru backend-ul tău. Cu toate acestea, există câteva modalități de a atenua aceste probleme. O modalitate este de a avea mai multe instanțe ale brokerului care rulează în paralel, ceea ce ar permite o mai bună toleranță la erori ale sistemului. O altă modalitate ar fi folosirea altor arhitecturi. Arhitecturile alternative diferă de arhitectura pe care o vom implementa în acest ghid prin faptul că nu folosim un broker, sau prin utilizarea unei arhitecturi broker diferite sau prin utilizarea unui alt protocol de mesagerie, cum ar fi HTTP.

Comunicarea între servicii

În acest ghid, vom folosi ZeroMQ pentru a gestiona comunicarea dintre servicii și broker.

Stiva ZeroMQ. În partea de sus este un bloc cu o elipsă apoi semnul ZeroMQ. Un bloc de jos are, de sus în jos: transport, rețea, legătură de date și fizic.

ZeroMQ oferă un strat de abstracție a protocolului care gestionează mesajele asincrone cu mai multe părți peste transporturi aleatorii. Avantajele utilizării ZeroMQ pentru mesageria între servicii și broker nu fac obiectul acestui ghid, așa că nu le vom analiza chiar aici, dar dacă doriți să aflați mai multe despre ele, consultați următorul articol Quora. Dacă sunteți interesat să aflați alte modalități de a face serviciile dvs. să vorbească între ele, vă sugerez să aruncați o privire la articolul Broker vs. Brokerless pentru a vedea ce altceva se poate realiza.

Construirea Suitei de Microservicii

Acest articol vă va ghida prin toți pașii necesari pentru a vă crea suita de microservicii. Sistemul nostru va consta dintr-un broker și un serviciu. De asemenea, vom folosi un mic script client pentru a testa apelurile către suita de servicii, dar rețineți că codul clientului poate fi utilizat cu ușurință oriunde.

Deci, să începem să construim.

Noțiuni de bază

În primul rând, să ne asigurăm că aveți tot ce aveți nevoie pentru a rula brokerul și serviciul. Mai întâi, începeți prin a descărca și instala Node.js, ZeroMQ și Git pe computer. Dacă utilizați OSX, există pachete homebrew pentru fiecare dintre ele, iar majoritatea distribuțiilor Linux au și un pachet pentru fiecare dintre ele, așa că nu ar trebui să aveți nicio problemă cu asta. Utilizatorii Windows pot folosi pur și simplu linkurile de descărcare furnizate mai sus.

Conducerea Brokerului

După instalarea tuturor dependențelor necesare, să punem în funcțiune brokerul nostru. În acest ghid, folosim o implementare Node.js a brokerului, care face parte din ZMQ Service Oriented Suite. Puteți găsi codul și documentația acestuia pe GitHub. Pentru a rula brokerul, mai întâi clonați un bootstrap Broker pe computer. Acest depozit este un bootstrap pentru utilizarea bibliotecii broker de mai sus. Rețineți, acest pas nu este necesar, deoarece biblioteca originală este ea însăși rulabilă, dar diferența dintre cele două este că în depozitul de bootstrap puteți modifica configurațiile implicite.

Deci, mai întâi, utilizați următoarea comandă Git pentru a descărca proiectul pe mașina dvs.:

 $ git clone [email protected]:dadah/zmq-broker-bootstrap.git

După ce ați făcut asta, treceți la directorul creat:

 $ cd zmq-broker-bootstrap

Acum instalați dependențele pachetului:

 $ npm install

Brokerul este acum gata. Pentru a rula brokerul, executați următoarea comandă:

 $ bin/zss-broker run

Puteți găsi fișiere de configurare pentru fiecare mediu în directorul config/ . Aceasta este configurația implicită de dezvoltare:

 { "broker": { "backend": "tcp://127.0.0.1:7776", "frontend": "tcp://127.0.0.1:7777" }, "log": { "consolePlugin": { "level": "debug" } } }

Parametrul backend definește adresa ip:port a back-end-ului și front-end-ului brokerului. Adresa back-end este locul unde brokerul primește cererile de la servicii și răspunde la acestea, iar adresa front-end este locul unde primește și trimite către clienții serviciului. De asemenea, puteți seta nivelul de înregistrare schimbând log.consolePlugin.level . Valorile posibile sunt trace , debug , info , warn și error , și ele determină cantitatea de informații de înregistrare pe care procesul brokerului va ieși.

Rularea Serviciului

După ce ați activat brokerul, este timpul să vă dezvoltați primul microserviciu Ruby. Începeți prin a deschide o nouă fereastră de consolă. Apoi, creați un director în care vor fi stocate serviciile dvs. și apoi mergeți la acel director. În acest ghid, folosim clientul Ruby și serviciul ZMQ SOA Suite. Există un serviciu bootstrap „Hello world” disponibil, așa că haideți să-l folosim pentru a rula primul nostru microserviciu.

Accesați directorul de servicii și clonați depozitul de bootstrap:

 $ git clone [email protected]:dadah/zmq-service-suite-ruby-bootstrap.git

Accesați directorul nou creat:

 $ cd zmq-service-suite-ruby-bootstrap

Acum instalați toate dependențele:

 $ bundle install

Pentru a porni serviciul, executați următoarea comandă:

 $ bin/zss-service run

Grozav. Aveți primul serviciu pus în funcțiune.

Dacă accesați fereastra consolei în care ați lăsat brokerul în funcțiune, puteți vedea următoarea ieșire:

 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

Acest jurnal înseamnă că brokerul a recunoscut existența unui nou serviciu și primește mesaje de bătăi inimii de la acesta. În fiecare secundă, serviciul trimite un mesaj de bătăi inimii către broker, astfel încât să știe că instanța serviciului este activată.

Consumul din Serviciu

Deci acum avem un serviciu care rulează, cum îl folosim?

În depozitul bootstrap, există un client inactiv pe care îl puteți utiliza pentru a vă testa serviciul „Hello World”. Pur și simplu deschideți o nouă fereastră sau filă de consolă și accesați directorul de servicii. Odată ce sunteți acolo, rulați următoarea comandă:

 $ bin/zss-client

Ar trebui să vezi așa ceva:

 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"

Dacă accesați fereastra consolei în care rulează serviciul dvs., ar trebui să vedeți asta:

 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

Bun. Tocmai ați lansat și ați consumat microserviciul „Hello World”. Acest lucru nu este, însă, ceea ce ne-am propus. Dorim să ne construim serviciile. Să trecem la asta, atunci.

Construirea serviciului dvs

În primul rând, să oprim serviciul nostru „Hello World”. Accesați fereastra consolei serviciului și apăsați Ctrl+C pentru a opri serviciul. În continuare, trebuie să transformăm serviciul nostru „Hello World” în serviciul „Persoană”.

Structura codului

Să începem prin a arunca o privire la arborele de cod al proiectului. Arata cam asa:

Ierarhia fișierelor/directoarelor exemplului nostru de proiect zmq-service-suite-ruby-bootstrap. Este descris în detaliu mai jos, dar rețineți că ultimele trei fișiere .rb menționate sunt de fapt sub lib/repositories, nu sub lib în sine.

  • Directorul bin este locul în care stocați scripturile care lansează serviciul.
  • Directorul de config stochează toate fișierele de configurare.
    • Fișierul boot.rb este locul în care puteți adăuga toate dependențele de servicii. Dacă îl deschideți, puteți observa că există deja multe dependențe enumerate acolo. Dacă trebuie să adăugați mai multe, aici ar trebui să o faceți.
    • Fișierul application.yml stochează toate setările aplicației. Vom arunca o privire asupra acestui fișier mai târziu.
    • În directorul config/initializers puteți adăuga scripturile de inițializare. Puteți, de exemplu, să adăugați setări pentru conexiunile ActiveRecord sau Redis aici. Scripturile pe care le adăugați în acest director vor rula la pornirea serviciului.
  • În directorul db/migrate puteți stoca migrațiile ActiveRecord sau Sequel, dacă aveți. În cazul în care nu o faceți, puteți șterge acest director cu totul.
  • Directorul lib este locul în care se află codul principal al aplicației.
    • Fișierul settings.rb încarcă pur și simplu fișierul application.yml și îl face disponibil în întregul domeniu de aplicare al serviciului, astfel încât să vă puteți accesa configurațiile oriunde. De exemplu, Settings.broker.backend returnează adresa de backend a brokerului pe care ați definit-o în fișierul YML de mai sus.
    • Fișierul service_register.rb este locul în care vă înregistrați serviciile și rutele de servicii. O vom explica mai târziu.
    • Fișierul hello_world_service.rb definește punctele finale ale serviciului „Hello World”.
    • Directorul lib/daos este locul în care vă stocați obiectele ActiveModel dacă utilizați ActiveRecord sau orice alte obiecte de acces la date pe care le-ați putea crea eventual, cum ar fi modelele dvs. Sequel.
    • Directorul lib/dtos stochează obiectele de transfer de date. Aceste obiecte sunt cele care sunt eventual trimise înapoi clienților serviciului.
    • Directorul lib/repositories stochează depozitele dvs. Arhivele sunt obiecte care permit serviciilor să acceseze date și sunt singurele obiecte autorizate să gestioneze DAO-uri. Deci, dacă un serviciu dorește un grup de instanțe „Hello World”, le va cere depozitului. Depozitul, la rândul său, utilizează DAO-urile adecvate pentru a prelua datele relevante din baza de date. Datele sunt apoi mapate într-o colecție DTO „HelloWorld” adecvată sau „HelloWorld” DTO, care este returnată serviciului.
    • Directorul lib/repositories/mappers este locul unde vă stocați mapperele. Maperii sunt obiecte care convertesc DAO-uri în DTO-uri și invers.

Fișierul application.yml din directorul de config arată astfel:

 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

Această setare setează pur și simplu adresa back-end și front-end a brokerului și nivelul de înregistrare.

Dacă toate acestea sună confuz până acum, nu vă faceți griji, deoarece va deveni mai clar pe măsură ce mergem mai departe.

Serviciul „Persoană”.

Deci, să continuăm cu serviciul nostru „Persoană”. Să începem prin a configura conexiunea la baza de date. Deschideți fișierul config/initializers/active_record.rb și decomentați singura linie de acolo. Apoi, adăugați următoarea intrare la configurația de dezvoltare în application.yml , astfel încât să arate astfel:

 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

Acum că ați adăugat configurația bazei de date, trebuie să creați baza de date. În acest moment, nu există nicio modalitate de a face acest lucru automat decât dacă utilizați o bază de date implicită PostgreSQL, caz în care puteți pur și simplu să rulați:

 $ rake db:create

Dacă preferați o altă bază de date, trebuie să adăugați bijuteria corespunzătoare în fișierul gem și apoi să instalați proiectul în pachet.

Urmează migrația. Pentru asta, pur și simplu creați fișierul db/migrate numit 000_creates_persons.rb :

 $ touch db/migrate/000_creates_persons_table.rb

Deschideți fișierul și creați migrarea așa cum ați face cu o migrare Rails obișnuită:

 class CreatesPersons < ActiveRecord::Migration def change create_table :persons do |t| t.name t.timestamps end end end

Apoi, rulați-l:

 $ 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) =======================================

Acum că avem tabelul creat, să creăm un model pentru acesta. Creați fișierul lib/daos/person.rb :

 $ touch lib/daos/person.rb

Editează-l astfel:

 module DAO class Person < ActiveRecord::Base end end

Există modelul tău. Acum trebuie să creați un model DTO pentru o „Persoană”, astfel încât să îl puteți returna clientului. Creați fișierul lib/dtos/person.rb :

 $ touch lib/dtos/person.rb

Editează-l astfel:

 module DTO class Person < Base attr_reader :id, :name end end

Apoi, trebuie să creați un Mapper pentru a converti DAO „Persoană” într-un DTO „Persoană”. Creați fișierul lib/repositories/mappers/person.rb și editați-l astfel:

 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

Aici, Mapper::Base vă solicită să implementați self.to_dao și self.to_dto . Dacă nu doriți să faceți acest lucru, puteți implementa self.map în schimb și înlocuiți Mapper::Base.map care apelează to_dao sau to_dto , în funcție de atributul pe care îl primește este un DAO sau un DTO.

Acum aveți un DAO pentru a vă accesa baza de date, un DTO pentru ao trimite clientului și un Mapper pentru a converti unul în celălalt. Acum puteți utiliza aceste trei clase într-un depozit pentru a crea logica care vă permite să obțineți persoane din baza de date și să returnați o colecție corespunzătoare de DTO.

Atunci să creăm depozitul. Creați fișierul lib/repositories/person.rb :

 $ touch lib/dtos/person.rb

Editează-l astfel:

 module Repository class Person < Repository::Base def get DAO::Person.all.map do |person| Mapper::Person.map(person) end end end end

Acest depozit are doar metoda de instanță get care pur și simplu preia toate persoanele din baza de date și le mapează într-o colecție de DTO-uri de persoane - destul de simplu. Să aducem toate acestea împreună acum. Tot ce mai rămâne acum este să creați serviciul și punctul final care apelează acest depozit. Pentru a face asta, să creăm fișierul lib/person_service.rb :

 $ touch lib/person_service.rb

Editează-l astfel:

 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

Serviciul „Persoană” inițializează depozitul în inițializatorul său. Toate metodele de instanță publică ale serviciului „Persoană” au sarcină utilă și anteturi pe care le puteți omite dacă nu aveți nevoie de ele. Ambele sunt Hashie::Mash și stochează variabilele trimise la punctul final, fie ca atribute, fie ca antete, iar răspunsurile lor imită răspunsurile HTTP, deoarece fiecare răspuns are un cod de stare pe care clienții îl pot folosi pentru a afla rezultatul solicitărilor trimise către serviciu, împreună cu sarcina utilă de răspuns a serviciului. Codurile de răspuns sunt aceleași pe care v-ați aștepta de la un server HTTP. De exemplu, o solicitare reușită va returna un cod de stare 200, împreună cu sarcina de răspuns. Dacă apare o eroare de serviciu, atunci codul de stare va fi 500, iar dacă există ceva în neregulă cu parametrii trimiși către server, codul de stare va fi 400. Serviciul poate răspunde cu majoritatea codurilor de stare HTTP împreună cu sarcina sa utilă. Așadar, dacă, de exemplu, doriți ca serviciul dvs. să spună clienților săi când nu au voie să acceseze un anumit punct final, puteți face acest lucru răspunzând cu un cod 403. Puteți vedea un alt exemplu de coduri de răspuns dacă vă uitați înapoi la codul nostru de serviciu de mai sus. În punctul final de get , returnăm codul de stare 404 împreună cu mesajul opțional „Nu există oameni aici” atunci când nu sunt găsite persoane, la fel cum un server HTTP ar returna un 404 dacă nu există resurse disponibile. Dacă depozitul returnează într-adevăr persoane, atunci serviciul serializează DTO-urile și le returnează clientului. Fiecare DTO are un serializator implicit care returnează un obiect JSON cu cheile și valorile corespunzătoare definite fie ca attr_reader , fie ca attr_accessible în definiția DTO. Puteți, desigur, să suprascrieți serializatorul prin definirea metodei dvs. de serializare în clasele DTO.

Acum că avem un serviciu definit, trebuie să-l înregistrăm. Acesta este pasul final. Deschideți fișierul lib/service_register.rb și înlocuiți toate aparițiile „HelloWorld” cu „Person”, astfel încât fișierul să arate în cele din urmă oarecum astfel:

 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

După cum probabil ați observat, există o mică schimbare în apelul add_route . Am eliminat șirul „HELLO/WORLD”. Asta pentru că șirul este necesar doar dacă verbul de serviciu nu se potrivește cu metoda care îl implementează. În cazul nostru, atunci când apelăm serviciul person cu verbul GET, metoda care trebuie apelată este get , deci putem omite șirul.

Clasa ServiceRegister este locul în care trebuie să definiți metoda self.get_service . Această metodă inițializează serviciul și îl conectează la backend-ul brokerului. Apoi potrivește rutele de pe acel serviciu cu metodele din una sau mai multe definiții de serviciu. De exemplu, în următorul caz, acesta creează serviciul și îl leagă de broker:

 config = Hashie::Mash.new( backend: Settings.broker.backend ) service = ZSS::Service.new(:person, config)

Apoi instanțiază un handler de servicii:

 personInstance = PersonService.new

Apoi, handlerul de servicii este legat de serviciu:

 service.add_route(personInstance, :get)

În cele din urmă, trebuie să returneze instanța de serviciu.

 return service

Acum, există doar un ultim pas înainte să putem lansa serviciul nostru „Persoană”; trebuie să creăm un script executabil pentru el. Avem deja unul pentru „HelloService”. Deci, deschideți fișierul bin/zss-service , înlocuiți „hello-word” cu „persoană” și salvați fișierul. Reveniți la consolă și rulați:

 $ 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'

Asta e. Tocmai ați început serviciul dvs. „Persoană” pentru prima dată. Acum hai să-l testăm. Deschideți fișierul bin/zss-client , schimbați variabila sid în „persoană” și modificați apelul clientului de la hello_world() la get() . După ce ați terminat, rulați clientul într-o fereastră nouă:

 $ 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>'

După cum puteți vedea, ați prins o ZSS::Error . Acest lucru se datorează faptului că generăm o eroare atunci când nu sunt găsite persoane de către serviciu și nu avem încă persoane în baza de date a serviciului nostru.

Atunci să ne ocupăm de această eroare. Deschideți zss-client și editați-l astfel:

 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

Acum tipărim mesajul de eroare când codul de eroare este 404, în timp ce ridicăm eroarea dacă este diferit. Să-l vedem în acțiune rulând din nou clientul nostru:

 $ bin/zss-client "No people here"

Excelent. Să adăugăm acum câteva persoane la masa noastră și să vedem dacă sunt returnate de serviciu clientului nostru. Pentru a face acest lucru, pur și simplu deschideți o consolă de service:

 $ rake service:console

Adăugați câteva persoane:

 $ 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

Acum, rulează-ți clientul din nou.

 $ bin/zss-client [{"id"=>1, "name"=>"John"}, {"id"=>2, "name"=>"Mary"}, {"id"=>3, "name"=>"Francis"}]

Iată-l.

Considerații finale

Parcurgând codul furnizat în acest ghid, ați putea crede că există o mulțime de pași care nu erau necesari, cum ar fi crearea de depozite sau DTO, și ați avea dreptate. Tot ce ar trebui să aveți un serviciu „Persoană” funcțional ar fi clasa dvs. de serviciu și DAO, pe care le puteți apela direct din clasa de serviciu. Cu toate acestea, este o bună practică să urmați modelul descris în acest articol, deoarece vă permite să păstrați logica serviciului separată de manipularea stocării datelor. Serviciile ar trebui să se concentreze doar pe logica lor, iar depozitele ar trebui să gestioneze toate interacțiunile cu stocarea datelor. DTO-urile determină sarcinile utile și serializarea serviciilor dvs., iar DAO-urile sunt preocupate doar de obținerea datelor din stocare. Convențiile și tehnicile descrise în acest ghid sunt cunoscute sub numele de model de depozit, pe care îl puteți verifica în imaginea de mai jos.

Modelul de depozit. Caseta din stânga este „logica de afaceri client”, care persistă și interogările din caseta din mijloc, care este o stivă constând din „mapper de date” peste „depozitiv” peste „obiect de interogare”, dar separate cu linii punctate. Persista și interogarea sunt ambele unite lateral prin conexiuni din casetele exterioare etichetate „entitate comercială”. În cele din urmă, caseta din dreapta, „sursă de date”, are o săgeată care indică „mapper de date” și săgeți bidirecționale cu „obiect de interogare”.

Aș dori să închei prin a întreba pe oricine care a găsit acest lucru util să contribuie la suita de servicii SOA, extinzând-o și îmbunătățind-o în orice fel. Toate cererile dvs. de furcă și tragere sunt binevenite.

Sper că acest lucru vă va ajuta să începeți în microservicii. Dacă doriți să verificați codul de serviciu, o versiune completă este disponibilă pe GitHub.