Ruby에서 마이크로서비스 아키텍처를 설정하는 방법: 단계별 가이드
게시 됨: 2022-03-11마이크로서비스란 무엇입니까?
마이크로서비스는 여러 독립 서비스가 서로 통신하고 자체 프로세스와 리소스를 보유하는 소프트웨어 설계의 최신 트렌드 중 하나입니다. 이 접근 방식은 일반적인 클라이언트-서버 응용 프로그램 디자인과 다릅니다. 일반적인 클라이언트-서버 애플리케이션은 하나 이상의 클라이언트, 모든 도메인 데이터 및 논리를 포함하는 모놀리식 백엔드, 클라이언트가 백엔드 및 해당 기능에 액세스할 수 있도록 하는 API로 구성됩니다.
마이크로 서비스 아키텍처에서 설명된 모놀리식 백엔드는 대신 분산 서비스 제품군으로 대체됩니다. 이 설계를 통해 더 나은 책임 분리, 더 쉬운 유지 관리, 각 서비스에 대한 기술 선택의 더 큰 유연성, 더 쉬운 확장성 및 내결함성을 허용합니다. 동시에 복잡한 분산 시스템에는 여러 가지 문제가 있습니다. 경쟁 조건을 처리해야 할 가능성이 더 높고 문제가 하나의 단일 서비스로 쉽게 지적되지 않고 대신 여러 서비스를 통해 분산되기 때문에 디버그하기가 더 어렵습니다. 이러한 시스템을 구축하는 동안 모범 사례를 따르기 위해 노력하지 않으면 진화 방법을 모르는 불에 둘러싸여 자신을 발견할 수 있습니다. 한 서비스의 변경이 모든 클라이언트에 영향을 미치고 결과적으로 모든 백엔드의 서비스 제품군에 영향을 줄 수 있으므로 서비스의 페이로드 계약에 특별한 주의를 기울여야 합니다.
이러한 고려 사항은 모두 중요하지만 이미 고려했다고 가정해 보겠습니다. 이제 원하는 것은 스스로 마이크로서비스 백엔드를 구축하는 방법을 찾는 것입니다. 그럼 바로 그 내용에 대해 알아보도록 하겠습니다.
마이크로서비스 아키텍처를 설정하는 방법
현재 마이크로서비스를 설정할 수 있는 방법은 다양하며 이 가이드에서는 브로커 아키텍처에 중점을 둘 것입니다.
브로커 아키텍처
브로커 아키텍처는 서비스가 서로 통신하도록 할 수 있는 방법 중 하나입니다. 그 안에서 모든 서비스는 메시징 서버인 브로커를 둘러싸고 모두 연결됩니다. 서비스는 브로커에게 메시지를 보내고 브로커는 이 메시지를 전달해야 하는 다른 서비스를 알게 됩니다. 이렇게 하면 서비스에서 다른 서비스에 대한 정보를 유지할 필요가 없습니다. 대신 모든 메시징을 처리하는 브로커에 의존하며 이를 통해 특정 도메인에만 격리되고 집중할 수 있습니다. 브로커는 수신자가 다운된 경우에도 메시지를 저장할 수 있으므로 발신자와 수신자가 동시에 강제 실행되지 않도록 하여 훨씬 더 격리할 수 있습니다. 물론 모든 통신이 브로커를 거쳐야 하므로 브로커가 빠르게 병목 상태가 될 수 있고 백엔드의 단일 실패 지점이 될 수도 있기 때문에 이 솔루션에는 단점이 있습니다. 그러나 이러한 문제를 완화할 수 있는 몇 가지 방법이 있습니다. 한 가지 방법은 브로커의 여러 인스턴스를 병렬로 실행하여 시스템 내결함성을 향상시키는 것입니다. 다른 방법은 다른 아키텍처를 사용하는 것입니다. 대체 아키텍처는 브로커를 사용하지 않거나 다른 브로커 아키텍처를 사용하거나 HTTP와 같은 다른 메시징 프로토콜을 사용하여 이 가이드에서 구현할 아키텍처와 다릅니다.
서비스 간 통신
이 가이드에서는 ZeroMQ를 사용하여 서비스와 브로커 간의 통신을 처리합니다.
ZeroMQ는 무작위 전송을 통해 다중 부분 비동기 메시지를 처리하는 프로토콜 추상화 계층을 제공합니다. 서비스와 브로커 간의 메시징에 ZeroMQ를 사용하는 이점은 이 가이드의 범위를 벗어나므로 여기서 바로 다루지는 않겠지만, 이에 대해 더 알고 싶다면 다음 Quora 기사를 확인하십시오. 귀하의 서비스가 서로 통신하도록 하는 다른 방법을 찾는 데 관심이 있다면 Broker vs. Brokerless 기사를 보고 다른 무엇을 얻을 수 있는지 확인하는 것이 좋습니다.
마이크로서비스 제품군 구축
이 문서에서는 마이크로서비스 제품군을 만드는 데 필요한 모든 단계를 안내합니다. 우리 시스템은 브로커와 서비스로 구성됩니다. 우리는 또한 서비스 제품군에 대한 호출을 테스트하기 위해 작은 클라이언트 스크립트를 사용할 것이지만 클라이언트 코드는 어디서나 쉽게 사용할 수 있다는 점을 명심하십시오.
자, 이제 빌드를 시작해 보겠습니다.
시작하기
먼저 브로커와 서비스를 실행하는 데 필요한 모든 것이 있는지 확인합니다. 먼저 컴퓨터에 Node.js, ZeroMQ 및 Git을 다운로드하여 설치합니다. OSX를 사용하는 경우 각각에 대한 homebrew 패키지가 있고 대부분의 Linux 배포판에도 각각에 대한 패키지가 있으므로 문제가 없을 것입니다. Windows 사용자는 위에 제공된 다운로드 링크를 사용하기만 하면 됩니다.
브로커 실행
필요한 모든 종속성을 설치한 후 브로커를 실행해 보겠습니다. 이 가이드에서는 ZMQ Service Oriented Suite의 일부인 브로커의 Node.js 구현을 사용하고 있습니다. GitHub에서 해당 코드와 설명서를 찾을 수 있습니다. 브로커를 실행하려면 먼저 브로커 부트스트랩을 머신에 복제합니다. 이 저장소는 위의 브로커 라이브러리를 사용하기 위한 부트스트랩입니다. 원본 라이브러리 자체가 실행 가능하므로 이 단계는 필요하지 않지만 두 가지 차이점은 부트스트랩 리포지토리에서 기본 구성을 변경할 수 있다는 것입니다.
따라서 먼저 다음 Git 명령을 사용하여 프로젝트를 컴퓨터에 다운로드합니다.
$ git clone [email protected]:dadah/zmq-broker-bootstrap.git
완료한 후 생성된 디렉터리로 이동합니다.
$ cd zmq-broker-bootstrap
이제 패키지 종속성을 설치합니다.
$ npm install
이제 브로커가 준비되었습니다. 브로커를 실행하려면 다음 명령을 실행하십시오.
$ bin/zss-broker run
config/
디렉토리에서 각 환경에 대한 구성 파일을 찾을 수 있습니다. 다음은 기본 개발 구성입니다.
{ "broker": { "backend": "tcp://127.0.0.1:7776", "frontend": "tcp://127.0.0.1:7777" }, "log": { "consolePlugin": { "level": "debug" } } }
backend
매개변수는 브로커의 백엔드 및 프런트엔드의 ip:port
주소를 정의합니다. 백엔드 주소는 브로커가 서비스로부터 요청을 수신하고 응답하는 곳이고, 프론트엔드 주소는 브로커가 서비스 클라이언트를 수신하고 보내는 곳입니다. log.consolePlugin.level
을 변경하여 로깅 수준을 설정할 수도 있습니다. 가능한 값은 trace
, debug
, info
, warn
및 error
이며 브로커 프로세스가 출력할 로깅 정보의 양을 결정합니다.
서비스 실행
브로커를 가동한 후에는 첫 번째 Ruby 마이크로서비스를 개발할 차례입니다. 새 콘솔 창을 열어 시작하십시오. 그런 다음 서비스가 저장될 디렉터리를 만든 다음 해당 디렉터리로 이동합니다. 이 가이드에서는 ZMQ SOA Suite의 Ruby 클라이언트와 서비스를 사용하고 있습니다. 사용할 수 있는 부트스트랩 "Hello world" 서비스가 있으므로 이를 사용하여 첫 번째 마이크로서비스를 실행해 보겠습니다.
서비스 디렉토리로 이동하여 부트스트랩 저장소를 복제합니다.
$ git clone [email protected]:dadah/zmq-service-suite-ruby-bootstrap.git
새로 생성된 디렉터리로 이동합니다.
$ cd zmq-service-suite-ruby-bootstrap
이제 모든 종속성을 설치합니다.
$ bundle install
서비스를 시작하려면 다음 명령을 실행하십시오.
$ bin/zss-service run
엄청난. 첫 번째 서비스가 실행 중입니다.
브로커를 실행한 상태로 둔 콘솔 창으로 이동하면 다음 출력을 볼 수 있습니다.
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
이 로그는 브로커가 새 서비스의 존재를 확인했으며 서비스로부터 하트비트 메시지를 수신하고 있음을 의미합니다. 서비스는 1초마다 하트비트 메시지를 브로커에 보내 서비스 인스턴스가 작동 중임을 알 수 있습니다.
서비스에서 소비
이제 서비스가 실행 중입니다. 어떻게 사용합니까?
부트스트랩 저장소에는 "Hello World" 서비스를 테스트하는 데 사용할 수 있는 더미 클라이언트가 있습니다. 새 콘솔 창이나 탭을 열고 서비스 디렉토리로 이동하기만 하면 됩니다. 일단 거기에 있으면 다음 명령을 실행하십시오.
$ bin/zss-client
다음과 같이 표시되어야 합니다.
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"
서비스가 실행 중인 콘솔 창으로 이동하면 다음이 표시되어야 합니다.
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
좋은. "Hello World" 마이크로서비스를 시작하고 사용했습니다. 그러나 이것은 우리가 하기로 한 것이 아닙니다. 서비스를 구축하고자 합니다. 그럼 시작하겠습니다.
서비스 구축
먼저 "Hello World" 서비스를 중지하겠습니다. 서비스의 콘솔 창으로 이동하고 Ctrl+C
를 눌러 서비스를 중지합니다. 다음으로 "Hello World" 서비스를 "Person" 서비스로 바꿔야 합니다.
코드 구조
먼저 프로젝트의 코드 트리를 살펴보겠습니다. 다음과 같이 보입니다.
-
bin
디렉토리는 서비스를 시작하는 스크립트를 저장하는 곳입니다. -
config
디렉토리는 모든 구성 파일을 저장합니다.-
boot.rb
파일은 모든 서비스 종속성을 추가할 수 있는 곳입니다. 열면 이미 많은 종속성이 나열되어 있음을 알 수 있습니다. 더 추가해야 하는 경우 여기에서 추가해야 합니다. -
application.yml
파일은 모든 애플리케이션 설정을 저장합니다. 이 파일은 나중에 살펴보겠습니다. -
config/initializers
디렉토리에서 이니셜라이저 스크립트를 추가할 수 있습니다. 예를 들어 여기에서 ActiveRecord 또는 Redis 연결에 대한 설정을 추가할 수 있습니다. 이 디렉토리에 추가한 스크립트는 서비스 시작 시 실행됩니다.
-
-
db/migrate
디렉토리에 ActiveRecord 또는 Sequel 마이그레이션이 있는 경우 저장할 수 있습니다. 그렇지 않은 경우 이 디렉토리를 모두 삭제할 수 있습니다. -
lib
디렉토리는 주요 애플리케이션 코드가 있는 곳입니다.-
settings.rb
파일은 단순히application.yml
파일을 로드하고 서비스 범위 전체에서 사용할 수 있도록 하므로 어디서나 구성에 액세스할 수 있습니다. 예를 들어,Settings.broker.backend
는 위의 YML 파일에서 정의한 브로커 백엔드 주소를 반환합니다. -
service_register.rb
파일은 서비스 및 서비스 경로를 등록하는 곳입니다. 나중에 설명하겠습니다. -
hello_world_service.rb
파일은 "Hello World" 서비스의 끝점을 정의합니다. -
lib/daos
디렉터리는 ActiveRecord를 사용하는 경우 ActiveModel 개체를 저장하거나 Sequel 모델과 같이 결국 만들 수 있는 다른 데이터 액세스 개체를 저장하는 곳입니다. -
lib/dtos
디렉토리는 데이터 전송 객체를 저장합니다. 이러한 개체는 결국 서비스의 클라이언트로 다시 전송되는 개체입니다. -
lib/repositories
디렉토리는 저장소를 저장합니다. 리포지토리는 서비스가 데이터에 액세스할 수 있도록 하는 개체이며 DAO를 처리할 수 있는 유일한 개체입니다. 따라서 서비스가 "Hello World" 인스턴스 그룹을 원하는 경우 저장소에 요청합니다. 저장소는 차례로 적절한 DAO를 사용하여 데이터베이스에서 관련 데이터를 가져옵니다. 그런 다음 데이터는 서비스에 반환되는 적절한 "HelloWorld" DTO 또는 "HelloWorld" DTO 컬렉션에 매핑됩니다. -
lib/repositories/mappers
디렉토리는 매퍼를 저장하는 곳입니다. 매퍼는 DAO를 DTO로 또는 그 반대로 변환하는 개체입니다.
-
config
디렉토리의 application.yml
파일은 다음과 같습니다.
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
이 설정은 단순히 브로커의 백엔드 및 프런트엔드 주소와 로깅 수준을 설정합니다.

