该模块参考了 node-zookeeper-dubbo 模块
CHANGE.LOG
-
2020-03-23
- 增加consumer 默认参数用于提前构造公用参数
- 增加针对provider注册参数过滤特定provider能力
-
2019-02-11
- 增加provider能力 用于给外部提供服务
- 修复consumer provider不自动热替换服务的问题
-
2019-01-30
- 移除对单provider线程池 保证高并发执行稳定
- 限制对单provider最大并发数为总并发数的一半
- 修复兜底超时回调可能会导致并发数错误问题
- 修复超时回调可能访问异常的问题
-
2019-01-29
- 修复调用异常错误处理超时
-
2019-01-28
- 修复并发数高出最大并发数的bug
- 修复socket关闭后回调访问属性出错
- 修改解码流程
-
2019-01-25
- 修改默认连接池数量为 2
- 重构调用策略同等数量调用,效率提升了4倍左右
附加库
- js-to-java 数据转换库
- 本地api
Promise
形式接口调用 自动维护超时时间 - 点对点
socket
连接 内部自动维护socket
连接池 - 自动维护
zookeeper
连接状态 event
形式通知内部状态ready
方法等待dubbo
初始化完成
- koa2形式服务开发
- 自动转换数据格式
npm install dubbo4node --save
const {Consumer} = require('dubbo4node')
// 注册dubbo客户端
const remoteDubbo = new Consumer({
application: 'your app name',
address: 'zookeeper address',
path: 'dubbo',
version: '1.1.3',
services: {
Remote: {
interface: 'com.remote.Remote',
version: '1.0',
methods: {
func1: [
(param, java) => java('com.remote.params.Remote', param)
]
}
}
}
})
// 等待dubbo服务初始化完成 调用dubbo接口
remoteDubbo.ready().then(() => {
return remoteDubbo.Remote.func1({
test: 1
})
}).then(res => {
console.log(res)
}).catch(e => {
console.log(e)
})
客户端构造函数 用于创建一个dubbo客户端
参数
- path
string
dubbo服务在zookeeper中注册的命名空间 - version
string
dubbo版本 - application
string
本地客户端名称 - address
string
zookeeper服务地址 - providerFilter
function
筛选当前接口使用哪些provider服务,该选项用于根据服务参数定制使用的provider默认为使用全部provider
- services
object
声明使用的dubbo接口 - services.remote.interface
string
dubbo公开接口 - services.remote.version
string
dubbo接口版本 - services.remote.token
string
是否启用token验证 可选 - services.remote.attachments
object | function
接口上下文变量 可选 - services.remote.group
string
接口分组 可选 - services.remote.methods
object
dubbo接口参数转义声明 可选 - services.remote.methods.fun1
array
参数转义函数数组
示例
const {Consumer} = require('dubbo4node')
const BetaConsumer = Consumer.default({
// 筛选特定provider
providerFilter: (service, provider) => {
return provider.profile === 'beta'
},
})
const dubbo = new BetaConsumer({
application: 'my_dubbo',
version: '1.1.3',
address: '127.0.0.1:2181',
// 覆盖默认参数
providerFilter: (service, provider) => {
return provider.profile === 'temp'
},
services: {
remote: {
interface: 'com.remote.Remote',
version: '1.0',
token: 'true',
group: 'test',
attachments: {
xxx: '1'
},
methods: {
fun1: [
// 长度视参数数量决定 第一个是参数值 第二个是js-to-java数据转换库
(param, java) => java.String(param)
]
}
}
}
})
// 直接调用即可
dubbo.remote.fun1('arg1').then(res => {
}).catch(e => {
})
很多场景需要启动就调用某个函数 所以提供了此函数
示例
// 单个interface使用
dubbo.ready().then((dubbo) => {
return dubbo.remote.fun1('arg1')
})
// 指定interface
dubbo.ready('remote').then((dubbo) => {
return dubbo.remote.fun1('arg1')
})
事件回调中提供了内部状态改变的通知 包含 zookeeper、socket、内部状态
error
zookeeper 连接出错、连接断开、认证失败、获取节点出错、创建客户端出错zookeeper-node-change
zookeeper 上注册的dubbo服务节点变化dubbo-socket-retry
socket 连接异常重试连接服务dubbo-server-merge
dubbo 节点变更合并新旧服务节点dubbo-ready
dubbo 服务初始化完成可以使用对应的服务
示例
/**
* zookeeper 连接状态不正常回调
*/
dubbo.on('error', (error, option) => {
// 如果不处理此事件的话 会导致consumer进程直接退出
})
/**
* dubbo 在zookeeper上注册的节点变化
*/
dubbo.on('zookeeper-node-change', (option) => {
})
/**
* provider socket 异常断开 重试连接
*/
dubbo.on('dubbo-socket-retry', (provider) => {
})
/**
* newServices 新的server列表
* mergedServices 合并后的server列表
*/
dubbo.on('dubbo-server-merge', (newServices, mergedServices) => {
})
/**
* dubbo 实例
* service 初始化完毕的service
*/
dubbo.on('dubbo-ready', (dubbo, service) => {
})
const {Provider, Service} = require('dubbo4node')
// 创建一个provider 用于处理整个服务的运行
const app = new Provider({
application: {
name: 'you provider',
version: '1.0'
},
version: '1.1.3',
ip: '0.0.0.0',
port: 20880,
zookeeper: {
address: 'zookeeper address',
path: 'path to zookeeper'
}
})
// 创建一个service 用于公开服务
const service = new Service({
interface: 'com.remote.Remote',
version: '1.0'
})
// 向外暴露调用接口
service.method('fun1', async (ctx, next, java) => {
const {args} = ctx
const [id] = args
ctx.result = id
})
// 把service注册给provider
app.addService(service)
// 添加全局中间件
app.use(async (ctx, next, java) => {
})
// 启动整个dubbo服务
app.start(() => {
console.log('dubbo start done')
})
服务端构造函数 创建一个dubbo服务端
参数
- application.name
string
服务名称 - application.version
string
服务版本 - version
string
dubbo版本 - ip
string
监听ip地址 - port
number
监听端口 - zookeeper
object
zookeeper 配置 详见 node-zookeeper-client - zookeeper.address
string
zookeeper 服务地址 - zookeeper.path
string
zookeeper 上注册的命名空间 - executes
number
最大执行队列 默认 1k - timeout
number
超时时间 默认5秒 - environment
string
运行环境 - organization
string
组织架构 - owner
string
负责人 - revision
string
修订版本号 - token
string
是否启用zookeeper token验证
示例
const {Provider} = require('dubbo4node')
// 创建一个provider 用于处理整个服务的运行
const app = new Provider({
application: {
name: 'you provider',
version: '1.0'
},
version: '1.1.3',
ip: '0.0.0.0',
port: 20880,
zookeeper: {
address: 'zookeeper address',
path: 'path to zookeeper'
}
})
向provider添加一个公开的服务
参数
- service
Service
Service 服务
示例
const {Service} = require('dubbo4node')
const service = new Service({
interface: 'com.remote.Remote',
version: '1.0'
})
service.method('fun1', async (ctx, next, java) => {
})
app.addService(service)
向provider添加一个全局的中间件
ps: 需要手动调用 next()
来继续执行后面的中间件 否则直接返回 null
示例
app.use(async (ctx, next)=>{
return 0 // 直接返回一个值的话 则不会再去执行服务里面的方法
})
app.use(async (ctx, next)=>{
await next()
console.log(ctx.result) // 获取服务执行结果
})
服务启动完成回调
参数
- callback
function
启动完成回调函数
示例
app.start(() => {
console.log('dubbo service init done')
})
服务变动事件
error
socket 错误close
socket 关闭
创建一个服务
参数
- interface
string
对外开放的interface名称 - version
string
interface版本
示例
const {Service} = require('dubbo4node')
const service = new Service({
interface: 'com.remote',
version: '1.0'
})
向外公开方法
参数
- name
string
方法名称 - ...functions
Function[]
方法实现
示例
const {Service} = require('dubbo4node')
const service = new Service({
interface: 'com.remote.Remote',
version: '1.0'
})
service.method('fun1', async (ctx, next) => {
const {args} = ctx
const [id] = args
await next() // 执行中间件
ctx.result = id // 返回结果
})
provider调用上下文对象
属性
- method
string
当前方法名 - args
any[]
调用参数数组- 客户端调用方法传递的参数 以数组形式传递进来
- attachments
object
客户端携带上下文- 客户端调用传递的附加数据 包含各种自定义信息 作用类似http cookie的作用
- result
any
返回结果- 当前调用返回给调用方的结果值 可以是任意值
- interface
string
当前方法所属interface- 创建Service时候传递的值
- version
string
当前interface版本- 如上
- buffer
Buffer
原始数据包- 当前dubbo调用的原始数据包
- socket
Socket
原始socket- 当前客户端对应的socket连接
- request
Protocol
请求协议头- 当前客户端对应的请求协议头数据
中间件和koa2的书写形式完全一样,只不过多了一个js-to-java库用来协助转换数据
全局中间件优先级高于Service
的中间件
示例
const {Provider, Service} = require('dubbo4node')
// 创建一个provider 用于处理整个服务的运行
const app = new Provider({
application: {
name: 'you provider',
version: '1.0'
},
version: '1.1.3',
ip: '0.0.0.0',
port: 20880,
zookeeper: {
address: 'zookeeper address',
path: 'path to zookeeper'
}
})
// 创建一个service 用于公开服务
const service = new Service({
interface: 'com.remote.Remote',
version: '1.0'
})
// 向外暴露调用接口
service.method('fun1', async (ctx, next, java) => {
const {args} = ctx
const [id] = args
ctx.result = java.String(`${id}`)
})
// 把service注册给provider
app.addService(service)
// 添加全局中间件
app.use(async (ctx, next, java) => {
// 如果在任意一个中间件内不显示调用 next() 的话则直接返回结果
ctx.result = java.int(100)
})
// 启动整个dubbo服务
app.start(() => {
console.log('dubbo start done')
})