Набор инструментов Node.js для микросервисных архитектур.
Этот модуль с открытым исходным кодом спонсируется и поддерживается Voxgig. |
---|
Seneca — это набор инструментов для написания микросервисов и организации бизнес-логики вашего приложения. Вы можете разбить свое приложение на «то, что происходит», вместо того, чтобы сосредотачиваться на моделях данных или управлении зависимостями.
Сенека указывает,
сопоставление с образцом: удивительно гибкий способ удовлетворения бизнес-требований
транспортная независимость: вам не стоит беспокоиться о том, как сообщения попадают на нужный сервер.
зрелость: 8 лет в продакшене (раньше мы называли это микросервисами ), но однажды был вынесен молнией
плюс: глубокая и обширная экосистема плагинов.
книга: руководство по проектированию микросервисных архитектур: taomicro
Используйте этот модуль для определения команд, которые работают, принимая некоторый JSON и, при необходимости, возвращая некоторый JSON. Команда для запуска выбирается путем сопоставления с шаблоном входного JSON. Существуют встроенные и дополнительные наборы команд, которые помогают создавать минимально жизнеспособные продукты: хранение данных, управление пользователями, распределенная логика, кэширование, ведение журналов и т. д. И вы можете определить свой собственный продукт, разбив его на набор команд - " вещи, которые случаются». Вот и все.
Если вы используете этот модуль и вам нужна помощь, вы можете:
Если вы впервые знакомы с Seneca, загляните на senecajs.org. У нас есть все: от учебных пособий до примеров приложений, которые помогут вам быстро приступить к работе.
Исходный код Сенеки можно прочитать в аннотированном виде, запустив 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
нет ничего особенного. Это просто свойство, которое мы хотим сопоставить с образцом. Вы можете искать 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 — это создание множества небольших процессов. Вот отличный доклад, объясняющий, почему вам следует это делать: Анархия программистов.
Сенека делает это очень легко. Давайте вынесем конфигурацию в сеть в отдельный процесс:
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 . 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 гг. Ричард Роджер и другие участники; Лицензия MIT .