マイクロサービス アーキテクチャ用の 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 メッセージをリッスンする Web サーバーを起動します。これらが到着すると、ローカルの 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 組織は参加を奨励しています。バグ報告、ドキュメント、サンプル、追加のテスト、新機能など、何らかの方法でお手伝いできると思われる場合は、お気軽に問題を作成するか、プル リクエストを送信してください。貢献の詳細については、貢献ガイドをご覧ください。
テストをローカルで実行するには、
npm run test
カバレッジレポートを入手するには、
npm run coverage; open docs/coverage.html
著作権 (c) 2010-2018 Richard Rodger およびその他の寄稿者。 MITの下でライセンスを取得しています。