Seneca
A Node.js toolkit for Microservice architectures
这是一个基于 NodeJS 的微服务工具套件。
官网地址: http://senecajs.org/
Methods 方法
seneca.add
添加一个新的 action pattern 到 seneca 实例
- pattern 匹配的属性模式
- action 模式匹配消息时要执行的函数,包含两个参数
- msg 匹配的入站消息(作为普通对象提供)
- respond 用于提供消息响应的回调函数。响应函数是具有标准 error, result 签名的回调。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17// 这是相同的两个写法
seneca.add('role:math, cmd:sum', (msg, reply) => {
reply(null, {
answer: (msg.left + msg.right)
})
})
seneca.add({
role: 'math',
cmd: 'sum'
}, function (msg, respond) {
var sum = msg.left + msg.right
respond(null, {
answer: sum
})
})
seneca.act
提交要执行的消息
- msg 消息对象
- response_callback 接收消息响应(如果有)的函数
- err
- result
1
2
3
4
5
6
7
8
9seneca.act({
role: 'math',
cmd: 'sum',
left: 1,
right: 2
}, function (err, result) {
if (err) return console.error(err)
console.log(result)
})
seneca.prior
当前动作模式调用先前的动作定义1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41var seneca = require('seneca')()
seneca
.add(
'role:math,cmd:sum',
function( msg, respond ) {
var sum = msg.left + msg.right
respond( null, { answer: sum } )
})
// override role:math,cmd:sum with additional functionality
.add(
'role:math,cmd:sum',
function( msg, respond ) {
// bail out early if there's a problem
if( !Number.isFinite( msg.left ) ||
!Number.isFinite( msg.right ) )
{
return respond( new Error("Expected left and right to be numbers.") )
}
// call previous action function for role:math,cmd:sum
this.prior({
role: 'math',
cmd: 'sum',
left: msg.left,
right: msg.right,
}, function( err, result ) {
if( err ) return respond( err )
result.info = msg.left+'+'+msg.right
respond( null, result )
})
})
// enhanced role:math,cmd:sum
.act( 'role:math,cmd:sum,left:1.5,right:2.5',
console.log // prints { answer: 4, info: '1.5+2.5' }
)
seneca.wrap
pin 引脚是模式匹配模式
action 动作扩展功能
匹配一组模式,并使用相同的动作扩展功能覆盖所有模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24module.exports = function math(options) {
this.add('role:math,cmd:sum', function sum(msg, respond) {
respond(null, { answer: msg.left + msg.right })
})
this.add('role:math,cmd:product', function product(msg, respond) {
respond(null, { answer: msg.left * msg.right })
})
this.wrap('role:math', function (msg, respond) {
msg.left = Number(msg.left).valueOf()
msg.right = Number(msg.right).valueOf()
this.prior(msg, respond)
})
}
// these are equivalent
require('seneca')()
.use(require('./math.js'))
.act('role:math,cmd:sum,left:1,right:2', console.log)
require('seneca')()
.use('math') // finds ./math.js in local folder
.act('role:math,cmd:sum,left:1,right:2', console.log)
seneca.use
使用插件,Seneca 插件是具有单个参数的函数 options。
- plugin 插件定义函数或插件名称
- options 插件的options对象
1
2
3
4
5
6
7var seneca = require('seneca')()
function minimal_plugin(options) {
console.log(options)
}
seneca.use(minimal_plugin, { foo: 'bar' })
- 插件内部不推荐用 act 方法
- 使用
this.add({ init: 'math' }, function(msg, respond){})可以初始化插件
seneca.listen
服务器的设置(默认使用 HTTP 通过端口 10101 进行监听)
- port 可选整数;端口号
- host 可选字符串;主机IP地址
- spec 可选对象;完整规格对象
seneca.client
- port 可选整数;端口号
- host 可选字符串;主机IP地址
- spec 可选对象;完整规格对象
–seneca.log.all
–seneca.log=plugin:math
–seneca.print.tree
WEB 服务器集成
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20var SenecaWeb = require('seneca-web')
var Express = require('express')
var Router = Express.Router
var context = new Router()
var senecaWebConfig = {
context: context,
adapter: require('seneca-web-adapter-express'),
options: { parseBody: false } // so we can use body-parser
}
var app = Express()
.use( require('body-parser').json() )
.use( context )
.listen(3000)
var seneca = require('seneca')()
.use(SenecaWeb, senecaWebConfig )
.use('api')
.client( { type:'tcp', pin:'role:math' } )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23module.exports = function api(options) {
var valid_ops = { sum:'sum', product:'product' }
this.add('role:api,path:calculate', function (msg, respond) {
var operation = msg.args.params.operation
var left = msg.args.query.left
var right = msg.args.query.right
this.act('role:math', {
cmd: valid_ops[operation],
left: left,
right: right,
}, respond)
})
this.add('init:api', function (msg, respond) {
this.act('role:web',{routes:{
prefix: '/api',
pin: 'role:api,path:*',
map: {
calculate: { GET:true, suffix:'/:operation' }
}
}}, respond)
})
}
附
微服务这一概念出现于2012年,是因软件作者 Martin Fowler 而流行,他承认这并没有精确地定义出这一架构形式,虽然围绕业务能力、自动化部署、终端智能以及语言和数据的分散控制有一些常见的特性。
为了让大家更好的理解,我这里转了一篇大白话的文章,感兴趣的可以看看
如何给老婆解释什么是微服务?