Jak skonfigurować architekturę mikroserwisów w Ruby: przewodnik krok po kroku
Opublikowany: 2022-03-11Czym są mikroserwisy?
Mikroserwisy to jeden z najnowszych trendów w projektowaniu oprogramowania, w którym wiele niezależnych usług komunikuje się między sobą i posiada własne procesy i zasoby. To podejście różni się od typowego projektu aplikacji klient-serwer. Zwykła aplikacja klient-serwer składa się z jednego lub więcej klientów, monolitycznego zaplecza, które zawiera wszystkie dane i logikę domeny oraz interfejsu API, który umożliwia klientom dostęp do zaplecza i jego funkcjonalności.
W architekturze mikrousług opisany monolityczny backend jest zastępowany zestawem usług rozproszonych. Taka konstrukcja pozwala na lepsze rozdzielenie odpowiedzialności, łatwiejszą konserwację, większą elastyczność w doborze technologii dla każdej usługi oraz łatwiejszą skalowalność i odporność na awarie. Jednocześnie złożone systemy rozproszone mają swój zestaw wyzwań. Mają większą szansę na radzenie sobie z warunkami wyścigu i są trudniejsze do debugowania, ponieważ problemy nie są łatwe do zlokalizowania w jednej usłudze, ale zamiast tego są rozprowadzane przez wiele. Jeśli podczas budowy takiego systemu nie podejmiesz wysiłków, aby postępować zgodnie z najlepszymi praktykami, możesz znaleźć się w otoczeniu pożarów, których nie wiesz, jak ugasić. Należy zachować szczególną ostrożność w przypadku umów dotyczących ładunku usług, ponieważ zmiany w jednej usłudze mogą wpłynąć na wszystkich jej klientów, aw konsekwencji na cały pakiet usług zaplecza.
Wszystkie te rozważania są ważne, ale załóżmy, że już je przemyślałeś. Teraz chcesz znaleźć sposób na samodzielne zbudowanie zaplecza mikrousług. Więc przejdźmy do tego.
Jak skonfigurować architekturę mikroserwisów
Obecnie istnieje wiele sposobów na skonfigurowanie mikroserwisów, a w tym przewodniku skupimy się na architekturze brokera.
Architektura brokera
Architektura brokera to jeden ze sposobów, w jaki możesz sprawić, by Twoje usługi komunikowały się między sobą. W nim wszystkie usługi otaczają serwer wiadomości, brokera i wszystkie są z nim połączone. Usługi wysyłają komunikaty do brokera, który następnie wie, jakiej innej usługi lub usług potrzebuje do przesłania tych komunikatów. W ten sposób usługi nie muszą przechowywać informacji o innych usługach. Zamiast tego polegają na brokerze, który zajmie się wszystkimi wiadomościami, co pozwala im odizolować się i skoncentrować tylko na swojej konkretnej domenie. Broker może również przechowywać wiadomości, gdy ich odbiorniki nie działają, co pozwala na uniknięcie jednoczesnego działania nadawców i odbiorców, co pozwala na jeszcze większą izolację. Oczywiście to rozwiązanie ma swoje wady, ponieważ broker może szybko stać się wąskim gardłem, ponieważ cała komunikacja musi przez nie przechodzić, a także może stać się pojedynczym punktem awarii dla Twojego backendu. Istnieje jednak kilka sposobów na złagodzenie tych problemów. Jednym ze sposobów jest równoległe działanie wielu instancji brokera, co pozwoliłoby na lepszą odporność systemu na błędy. Innym sposobem byłoby użycie innych architektur. Alternatywne architektury różnią się od architektury, którą zaimplementujemy w tym przewodniku, nie używając brokera, używając innej architektury brokera lub używając innego protokołu przesyłania wiadomości, takiego jak HTTP.
Komunikacja między usługami
W tym przewodniku będziemy używać ZeroMQ do obsługi komunikacji między usługami a brokerem.
ZeroMQ zapewnia warstwę abstrakcji protokołu, która obsługuje wieloczęściowe asynchroniczne komunikaty w losowych transportach. Zalety korzystania z ZeroMQ do przesyłania wiadomości między usługami a brokerem są poza zakresem tego przewodnika, więc nie będziemy ich tutaj omawiać, ale jeśli chcesz dowiedzieć się o nich więcej, zapoznaj się z następującym artykułem Quora. Jeśli jesteś zainteresowany innymi sposobami, aby Twoje usługi komunikowały się ze sobą, proponuję zapoznać się z artykułem Broker vs. Brokerless, aby zobaczyć, co jeszcze można osiągnąć.
Budowanie pakietu mikrousług
Ten artykuł poprowadzi Cię przez wszystkie kroki potrzebne do utworzenia pakietu mikrousług. Nasz system będzie składał się z brokera i serwisu. Będziemy również używać małego skryptu klienta do testowania wywołań pakietu usług, ale pamiętaj, że kod klienta może być łatwo używany w dowolnym miejscu.
Więc zacznijmy budować.
Pierwsze kroki
Najpierw upewnijmy się, że masz wszystko, czego potrzebujesz do uruchomienia brokera i usługi. Najpierw zacznij od pobrania i zainstalowania Node.js, ZeroMQ i Git na swoim komputerze. Jeśli używasz OSX, istnieją pakiety homebrew dla każdego z nich, a większość dystrybucji Linuksa również ma pakiet dla każdego z nich, więc nie powinieneś mieć z tym problemu. Użytkownicy systemu Windows mogą po prostu skorzystać z linków do pobrania podanych powyżej.
Prowadzenie brokera
Po zainstalowaniu wszystkich wymaganych zależności, włączmy naszego brokera. W tym przewodniku używamy implementacji Node.js brokera, która jest częścią ZMQ Service Oriented Suite. Możesz znaleźć jego kod i dokumentację na GitHub. Aby uruchomić brokera, najpierw sklonuj program startowy Brokera na swój komputer. To repozytorium jest programem startowym do korzystania z powyższej biblioteki brokera. Uwaga, ten krok nie jest wymagany, ponieważ oryginalną bibliotekę można uruchomić, ale różnica między nimi polega na tym, że w repozytorium ładowania początkowego można zmienić domyślne konfiguracje.
Więc najpierw użyj następującego polecenia Git, aby pobrać projekt na swój komputer:
$ git clone [email protected]:dadah/zmq-broker-bootstrap.gitPo wykonaniu tej czynności przejdź do utworzonego katalogu:
$ cd zmq-broker-bootstrapTeraz zainstaluj zależności pakietów:
$ npm installBroker jest teraz gotowy. Aby uruchomić swojego brokera, uruchom następujące polecenie:
$ bin/zss-broker run Pliki konfiguracyjne dla każdego środowiska można znaleźć w katalogu config/ . To jest domyślna konfiguracja programistyczna:
{ "broker": { "backend": "tcp://127.0.0.1:7776", "frontend": "tcp://127.0.0.1:7777" }, "log": { "consolePlugin": { "level": "debug" } } } Parametr backend definiuje adres ip:port back-endu i front-endu brokera. Adres zaplecza to miejsce, w którym broker otrzymuje żądania i odpowiedzi na usługi, a adres frontonu to miejsce, w którym odbiera i wysyła do klientów usługi. Możesz również ustawić poziom rejestrowania, zmieniając log.consolePlugin.level . Możliwe wartości to trace , debug , info , warn i error , które określają ilość informacji rejestrowanych przez proces brokera.
Prowadzenie usługi
Po utworzeniu brokera nadszedł czas na opracowanie pierwszego mikroserwisu Ruby. Zacznij od otwarcia nowego okna konsoli. Następnie utwórz katalog, w którym będą przechowywane Twoje usługi, a następnie przejdź do tego katalogu. W tym przewodniku używamy klienta Ruby i usługi ZMQ SOA Suite. Dostępna jest usługa ładowania początkowego „Hello world”, więc użyjmy jej, aby uruchomić nasz pierwszy mikroserwis.
Przejdź do katalogu usług i sklonuj repozytorium ładowania początkowego:
$ git clone [email protected]:dadah/zmq-service-suite-ruby-bootstrap.gitPrzejdź do nowo utworzonego katalogu:
$ cd zmq-service-suite-ruby-bootstrapTeraz zainstaluj wszystkie zależności:
$ bundle installAby uruchomić usługę, uruchom następujące polecenie:
$ bin/zss-service runŚwietnie. Masz już uruchomioną pierwszą usługę.
Jeśli przejdziesz do okna konsoli, w którym pozostawiłeś uruchomionego brokera, zobaczysz następujące dane wyjściowe:
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: 200Ten dziennik oznacza, że broker potwierdził istnienie nowej usługi i otrzymuje od niej komunikaty pulsu. Co sekundę usługa wysyła komunikat pulsu do brokera, dzięki czemu wie, że instancja usługi działa.
Spożywanie z Usługi
Więc teraz mamy uruchomioną usługę, jak z niej korzystamy?
W repozytorium bootstrap znajduje się fikcyjny klient, którego możesz użyć do przetestowania swojej usługi „Hello World”. Po prostu otwórz nowe okno lub kartę konsoli i przejdź do katalogu usług. Gdy już tam będziesz, uruchom następujące polecenie:
$ bin/zss-clientPowinieneś zobaczyć coś takiego:
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"Jeśli przejdziesz do okna konsoli, w którym działa Twoja usługa, powinieneś zobaczyć to:
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: 200Dobry. Właśnie uruchomiłeś i wykorzystałeś mikroserwis „Hello World”. Nie to jednak postanowiliśmy zrobić. Chcemy budować nasze usługi. Przejdźmy więc do tego.
Budowanie Twojej usługi
Najpierw zatrzymajmy naszą usługę „Hello World”. Przejdź do okna konsoli usługi i naciśnij Ctrl+C , aby zatrzymać usługę. Następnie musimy zmienić naszą usługę „Hello World” na usługę „Osoba”.
Struktura kodu
Zacznijmy od spojrzenia na drzewo kodu projektu. To wygląda tak:
- Katalog
binto miejsce, w którym przechowujesz skrypty uruchamiające Twoją usługę. - Katalog
configprzechowuje wszystkie pliki konfiguracyjne.- Plik
boot.rbto miejsce, w którym możesz dodać wszystkie zależności usług. Jeśli go otworzysz, zauważysz, że jest tam już wiele zależności. Jeśli chcesz dodać więcej, tutaj powinieneś to zrobić. - Plik
application.ymlprzechowuje wszystkie ustawienia aplikacji. Przyjrzymy się temu plikowi później. - W katalogu
config/initializersmożesz dodać swoje skrypty inicjujące. Możesz na przykład dodać tutaj ustawienia dla połączeń ActiveRecord lub Redis. Skrypty dodane do tego katalogu będą uruchamiane podczas uruchamiania usługi.
- Plik
- W katalogu
db/migratemożesz przechowywać migracje ActiveRecord lub Sequel, jeśli takie posiadasz. Jeśli tego nie zrobisz, możesz całkowicie usunąć ten katalog. - Katalog
libto miejsce, w którym znajduje się główny kod aplikacji.- Plik
settings.rbpo prostu ładuje plikapplication.ymli udostępnia go w całym zakresie usługi, dzięki czemu możesz uzyskać dostęp do swoich konfiguracji z dowolnego miejsca. Na przykładSettings.broker.backendzwraca adres zaplecza brokera zdefiniowany w powyższym pliku YML. - Plik
service_register.rbto miejsce, w którym rejestrujesz swoje usługi i trasy usług. Wyjaśnimy to później. - Plik
hello_world_service.rbdefiniuje punkty końcowe usługi „Hello World”. - Katalog
lib/daosto miejsce, w którym przechowujesz obiekty ActiveModel, jeśli używasz ActiveRecord, lub jakiekolwiek inne obiekty dostępu do danych, które możesz w końcu utworzyć, takie jak modele Sequel. - Katalog
lib/dtosprzechowuje obiekty przesyłania danych. Obiekty te są ostatecznie odsyłane do klientów usługi. - Katalog
lib/repositoriesprzechowuje twoje repozytoria. Repozytoria to obiekty, które umożliwiają usługom dostęp do danych i są jedynymi obiektami, które mogą obsługiwać DAO. Jeśli więc usługa chce mieć grupę instancji „Hello World”, poprosi o nie repozytorium. Repozytorium z kolei wykorzystuje odpowiednie DAO do pobierania odpowiednich danych z bazy danych. Dane są następnie mapowane do odpowiedniej kolekcji DTO „HelloWorld” lub „HelloWorld” DTO, która jest zwracana do usługi. - Katalog
lib/repositories/mappersto miejsce przechowywania maperów. Mapery to obiekty, które przekształcają obiekty DAO w obiekty DTO i na odwrót.
- Plik
Plik application.yml z katalogu config wygląda tak:

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: <<: *defaultsTo ustawienie po prostu ustawia adres zaplecza i frontonu brokera oraz poziom rejestrowania.
Jeśli do tej pory wszystko to wydaje się zagmatwane, nie martw się, ponieważ stanie się to jaśniejsze, gdy przejdziemy dalej.
Usługa „osoba”
Przejdźmy więc do naszej usługi „Osoba”. Zacznijmy od skonfigurowania połączenia z bazą danych. Otwórz plik config/initializers/active_record.rb i odkomentuj jedyną tam linię. Następnie dodaj następujący wpis do swojej konfiguracji programistycznej w pliku application.yml , aby wyglądał tak:
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-developmentTeraz, po dodaniu konfiguracji bazy danych, musisz utworzyć bazę danych. W tej chwili nie ma możliwości zrobienia tego automatycznie, chyba że używasz domyślnej bazy danych PostgreSQL, w którym to przypadku możesz po prostu uruchomić:
$ rake db:createJeśli wolisz inną bazę danych, musisz dodać odpowiedni gem do pliku gem, a następnie spakować zainstalować projekt.
Następna jest migracja. W tym celu po prostu utwórz plik db/migrate o nazwie 000_creates_persons.rb :
$ touch db/migrate/000_creates_persons_table.rbOtwórz plik i utwórz migrację tak jak w przypadku zwykłej migracji Rails:
class CreatesPersons < ActiveRecord::Migration def change create_table :persons do |t| t.name t.timestamps end end endNastępnie uruchom go:
$ 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) ======================================= Teraz, gdy stworzyliśmy nasz stół, stwórzmy dla niego model. Utwórz plik lib/daos/person.rb :
$ touch lib/daos/person.rbEdytuj to w ten sposób:
module DAO class Person < ActiveRecord::Base end end Oto twój model. Teraz musisz stworzyć model DTO dla „Osoby”, aby móc go zwrócić klientowi. Utwórz plik lib/dtos/person.rb :
$ touch lib/dtos/person.rbEdytuj to w ten sposób:
module DTO class Person < Base attr_reader :id, :name end end Następnie musisz utworzyć Mapper, aby przekonwertować DAO „Osoba” na DTO „Osoba”. Utwórz plik lib/repositories/mappers/person.rb i edytuj go w następujący sposób:
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 Tutaj Mapper::Base wymaga zaimplementowania self.to_dao i self.to_dto . Jeśli nie chcesz tego robić, możesz zamiast tego zaimplementować self.map i nadpisać Mapper::Base.map , który wywołuje to_dao lub to_dto , w zależności od tego, czy otrzymany atrybut jest DAO czy DTO.
Teraz masz DAO, aby uzyskać dostęp do bazy danych, DTO, aby wysłać je do klienta, oraz Mapper do konwersji jednego na drugie. Możesz teraz użyć tych trzech klas w repozytorium, aby stworzyć logikę, która umożliwia pobieranie osób z bazy danych i zwracanie odpowiedniej kolekcji DTO.
Stwórzmy zatem repozytorium. Utwórz plik lib/repositories/person.rb :
$ touch lib/dtos/person.rbEdytuj to w ten sposób:
module Repository class Person < Repository::Base def get DAO::Person.all.map do |person| Mapper::Person.map(person) end end end end To repozytorium ma tylko metodę instancji get , która po prostu pobiera wszystkie osoby z bazy danych i mapuje je do kolekcji osób DTO - całkiem proste. Połączmy to wszystko teraz. Teraz pozostaje tylko stworzyć usługę i punkt końcowy, który wywołuje to repozytorium. W tym celu stwórzmy plik lib/person_service.rb :
$ touch lib/person_service.rbEdytuj to w ten sposób:
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 Usługa „Osoba” inicjuje repozytorium w swoim inicjatorze. Wszystkie metody instancji publicznych usługi „Osoba” mają ładunek i nagłówki, które możesz pominąć, jeśli ich nie potrzebujesz. Oba są instancjami Hashie::Mash i przechowują zmienne wysyłane do punktu końcowego, jako atrybuty lub nagłówki, a ich odpowiedzi naśladują odpowiedzi HTTP, ponieważ każda odpowiedź ma kod stanu, którego klienci mogą użyć do znalezienia wyniku żądań wysłanych do usługi wraz z ładunkiem odpowiedzi usługi. Kody odpowiedzi są takie same, jakich można oczekiwać od serwera HTTP. Na przykład pomyślne żądanie zwróci kod stanu 200 wraz z ładunkiem odpowiedzi. Jeśli wystąpi jakiś błąd usługi, kod statusu będzie wynosił 500, a jeśli coś jest nie tak z parametrami przesłanymi do serwera, kod statusu będzie wynosił 400. Usługa może odpowiedzieć większością kodów statusu HTTP wraz z ładunkiem. Tak więc, jeśli na przykład chcesz, aby Twoja usługa informowała swoich klientów, kiedy nie mogą uzyskać dostępu do określonego punktu końcowego, możesz to zrobić, odpowiadając kodem 403. Możesz zobaczyć inny przykład kodów odpowiedzi, jeśli spojrzysz wstecz na nasz kod usługi powyżej. W punkcie końcowym get zwracamy kod stanu 404 wraz z opcjonalnym komunikatem „Brak tu osób”, gdy nie znaleziono żadnych osób, podobnie jak serwer HTTP zwróciłby kod 404, jeśli nie ma dostępnych zasobów. Jeśli repozytorium rzeczywiście zwraca ludzi, usługa serializuje DTO i zwraca je do klienta. Każdy DTO ma domyślny serializator, który zwraca obiekt JSON z kluczami i odpowiednimi wartościami zdefiniowanymi jako attr_reader lub attr_accessible w definicji DTO. Możesz oczywiście przesłonić serializator, definiując metodę serializacji w klasach DTO.
Teraz, gdy mamy zdefiniowaną usługę, musimy ją zarejestrować. To jest ostatni krok. Otwórz plik lib/service_register.rb i zastąp wszystkie wystąpienia „HelloWorld” słowem „Person”, aby ostatecznie plik wyglądał mniej więcej tak:
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 Jak zapewne zauważyłeś, nastąpiła niewielka zmiana w wywołaniu add_route . Usunęliśmy ciąg „HELLO/WORLD”. Dzieje się tak, ponieważ ciąg jest potrzebny tylko wtedy, gdy czasownik usługi nie pasuje do metody, która go implementuje. W naszym przypadku, gdy wywołujemy usługę person za pomocą czasownika GET, należy wywołać metodę get , więc możemy pominąć ciąg.
W klasie ServiceRegister należy zdefiniować metodę self.get_service . Ta metoda inicjuje usługę i łączy ją z backendem brokera. Następnie dopasowuje trasy w tej usłudze do metod w co najmniej jednej definicji usługi. Na przykład w następującym przypadku tworzy usługę i wiąże ją z brokerem:
config = Hashie::Mash.new( backend: Settings.broker.backend ) service = ZSS::Service.new(:person, config)Następnie tworzy instancję obsługi usługi:
personInstance = PersonService.newNastępnie program obsługi usługi jest powiązany z usługą:
service.add_route(personInstance, :get)Na koniec musi zwrócić wystąpienie usługi.
return service Teraz jest tylko jeden ostatni krok, zanim będziemy mogli uruchomić naszą usługę „Osoba”; musimy stworzyć dla niego skrypt wykonywalny. Mamy już jeden dla „HelloService”. Otwórz więc plik bin/zss-service , zastąp „hello-word” słowem „person” i zapisz plik. Wróć do konsoli i uruchom:
$ 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' Otóż to. Właśnie uruchomiłeś swoją usługę „Osoba” po raz pierwszy. Teraz przetestujmy to. Otwórz plik bin/zss-client , zmień zmienną sid na „person” i zmień wywołanie klienta z hello_world() na get() . Gdy to zrobisz, uruchom klienta w nowym oknie:
$ 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>' Jak widać, ZSS::Error . Dzieje się tak, ponieważ zgłaszamy błąd, gdy serwis nie znalazł żadnych osób i nie mamy jeszcze żadnych osób w bazie danych naszego serwisu.
Zajmijmy się więc tym błędem. Otwórz zss-client i edytuj go w ten sposób:
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 endTeraz wyświetlamy komunikat o błędzie, gdy kod błędu to 404, podnosząc błąd, jeśli jest inny. Zobaczmy to w akcji uruchamiając ponownie naszego klienta:
$ bin/zss-client "No people here"Doskonały. Dodajmy teraz kilka osób do naszego stołu i zobaczmy, czy są one zwracane przez usługę do naszego klienta. Aby to zrobić, po prostu otwórz konsolę serwisową:
$ rake service:consoleDodaj kilka osób:
$ 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)> exitTeraz ponownie uruchom swojego klienta.
$ bin/zss-client [{"id"=>1, "name"=>"John"}, {"id"=>2, "name"=>"Mary"}, {"id"=>3, "name"=>"Francis"}]Masz to.
Rozważania końcowe
Przeglądając kod podany w tym przewodniku, możesz pomyśleć, że istnieje wiele niepotrzebnych kroków, takich jak tworzenie repozytoriów lub DTO, i masz rację. Wszystko, czego potrzebujesz, aby mieć działającą usługę „Osoba”, to Twoja klasa usług i DAO, które możesz wywołać bezpośrednio z klasy usługi. Niemniej jednak dobrą praktyką jest przestrzeganie wzorca opisanego w tym artykule, ponieważ umożliwia to oddzielenie logiki usługi od manipulacji przechowywaniem danych. Usługi powinny skupiać się tylko na ich logice, a repozytoria powinny obsługiwać wszystkie interakcje z przechowywaniem danych. DTO określają ładunek i serializację usług, a DAO zajmują się tylko pobieraniem danych z magazynu. Konwencje i techniki opisane w tym przewodniku są znane jako wzorzec repozytorium, który możesz sprawdzić na poniższym obrazku.
Chciałbym zakończyć, prosząc każdego, kto uznał to za przydatne, aby wniósł wkład w pakiet usług SOA, rozszerzając go i ulepszając w jakikolwiek sposób. Wszystkie Twoje widelce i prośby o ściągnięcie są mile widziane.
Mam nadzieję, że to pomoże Ci rozpocząć pracę w mikroserwisach. Jeśli chcesz sprawdzić kod usługi, pełna wersja jest dostępna na GitHub.
