마이크로서비스 아키텍처용 Node.js 툴킷
이 오픈 소스 모듈은 Voxgig에서 후원하고 지원합니다. |
---|
Seneca는 마이크로서비스를 작성하고 앱의 비즈니스 로직을 구성하기 위한 툴킷입니다. 데이터 모델에 집중하거나 종속성을 관리하는 대신 앱을 "발생하는 일"로 분류할 수 있습니다.
세네카가 제공하는
패턴 매칭: 비즈니스 요구 사항을 처리하는 놀랍도록 유연한 방법
전송 독립성: 메시지가 올바른 서버에 전달되는 방식은 걱정할 필요가 없습니다.
성숙도: 프로덕션 기간 8년( 마이크로서비스 라고 부르기 전), 한 번은 번개로 인해 중단되었습니다.
플러스: 깊고 광범위한 플러그인 생태계
도서: 마이크로서비스 아키텍처 설계 가이드: taomicro
이 모듈을 사용하여 일부 JSON을 사용하고 선택적으로 일부 JSON을 반환하여 작동하는 명령을 정의합니다. 실행할 명령은 입력 JSON에 대한 패턴 일치를 통해 선택됩니다. 최소 실행 가능 제품(데이터 저장, 사용자 관리, 분산 논리, 캐싱, 로깅 등)을 구축하는 데 도움이 되는 기본 제공 및 선택적 명령 세트가 있습니다. 그리고 이를 명령 세트로 나누어 고유한 제품을 정의할 수 있습니다. 일어나는 일들". 거의 그 정도입니다.
이 모듈을 사용 중이고 도움이 필요한 경우 다음을 수행할 수 있습니다.
Seneca를 처음 접하신다면 senecajs.org를 살펴보시기 바랍니다. 튜토리얼부터 샘플 앱까지 모든 것을 갖추고 있어 빠르게 시작하고 실행할 수 있습니다.
Seneca의 소스는 npm run annotate
실행하여 주석이 달린 방식으로 읽을 수 있습니다. 각 파일의 주석이 달린 버전이 ./docs/
에 생성됩니다.
npm을 통해 설치하려면,
npm install seneca
'use strict'
var Seneca = require ( 'seneca' )
// Functionality in seneca is composed into simple
// plugins that can be loaded into seneca instances.
function rejector ( ) {
this . add ( 'cmd:run' , ( msg , done ) => {
return done ( null , { tag : 'rejector' } )
} )
}
function approver ( ) {
this . add ( 'cmd:run' , ( msg , done ) => {
return done ( null , { tag : 'approver' } )
} )
}
function local ( ) {
this . add ( 'cmd:run' , function ( msg , done ) {
this . prior ( msg , ( err , reply ) => {
return done ( null , { tag : reply ? reply . tag : 'local' } )
} )
} )
}
// Services can listen for messages using a variety of
// transports. In process and http are included by default.
Seneca ( )
. use ( approver )
. listen ( { type : 'http' , port : '8260' , pin : 'cmd:*' } )
Seneca ( )
. use ( rejector )
. listen ( 8270 )
// Load order is important, messages can be routed
// to other services or handled locally. Pins are
// basically filters over messages
function handler ( err , reply ) {
console . log ( err , reply )
}
Seneca ( )
. use ( local )
. act ( 'cmd:run' , handler )
Seneca ( )
. client ( { port : 8270 , pin : 'cmd:run' } )
. client ( { port : 8260 , pin : 'cmd:run' } )
. use ( local )
. act ( 'cmd:run' , handler )
Seneca ( )
. client ( { port : 8260 , pin : 'cmd:run' } )
. client ( { port : 8270 , pin : 'cmd:run' } )
. use ( local )
. act ( 'cmd:run' , handler )
// Output
// null { tag: 'local' }
// null { tag: 'approver' }
// null { tag: 'rejector' }
예를 들어 컨테이너에서 정상적으로 실행하려면 다음을 사용하세요.
$ node microservice.js
(여기서 microservice.js
는 Seneca를 사용하는 스크립트 파일입니다.) 로그는 JSON 형식으로 출력되므로 로깅 서비스로 보낼 수 있습니다.
사람이 읽을 수 있는 전체 디버그 로그를 사용하여 테스트 모드에서 실행하려면 다음을 사용하세요.
$ node microservice.js --seneca.test
상관없도록,
일부 명령이 주어진 JSON 문서를 처리할 수 있다면 괜찮습니다.
예는 다음과 같습니다.
var seneca = require ( 'seneca' ) ( )
seneca . add ( { cmd : 'salestax' } , function ( msg , done ) {
var rate = 0.23
var total = msg . net * ( 1 + rate )
done ( null , { total : total } )
} )
seneca . act ( { cmd : 'salestax' , net : 100 } , function ( err , result ) {
console . log ( result . total )
} )
이 코드에서 seneca는 {cmd:'salestax'}
패턴을 발견할 때마다 판매세를 계산하는 이 패턴과 관련된 함수를 실행합니다. cmd
속성에는 특별한 것이 없습니다. 이는 단순히 패턴 일치를 원하는 속성입니다. 모든 seneca 관심 사항에 대해 foo
를 찾을 수 있습니다! 야아!
seneca.add
메소드는 새 패턴을 추가하고 해당 패턴이 발생할 때마다 실행할 함수를 추가합니다.
seneca.act
메소드는 객체를 승인하고 일치하는 명령이 있는 경우 이를 실행합니다.
판매세율은 어디서 나오나요? 다시 시도해 봅시다:
seneca . add ( { cmd : 'config' } , function ( msg , done ) {
var config = { rate : 0.23 }
var value = config [ msg . prop ]
done ( null , { value : value } )
} )
seneca . add ( { cmd : 'salestax' } , function ( msg , done ) {
seneca . act ( { cmd : 'config' , prop : 'rate' } , function ( err , result ) {
var rate = parseFloat ( result . value )
var total = msg . net * ( 1 + rate )
done ( null , { total : total } )
} )
} )
seneca . act ( { cmd : 'salestax' , net : 100 } , function ( err , result ) {
console . log ( result . total )
} )
config
명령은 구성을 제공합니다. 이는 하드 코딩된 파일 시스템, 데이터베이스, 네트워크 서비스 등 어디에서 구성을 가져오는지는 중요하지 않기 때문에 좋습니다. 이 작업을 수행하려면 추상화 API를 정의해야 했나요? 아니요.
여기에는 조금 있지만 너무 많은 장황함이 있다고 생각하지 않습니까? 문제를 해결해 보겠습니다.
seneca . act ( 'cmd:salestax,net:100' , function ( err , result ) {
console . log ( result . total )
} )
객체를 제공하는 대신 JSON의 축약형을 사용하여 문자열을 제공할 수 있습니다. 실제로 다음 두 가지를 모두 제공할 수 있습니다.
seneca . act ( 'cmd:salestax' , { net : 100 } , function ( err , result ) {
console . log ( result . total )
} )
이는 패턴과 매개변수 데이터를 결합하는 매우 편리한 방법 입니다.
Node.js 시스템을 구축하는 방법은 많은 작은 프로세스를 구축하는 것입니다. 왜 이렇게 해야 하는지 설명하는 훌륭한 강연이 있습니다: Programmer Anarchy.
Seneca는 이것을 정말 쉽게 만듭니다. 네트워크의 구성을 자체 프로세스에 넣어 보겠습니다.
seneca . add ( { cmd : 'config' } , function ( msg , done ) {
var config = { rate : 0.23 }
var value = config [ msg . prop ]
done ( null , { value : value } )
} )
seneca . listen ( )
listen
메서드는 JSON 메시지를 수신하는 웹 서버를 시작합니다. 이러한 항목이 도착하면 로컬 Seneca 인스턴스에 제출되고 일반적인 방식으로 작업으로 실행됩니다. 그런 다음 결과는 HTTP 요청에 대한 응답으로 클라이언트에 반환됩니다. Seneca는 메시지 버스를 통해 작업을 수신할 수도 있습니다.
구성 코드 구현은 동일하게 유지됩니다 .
클라이언트 코드는 다음과 같습니다.
seneca . add ( { cmd : 'salestax' } , function ( msg , done ) {
seneca . act ( { cmd : 'config' , prop : 'rate' } , function ( err , result ) {
var rate = parseFloat ( result . value )
var total = msg . net * ( 1 + rate )
done ( null , { total : total } )
} )
} )
seneca . client ( )
seneca . act ( 'cmd:salestax,net:100' , function ( err , result ) {
console . log ( result . total )
} )
클라이언트 측에서 seneca.client()
호출한다는 것은 Seneca가 로컬에서 일치시킬 수 없는 모든 작업을 네트워크를 통해 전송한다는 것을 의미합니다. 이 경우 구성 서버는 cmd:config
패턴을 일치시키고 구성 데이터를 반환합니다.
다시 한번 말씀드리지만, 판매세 코드는 변경되지 않습니다 . 구성이 어디서 왔는지, 누가 제공하는지, 어떻게 제공하는지 알 필요가 없습니다.
모든 명령으로 이 작업을 수행할 수 있습니다.
비즈니스 요구 사항은 상식, 논리 또는 질서 있는 구조를 존중하지 않는다는 것입니다. 현실 세계는 지저분합니다.
이 예에서는 일부 국가에는 단일 판매세율이 있고 다른 국가에는 지역이나 제품 범주에 따라 달라지는 가변 세율이 있다고 가정해 보겠습니다.
코드는 다음과 같습니다. 이 예에서는 구성 코드를 추출해 보겠습니다.
// fixed rate
seneca . add ( { cmd : 'salestax' } , function ( msg , done ) {
var rate = 0.23
var total = msg . net * ( 1 + rate )
done ( null , { total : total } )
} )
// local rates
seneca . add ( { cmd : 'salestax' , country : 'US' } , function ( msg , done ) {
var state = {
'NY' : 0.04 ,
'CA' : 0.0625
// ...
}
var rate = state [ msg . state ]
var total = msg . net * ( 1 + rate )
done ( null , { total : total } )
} )
// categories
seneca . add ( { cmd : 'salestax' , country : 'IE' } , function ( msg , done ) {
var category = {
'top' : 0.23 ,
'reduced' : 0.135
// ...
}
var rate = category [ msg . category ]
var total = msg . net * ( 1 + rate )
done ( null , { total : total } )
} )
seneca . act ( 'cmd:salestax,net:100,country:DE' , function ( err , result ) {
console . log ( 'DE: ' + result . total )
} )
seneca . act ( 'cmd:salestax,net:100,country:US,state:NY' , function ( err , result ) {
console . log ( 'US,NY: ' + result . total )
} )
seneca . act ( 'cmd:salestax,net:100,country:IE,category:reduced' , function ( err , result ) {
console . log ( 'IE: ' + result . total )
} )
이 경우 다양한 패턴에 대해 다양한 구현을 제공합니다. 이를 통해 복잡성을 잘 정의된 위치로 격리할 수 있습니다. 이는 또한 특별한 경우를 매우 쉽게 처리할 수 있음을 의미합니다.
Senecajs 조직은 참여를 권장합니다. 버그 보고, 문서, 예제, 추가 테스트 또는 새로운 기능 등 어떤 식으로든 도움이 될 수 있다고 생각되면 자유롭게 문제를 제기하거나 풀 요청(Pull Request)을 제출하는 것이 더 좋습니다. 기여에 대한 자세한 내용은 기여 가이드를 참조하세요.
로컬에서 테스트를 실행하려면
npm run test
보장 보고서를 얻으려면,
npm run coverage; open docs/coverage.html
저작권 (c) 2010-2018 Richard Rodger 및 기타 기여자; MIT 에 따라 라이센스가 부여되었습니다.