지금까지 이 모든 것이 혼란스럽게 들린다면 계속 진행하면서 더 명확해질 것이므로 걱정하지 마십시오.
"사람" 서비스
이제 "Person" 서비스를 계속 진행해 보겠습니다. 데이터베이스 연결을 구성하는 것으로 시작하겠습니다. config/initializers/active_record.rb
파일을 열고 거기에 있는 유일한 줄의 주석 처리를 제거합니다. 그런 다음 application.yml
의 개발 구성에 다음 항목을 추가하여 다음과 같이 보이도록 합니다.
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
데이터베이스 구성을 추가했으므로 이제 데이터베이스를 생성해야 합니다. 현재 기본 PostgreSQL 데이터베이스를 사용하지 않는 한 이 작업을 자동으로 수행할 방법이 없습니다. 이 경우 다음을 간단히 실행할 수 있습니다.
$ rake db:create
다른 데이터베이스를 선호하는 경우 적절한 gem을 gemfile에 추가한 다음 프로젝트를 번들로 설치해야 합니다.
다음은 마이그레이션입니다. 이를 위해 000_creates_persons.rb
라는 db/migrate
파일을 생성하기만 하면 됩니다.
$ touch db/migrate/000_creates_persons_table.rb
파일을 열고 일반 Rails 마이그레이션과 마찬가지로 마이그레이션을 생성합니다.
class CreatesPersons < ActiveRecord::Migration def change create_table :persons do |t| t.name t.timestamps end end end
다음으로 실행합니다.
$ 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) =======================================
이제 테이블이 생성되었으므로 테이블에 대한 모델을 생성해 보겠습니다. lib/daos/person.rb
파일 생성:
$ touch lib/daos/person.rb
다음과 같이 편집합니다.
module DAO class Person < ActiveRecord::Base end end
당신의 모델이 있습니다. 이제 클라이언트에게 반환할 수 있도록 "사람"에 대한 DTO 모델을 만들어야 합니다. lib/dtos/person.rb
파일을 만듭니다.
$ touch lib/dtos/person.rb
다음과 같이 편집합니다.
module DTO class Person < Base attr_reader :id, :name end end
다음으로 "Person" DAO를 "Person" DTO로 변환하기 위해 Mapper를 생성해야 합니다. lib/repositories/mappers/person.rb
파일을 만들고 다음과 같이 편집합니다.
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
여기에서 Mapper::Base
는 self.to_dao
및 self.to_dto
를 구현하도록 요구합니다. 그렇게 하지 않으려면 대신 self.map
을 구현하고 받는 속성이 DAO인지 DTO인지에 따라 to_dao
또는 to_dto
를 호출하는 Mapper::Base.map
을 재정의할 수 있습니다.
이제 데이터베이스에 액세스하기 위한 DAO, 클라이언트로 보내기 위한 DTO, 하나를 다른 것으로 변환하는 매퍼가 있습니다. 이제 저장소 내에서 이 세 가지 클래스를 사용하여 데이터베이스에서 사람을 가져오고 해당하는 DTO 컬렉션을 반환할 수 있는 논리를 만들 수 있습니다.
그럼 저장소를 생성해봅시다. lib/repositories/person.rb
파일 생성:
$ touch lib/dtos/person.rb
다음과 같이 편집합니다.
module Repository class Person < Repository::Base def get DAO::Person.all.map do |person| Mapper::Person.map(person) end end end end
이 리포지토리에는 데이터베이스에서 모든 사람을 가져와서 사람 DTO 모음에 매핑하는 get
인스턴스 메서드만 있습니다. 매우 간단합니다. 이제 이 모든 것을 하나로 모읍시다. 이제 이 저장소를 호출하는 서비스와 끝점을 만드는 일만 남았습니다. 그렇게 하려면 lib/person_service.rb
파일을 생성해 보겠습니다.
$ touch lib/person_service.rb
다음과 같이 편집합니다.
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
"Person" 서비스는 이니셜라이저에서 리포지토리를 초기화합니다. "Person" 서비스의 모든 공개 인스턴스 메소드에는 페이로드와 헤더가 있으며 필요하지 않은 경우 생략할 수 있습니다. 둘 다 Hashie::Mash
인스턴스이며 끝점에 보낸 변수를 속성이나 헤더로 저장하고 각 응답에는 클라이언트가 보낸 요청의 결과를 찾는 데 사용할 수 있는 상태 코드가 있으므로 응답은 HTTP 응답을 모방합니다. 서비스의 응답 페이로드와 함께. 응답 코드는 HTTP 서버에서 기대하는 것과 동일합니다. 예를 들어 성공적인 요청은 응답 페이로드와 함께 200 상태 코드를 반환합니다. 어떤 서비스 오류가 발생하면 상태 코드는 500이 되고 서버에 전송된 매개 변수에 문제가 있는 경우 상태 코드는 400이 됩니다. 서비스는 페이로드와 함께 대부분의 HTTP 상태 코드로 응답할 수 있습니다. 따라서 예를 들어 서비스가 클라이언트에게 특정 엔드포인트에 대한 액세스가 허용되지 않을 때 이를 알리고 싶다면 403 코드로 응답하면 됩니다. 위의 서비스 코드를 다시 보면 응답 코드의 다른 예를 볼 수 있습니다. get
엔드포인트에서 사람이 없으면 선택적인 "No people here" 메시지와 함께 상태 코드 404를 반환합니다. 마치 HTTP 서버가 사용 가능한 리소스가 없는 경우 404를 반환하는 것과 같습니다. 저장소가 실제로 사람을 반환하는 경우 서비스는 DTO를 직렬화하여 클라이언트에 반환합니다. 각 DTO에는 DTO 정의에서 attr_reader
또는 attr_accessible
로 정의된 키 및 해당 값이 있는 JSON 개체를 반환하는 기본 직렬 변환기가 있습니다. 물론 DTO 클래스에서 serialize 메서드를 정의하여 serializer를 재정의할 수 있습니다.
이제 서비스가 정의되었으므로 등록해야 합니다. 이것이 마지막 단계입니다. lib/service_register.rb
파일을 열고 "HelloWorld"의 모든 항목을 "Person"으로 대체하여 파일이 최종적으로 다음과 같이 보이도록 합니다.
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
아마 눈치채셨겠지만, add_route
호출에 약간의 변화가 있습니다. "HELLO/WORLD" 문자열을 제거했습니다. 서비스 동사가 그것을 구현하는 메서드와 일치하지 않는 경우에만 문자열이 필요하기 때문입니다. 우리의 경우 GET 동사로 person 서비스를 호출할 때 호출할 메서드는 get
이므로 문자열을 생략할 수 있습니다.
ServiceRegister
클래스는 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
이제 "Person" 서비스를 시작하기 전에 마지막 단계만 남았습니다. 이를 위한 실행 가능한 스크립트를 만들어야 합니다. "HelloService"에 대해 이미 하나가 있습니다. 따라서 bin/zss-service
파일을 열고 "hello-word"를 "person"으로 대체하고 파일을 저장합니다. 콘솔로 돌아가서 다음을 실행합니다.
$ 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'
그게 다야 처음으로 "사람" 서비스를 시작했습니다. 이제 테스트해 보겠습니다. bin/zss-client
파일을 열고 sid
변수를 "person"으로 변경하고 클라이언트 호출을 hello_world()
에서 get()
으로 변경합니다. 완료되면 새 창에서 클라이언트를 실행합니다.
$ 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>'
보시다시피 ZSS::Error
를 잡았습니다. 이는 서비스에서 사람을 찾지 못하고 서비스 데이터베이스에 아직 사람이 없을 때 오류가 발생하기 때문입니다.
그러면 이 오류를 처리해 보겠습니다. zss-client
를 열고 다음과 같이 편집합니다.
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
이제 우리는 오류 코드가 404일 때 오류 메시지를 인쇄하고 있고, 다른 경우 오류를 발생시킵니다. 클라이언트를 다시 실행하여 작동하는 모습을 보겠습니다.
$ bin/zss-client "No people here"
훌륭한. 이제 테이블에 사람을 추가하고 서비스가 클라이언트에게 반환하는지 확인하겠습니다. 이렇게 하려면 서비스 콘솔을 열면 됩니다.
$ rake service:console
몇 명 추가:
$ 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
이제 클라이언트를 다시 실행하십시오.
$ bin/zss-client [{"id"=>1, "name"=>"John"}, {"id"=>2, "name"=>"Mary"}, {"id"=>3, "name"=>"Francis"}]
당신은 그것을 가지고 있습니다.
최종 고려 사항
이 가이드에서 제공하는 코드를 살펴보면 리포지토리 또는 DTO 생성과 같이 불필요한 단계가 많이 있다고 생각할 수 있으며 그 생각이 옳습니다. "사람" 서비스가 작동하기 위해 필요한 것은 서비스 클래스와 DAO뿐이며, 서비스 클래스에서 직접 호출할 수 있습니다. 그럼에도 불구하고 이 문서에 설명된 패턴을 따르는 것이 좋습니다. 이렇게 하면 데이터 저장소 조작과 서비스 논리를 분리할 수 있습니다. 서비스는 논리에만 집중해야 하며 저장소는 데이터 저장소와의 모든 상호 작용을 처리해야 합니다. DTO는 서비스의 페이로드 및 직렬화를 결정하고 DAO는 저장소에서 데이터를 가져오는 데만 관심이 있습니다. 이 가이드에서 설명하는 규칙과 기술은 저장소 패턴으로 알려져 있으며 아래 이미지에서 확인할 수 있습니다.
이 기능이 유용하다고 생각하는 모든 사람에게 SOA 서비스 제품군을 확장하고 어떤 식으로든 향상하여 기여하도록 요청하는 것으로 마무리하고 싶습니다. 모든 포크와 풀 리퀘스트를 환영합니다.
이것이 마이크로서비스를 시작하는 데 도움이 되기를 바랍니다. 서비스 코드를 확인하려면 GitHub에서 전체 버전을 사용할 수 있습니다.