Ruby'de Mikro Hizmet Mimarisi Nasıl Kurulur: Adım Adım Kılavuz
Yayınlanan: 2022-03-11Mikro Hizmetler Nedir?
Mikro hizmetler, birden çok bağımsız hizmetin kendi aralarında iletişim kurduğu ve kendi süreçlerine ve kaynaklarına sahip olduğu yazılım tasarımındaki en son trendlerden biridir. Bu yaklaşım, tipik bir istemci-sunucu uygulama tasarımından farklıdır. Olağan istemci-sunucu uygulaması, bir veya daha fazla istemciden, tüm etki alanı verilerini ve mantığını içeren monolitik bir arka uçtan ve istemcilerin arka uca ve işlevselliğine erişmesine izin veren bir API'den oluşur.
Bir mikro hizmet mimarisinde, açıklanan monolitik arka uç, bunun yerine bir dağıtılmış hizmet paketi ile değiştirilir. Bu tasarım, sorumlulukların daha iyi ayrılmasını, daha kolay bakım yapılmasını, her hizmet için teknoloji seçiminde daha fazla esneklik ve daha kolay ölçeklenebilirlik ve hata toleransı sağlar. Aynı zamanda, karmaşık dağıtılmış sistemlerin kendi zorlukları vardır. Yarış koşullarıyla uğraşmak zorunda kalma şansları daha yüksektir ve sorunlar tek bir hizmette kolayca belirlenmediğinden, bunun yerine birçok hizmete dağıtıldığından hata ayıklaması daha zordur. Böyle bir sistemi kurarken en iyi uygulamaları takip etmeye çalışılmazsa, kendinizi nasıl söndüreceğinizi bilmediğiniz yangınlarla çevrili bulabilirsiniz. Bir hizmetteki değişiklikler tüm istemcilerini ve dolayısıyla tüm arka ucun hizmet paketini etkileyebileceğinden, hizmetlerin yük sözleşmelerine özel dikkat gösterilmelidir.
Tüm bu düşünceler önemlidir, ancak bunları zaten düşündüğünüzü varsayalım. Şimdi istediğiniz şey, kendi başınıza bir mikro hizmet arka ucu oluşturmanın bir yolunu bulmak. Öyleyse hemen buna dalalım.
Mikro Hizmet Mimarisi Nasıl Kurulur
Şu anda mikro hizmetlerinizi kurmanın birçok yolu vardır ve bu kılavuzda bir komisyoncu mimarisine odaklanacağız.
Bir Broker Mimarisi
Aracı mimarisi, hizmetlerinizin kendi aralarında iletişim kurmasını sağlamanın yollarından biridir. İçinde, tüm hizmetler bir mesajlaşma sunucusunu, aracıyı çevreler ve hepsi ona bağlıdır. Hizmetler, aracıya mesajlar gönderir, aracı kurum daha sonra bu mesajları iletmek için başka hangi hizmet veya hizmetlere ihtiyacı olduğunu bilir. Bu sayede servislerin diğer servisler hakkında bilgi tutmasına gerek kalmaz. Bunun yerine, tüm mesajlaşmayı halletmek için aracıya güvenirler ve bu, onların yalıtılmalarına ve yalnızca kendi alanlarına odaklanmalarına olanak tanır. Bir komisyoncu, alıcıları kapalıyken de mesajları saklayabilir, bu da göndericilerin ve alıcıların aynı anda çalışmaya zorlanmamasına, böylece daha da fazla izolasyona izin verir. Elbette, tüm iletişimin bunlardan geçmesi gerektiğinden, komisyoncu hızla bir darboğaz haline gelebileceğinden ve aynı zamanda arka ucunuz için tek bir başarısızlık noktası haline gelebileceğinden, bu çözümün dezavantajları vardır. Ancak, bu sorunları azaltmanın birkaç yolu vardır. Bunun bir yolu, daha iyi sistem hatası toleransı sağlayacak şekilde, aracının birden çok örneğini paralel olarak çalıştırmaktır. Başka bir yol, diğer mimarileri kullanmak olacaktır. Alternatif mimariler, bu kılavuzda uygulayacağımız mimariden, aracı kullanmamak, farklı bir aracı mimarisi kullanmak veya HTTP gibi farklı bir mesajlaşma protokolü kullanmak suretiyle farklılık gösterir.
Hizmetler Arası İletişim
Bu kılavuzda, hizmetler ve komisyoncu arasındaki iletişimi yönetmek için ZeroMQ kullanacağız.
ZeroMQ, rastgele aktarımlar üzerinden çok parçalı asenkron mesajları işleyen bir protokol soyutlama katmanı sağlar. Hizmetler ve komisyoncu arasında mesajlaşma için ZeroMQ kullanmanın avantajları bu kılavuzun kapsamı dışındadır, bu nedenle bunları burada ele almayacağız, ancak bunlar hakkında daha fazla bilgi edinmek istiyorsanız aşağıdaki Quora makalesine göz atın. Hizmetlerinizin birbiriyle konuşmasını sağlamanın başka yollarını bulmakla ilgileniyorsanız, başka neler yapılabileceğini görmek için Broker vs. Brokerless makalesine bir göz atmanızı öneririm.
Mikro Hizmetler Paketini Oluşturma
Bu makale, mikro hizmet paketinizi oluşturmak için gereken tüm adımlarda size rehberlik edecektir. Sistemimiz bir komisyoncu ve bir hizmetten oluşacaktır. Ayrıca hizmet paketine yapılan çağrıları test etmek için küçük bir istemci komut dosyası kullanacağız, ancak istemci kodunun her yerde kolayca kullanılabileceğini unutmayın.
Öyleyse, inşa etmeye başlayalım.
Başlarken
İlk olarak, aracıyı ve hizmeti çalıştırmak için ihtiyacınız olan her şeye sahip olduğunuzdan emin olalım. İlk olarak, makinenize Node.js, ZeroMQ ve Git'i indirip yükleyerek başlayın. OSX kullanıyorsanız, her biri için homebrew paketleri vardır ve çoğu Linux dağıtımının da her biri için bir paketi vardır, bu nedenle bununla ilgili bir sorununuz olmamalıdır. Windows kullanıcıları, yukarıda verilen indirme bağlantılarını kullanabilir.
Aracıyı Çalıştırmak
Gerekli tüm bağımlılıkları yükledikten sonra aracımızı çalıştıralım. Bu kılavuzda, ZMQ Service Oriented Suite'in bir parçası olan aracının Node.js uygulamasını kullanıyoruz. Kodunu ve belgelerini GitHub'da bulabilirsiniz. Aracıyı çalıştırmak için önce makinenize bir Aracı önyüklemesini klonlayın. Bu depo, yukarıdaki aracı kitaplığını kullanmak için bir önyüklemedir. Orijinal kitaplığın kendisi çalıştırılabilir olduğundan bu adım gerekli değildir, ancak ikisi arasındaki fark, önyükleme deposunda varsayılan yapılandırmaları değiştirebilmenizdir.
Bu nedenle, projeyi makinenize indirmek için önce aşağıdaki Git komutunu kullanın:
$ git clone [email protected]:dadah/zmq-broker-bootstrap.git
Bunu yaptıktan sonra oluşturulan dizine gidin:
$ cd zmq-broker-bootstrap
Şimdi paket bağımlılıklarını kurun:
$ npm install
Broker artık hazır. Aracınızı çalıştırmak için aşağıdaki komutu çalıştırın:
$ bin/zss-broker run
Her ortam için yapılandırma dosyalarını config/
dizininde bulabilirsiniz. Bu, varsayılan geliştirme yapılandırmasıdır:
{ "broker": { "backend": "tcp://127.0.0.1:7776", "frontend": "tcp://127.0.0.1:7777" }, "log": { "consolePlugin": { "level": "debug" } } }
Arka backend
parametresi, aracının arka ucunun ve ön ucunun ip:port
adresini tanımlar. Arka uç adresi, aracının hizmetlerden istekleri aldığı ve yanıtladığı yerdir ve ön uç adresi, hizmet istemcilerini alıp onlara gönderdiği yerdir. log.consolePlugin.level
değiştirerek de günlük düzeyini ayarlayabilirsiniz. Olası değerler trace
, debug
, info
, warn
ve error
'dur ve bunlar broker işleminin ne kadar loglama yapacağını belirler.
Hizmeti Çalıştırmak
Aracınızı kurduktan sonra, ilk Ruby mikro hizmetinizi geliştirmenin zamanı geldi. Yeni bir konsol penceresi açarak başlayın. Ardından, hizmetlerinizin saklanacağı bir dizin oluşturun ve ardından bu dizine gidin. Bu kılavuzda, ZMQ SOA Suite'in Ruby istemcisini ve hizmetini kullanıyoruz. Bir önyükleme “Merhaba dünya” hizmeti mevcut, bu yüzden ilk mikro hizmetimizi çalıştırmak için kullanalım.
Hizmetler dizininize gidin ve önyükleme deposunu klonlayın:
$ git clone [email protected]:dadah/zmq-service-suite-ruby-bootstrap.git
Yeni oluşturulan dizine gidin:
$ cd zmq-service-suite-ruby-bootstrap
Şimdi tüm bağımlılıkları yükleyin:
$ bundle install
Hizmeti başlatmak için aşağıdaki komutu çalıştırın:
$ bin/zss-service run
Harika. İlk hizmetiniz çalışıyor ve çalışıyor.
Aracınızı çalışır durumda bıraktığınız konsol penceresine giderseniz, aşağıdaki çıktıyı görebilirsiniz:
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
Bu günlük, aracının yeni bir hizmetin varlığını kabul ettiği ve ondan sinyal mesajları aldığı anlamına gelir. Hizmet, her saniye aracıya bir sinyal mesajı gönderir, böylece hizmet örneğinin çalıştığını bilir.
Hizmetten Tüketmek
Peki şimdi çalışan bir servisimiz var, onu nasıl kullanacağız?
Önyükleme deposunda, “Merhaba Dünya” hizmetinizi test etmek için kullanabileceğiniz sahte bir istemci var. Yeni bir konsol penceresi veya sekmesi açın ve servis dizininize gidin. Oradayken, aşağıdaki komutu çalıştırın:
$ bin/zss-client
Bunun gibi bir şey görmelisiniz:
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"
Hizmetinizin çalıştığı konsol penceresine giderseniz şunu görmelisiniz:
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
İyi. “Merhaba Dünya” mikro hizmetinizi yeni başlattınız ve tükettiniz. Ancak bu, yapmaya karar verdiğimiz şey değil. Hizmet(ler)imizi oluşturmak istiyoruz. O halde ona geçelim.
Hizmetinizi Oluşturmak
Öncelikle “Merhaba Dünya” hizmetimizi durduralım. Hizmetin konsol penceresine gidin ve hizmeti durdurmak için Ctrl+C
basın. Ardından “Merhaba Dünya” hizmetimizi “Kişi” hizmetine dönüştürmemiz gerekiyor.
Kod Yapısı
Projenin kod ağacına bir göz atarak başlayalım. Şuna benziyor:
-
bin
dizini, hizmetinizi başlatan komut dosyalarını sakladığınız yerdir. -
config
dizini, tüm yapılandırma dosyalarını saklar.-
boot.rb
dosyası, tüm hizmet bağımlılıklarınızı ekleyebileceğiniz yerdir. Açarsanız, orada zaten listelenen birçok bağımlılık olduğunu fark edebilirsiniz. Daha fazlasını eklemeniz gerekiyorsa, yapmanız gereken yer burasıdır. -
application.yml
dosyası, tüm uygulama ayarlarınızı saklar. Bu dosyaya daha sonra bakacağız. -
config/initializers
dizininde başlatıcı komut dosyalarınızı ekleyebilirsiniz. Örneğin, buraya ActiveRecord veya Redis bağlantıları için ayarlar ekleyebilirsiniz. Bu dizine eklediğiniz komut dosyaları hizmet başlangıcında çalışacaktır.
-
- Varsa, ActiveRecord veya Sequel geçişlerinizi
db/migrate
dizininde saklayabilirsiniz. Bunu yapmazsanız, bu dizini tamamen silebilirsiniz. -
lib
dizini, ana uygulama kodunuzun bulunduğu yerdir.-
settings.rb
dosyası,application.yml
dosyasını yükler ve yapılandırmalarınıza her yerden erişebilmeniz için bunu hizmet kapsamında kullanılabilir hale getirir. Örneğin,Settings.broker.backend
, yukarıdaki YML dosyasında tanımladığınız aracı arka uç adresini döndürür. -
service_register.rb
dosyası, hizmetlerinizi ve hizmet rotalarınızı kaydettiğiniz yerdir. Daha sonra açıklayacağız. -
hello_world_service.rb
dosyası, “Merhaba Dünya” hizmetinin uç noktalarını tanımlar. -
lib/daos
dizini, ActiveRecord kullanıyorsanız ActiveModel nesnelerinizi veya Sequel modelleriniz gibi sonunda oluşturabileceğiniz diğer veri erişim nesnelerini depoladığınız yerdir. -
lib/dtos
dizini, veri aktarım nesnelerinizi depolar. Bu nesneler, sonunda hizmetin istemcilerine geri gönderilen nesnelerdir. -
lib/repositories
dizini, havuzlarınızı saklar. Depolar, hizmetlerin verilere erişmesine izin veren nesnelerdir ve DAO'ları işlemesine izin verilen tek nesnelerdir. Bu nedenle, bir hizmet bir grup “Merhaba Dünya” örneği isterse, bunları depodan isteyecektir. Depo, ilgili verileri veritabanından almak için uygun DAO'ları kullanır. Veriler daha sonra uygun bir “HelloWorld” DTO veya “HelloWorld” DTO koleksiyonuyla eşleştirilir ve hizmete geri gönderilir. -
lib/repositories/mappers
dizini, eşleyicilerinizi sakladığınız yerdir. Eşleştiriciler, DAO'ları DTO'lara dönüştüren nesnelerdir ve bunun tersi de geçerlidir.
-
config
dizinindeki application.yml
dosyası şöyle görünür:

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
Bu ayar, aracının arka uç ve ön uç adresini ve günlüğe kaydetme düzeyini basitçe ayarlar.
Tüm bunlar şu ana kadar kafa karıştırıcı geliyorsa endişelenmeyin çünkü ilerledikçe daha da netleşecektir.
“Kişi” Hizmeti
O halde “Kişi” hizmetimizle devam edelim. Veritabanı bağlantısını yapılandırarak başlayalım. config/initializers/active_record.rb
dosyasını açın ve oradaki tek satırın yorumunu kaldırın. Ardından, aşağıdaki gibi görünmesi için application.yml
geliştirme yapılandırmanıza aşağıdaki girişi ekleyin:
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
Artık veritabanı yapılandırmanızı eklediğinize göre, veritabanını oluşturmanız gerekir. Şu anda, varsayılan bir PostgreSQL veritabanı kullanmıyorsanız bunu otomatik olarak yapmanın bir yolu yoktur; bu durumda aşağıdakileri basitçe çalıştırabilirsiniz:
$ rake db:create
Başka bir veritabanını tercih ederseniz, uygun gem'i gemfile'e eklemeniz ve ardından projeyi paket halinde yüklemeniz gerekir.
Sırada göç var. Bunun için, 000_creates_persons.rb
adlı db/migrate
dosyasını oluşturmanız yeterlidir:
$ touch db/migrate/000_creates_persons_table.rb
Dosyayı açın ve normal bir Rails geçişinde yaptığınız gibi geçişi oluşturun:
class CreatesPersons < ActiveRecord::Migration def change create_table :persons do |t| t.name t.timestamps end end end
Ardından, çalıştırın:
$ 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) =======================================
Şimdi tablomuzu oluşturduğumuza göre onun için bir model oluşturalım. lib/daos/person.rb
dosyasını oluşturun:
$ touch lib/daos/person.rb
Bunu şu şekilde düzenleyin:
module DAO class Person < ActiveRecord::Base end end
İşte modeliniz. Şimdi bir “Kişi” için bir DTO modeli oluşturmanız gerekiyor, böylece onu müşteriye iade edebilirsiniz. lib/dtos/person.rb
dosyasını oluşturun:
$ touch lib/dtos/person.rb
Bunu şu şekilde düzenleyin:
module DTO class Person < Base attr_reader :id, :name end end
Ardından, "Kişi" DAO'yu "Kişi" DTO'ya dönüştürmek için bir Eşleştirici oluşturmanız gerekir. lib/repositories/mappers/person.rb
dosyasını oluşturun ve şu şekilde düzenleyin:
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
Burada, Mapper::Base
self.to_dao
ve self.to_dto
uygulamanızı gerektirir. Bunu yapmak istemiyorsanız, bunun yerine self.map
uygulayabilir ve aldığı özniteliğin bir DAO veya DTO olmasına bağlı olarak to_dao
veya to_dto
çağıran Mapper::Base.map
geçersiz kılabilirsiniz.
Artık veritabanınıza erişmek için bir DAO'nuz, onu istemciye göndermek için bir DTO'nuz ve birini diğerine dönüştürmek için bir Eşleştiriciniz var. Artık bu üç sınıfı, veri tabanından kişileri almanızı ve karşılık gelen bir DTO koleksiyonu döndürmenizi sağlayan mantığı oluşturmak için bir havuz içinde kullanabilirsiniz.
O zaman depoyu oluşturalım. lib/repositories/person.rb
dosyasını oluşturun:
$ touch lib/dtos/person.rb
Bunu şu şekilde düzenleyin:
module Repository class Person < Repository::Base def get DAO::Person.all.map do |person| Mapper::Person.map(person) end end end end
Bu depo, yalnızca tüm kişileri veritabanından alan ve get
bir kişi DTO'ları koleksiyonuna eşleyen örnek yöntemine sahiptir - oldukça basit. Şimdi hepsini bir araya getirelim. Şimdi geriye kalan tek şey hizmeti ve bu depoyu çağıran uç noktayı oluşturmak. Bunu yapmak için lib/person_service.rb
dosyasını oluşturalım:
$ touch lib/person_service.rb
Bunu şu şekilde düzenleyin:
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
"Kişi" hizmeti, depoyu başlatıcısında başlatır. "Kişi" hizmetinin tüm genel örnek yöntemlerinde, ihtiyacınız olmadığında atlayabileceğiniz yük ve başlıklar bulunur. Her ikisi de Hashie::Mash
örnekleridir ve uç noktaya gönderilen değişkenleri öznitelikler veya başlıklar olarak depolarlar ve yanıtları HTTP yanıtlarını taklit eder, çünkü her yanıt, istemcilere gönderilen isteklerin sonucunu bulmak için kullanabilecekleri bir durum koduna sahiptir. hizmet, hizmetin yanıt yüküyle birlikte. Yanıt kodları, bir HTTP sunucusundan beklediğinizle aynıdır. Örneğin, başarılı bir istek, yanıt yüküyle birlikte bir 200 durum kodu döndürür. Bir servis hatası oluşursa, durum kodu 500 olur ve sunucuya gönderilen parametrelerde bir yanlışlık varsa durum kodu 400 olur. Servis, yükü ile birlikte çoğu HTTP durum koduyla cevap verebilir. Örneğin, hizmetinizin müşterilerine belirli bir uç noktaya erişmelerine izin verilmediğini söylemesini istiyorsanız, 403 koduyla yanıt vererek bunu yapabilirsiniz. Yukarıdaki hizmet kodumuza bakarsanız, yanıt kodlarının başka bir örneğini görebilirsiniz. get
uç noktasında, hiç kimse bulunmadığında isteğe bağlı "Burada kimse yok" mesajıyla birlikte 404 durum kodunu döndürüyoruz, tıpkı bir HTTP sunucusunun kullanılabilir kaynak yoksa 404 döndürmesi gibi. Depo gerçekten insanları döndürürse, hizmet DTO'ları seri hale getirir ve bunları istemciye geri gönderir. Her DTO'nun, DTO tanımında attr_reader
veya attr_accessible
olarak tanımlanan anahtarlara ve karşılık gelen değerlere sahip bir JSON nesnesi döndüren varsayılan bir serileştiricisi vardır. Elbette, DTO sınıflarınızda serileştirme yönteminizi tanımlayarak serileştiriciyi geçersiz kılabilirsiniz.
Artık tanımlı bir hizmetimiz olduğuna göre, onu kaydetmemiz gerekiyor. Bu son adımdır. lib/service_register.rb
dosyasını açın ve "HelloWorld"ün tüm oluşumlarını "Person" ile değiştirin, böylece dosya sonunda şöyle görünecek:
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
Muhtemelen fark ettiğiniz gibi, add_route
çağrısında küçük bir değişiklik var. “HELLO/WORLD” dizesini kaldırdık. Bunun nedeni, dizgenin yalnızca hizmet fiilinin onu uygulayan yöntemle eşleşmemesi durumunda gerekli olmasıdır. Bizim durumumuzda, kişi servisini GET fiiliyle çağırırken çağrılacak yöntem get
, böylece dizeyi atlayabiliriz.
ServiceRegister
sınıfı, self.get_service
yöntemini tanımlamanız gereken yerdir. Bu yöntem, hizmeti başlatır ve aracının arka ucuna bağlar. Daha sonra bu hizmetteki rotaları bir veya daha fazla hizmet tanımındaki yöntemlerle eşleştirir. Örneğin, aşağıdaki durumda hizmeti oluşturur ve aracıya bağlar:
config = Hashie::Mash.new( backend: Settings.broker.backend ) service = ZSS::Service.new(:person, config)
Ardından bir servis işleyicisini başlatır:
personInstance = PersonService.new
Ardından, hizmet işleyici hizmete bağlanır:
service.add_route(personInstance, :get)
Son olarak, hizmet örneğini döndürmesi gerekir.
return service
Artık “Person” hizmetimizi başlatabilmemiz için son bir adım kaldı; bunun için yürütülebilir bir komut dosyası oluşturmamız gerekiyor. "HelloService" için zaten bir tane var. Bu nedenle, bin/zss-service
dosyasını açın, "hello-word" yerine "person" yazın ve dosyayı kaydedin. Konsola geri dönün ve çalıştırın:
$ 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'
Bu kadar. “Kişi” hizmetinize ilk kez yeni başladınız. Şimdi test edelim. bin/zss-client
dosyasını açın, sid
değişkenini "person" olarak değiştirin ve müşteri çağrısını hello_world()
'den get()
'e değiştirin. Bu yapıldıktan sonra, istemciyi yeni bir pencerede çalıştırın:
$ 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>'
Gördüğünüz gibi, bir ZSS::Error
yakaladınız. Bunun nedeni, servis tarafından hiç kimse bulunmadığında ve servisimizin veritabanında henüz hiç kimse bulunmadığında bir hata ortaya çıkarmamızdır.
O zaman bu hatayı halledelim. zss-client
açın ve şu şekilde düzenleyin:
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
Şimdi hata kodu 404 olduğunda hata mesajını yazdırıyoruz, farklı ise hatayı yükseltiyoruz. İstemcimizi tekrar çalıştırarak eylemde görelim:
$ bin/zss-client "No people here"
Harika. Şimdi tablomuza birkaç kişi ekleyelim ve hizmet tarafından müşterimize iade edilip edilmediğine bakalım. Bunu yapmak için bir servis konsolu açmanız yeterlidir:
$ rake service:console
Birkaç kişi ekleyin:
$ 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
Şimdi, istemcinizi tekrar çalıştırın.
$ bin/zss-client [{"id"=>1, "name"=>"John"}, {"id"=>2, "name"=>"Mary"}, {"id"=>3, "name"=>"Francis"}]
İşte aldın.
Son düşünceler
Bu kılavuzda verilen kodu incelerken, depolar veya DTO'lar oluşturmak gibi gereksiz birçok adım olduğunu düşünebilirsiniz ve haklısınız. Çalışan bir “Kişi” hizmetine sahip olmak için ihtiyacınız olan tek şey, hizmet sınıfınız ve doğrudan hizmet sınıfından arayabileceğiniz DAO'nuz olacaktır. Yine de, hizmet mantığını veri depolama manipülasyonunuzdan ayrı tutmanıza izin verdiği için bu makalede açıklanan modeli takip etmek iyi bir uygulamadır. Hizmetler yalnızca mantığına odaklanmalıdır ve depolar, veri depolama alanınızla tüm etkileşimleri ele almalıdır. DTO'lar hizmetlerinizin yüklerini ve serileştirmesini belirler ve DAO'lar yalnızca depolamadan veri almakla ilgilenir. Bu kılavuzda açıklanan kurallar ve teknikler, aşağıdaki resimde kontrol edebileceğiniz depo düzeni olarak bilinir.
Bunu yararlı bulan herkese SOA hizmet paketini herhangi bir şekilde genişleterek ve geliştirerek katkıda bulunmalarını isteyerek bitirmek istiyorum. Tüm çatal ve çekme istekleriniz kabul edilir.
Umarım bu, mikro hizmetlere başlamanıza yardımcı olur. Servis kodunu kontrol etmek isterseniz, GitHub'da tam bir sürüm mevcuttur.