随着 BFF 的普及,越来越多的应用使用 Nodejs 作为中间层来提供 SSR、WEB API聚合等能力,而类似 Java 等后端更加偏向于服务下沉,而 node 和 java 之间的调用如果走 http 的话,性能没有 rpc 来的高效,在这里介绍一下 node 和 java 之前使用 dubbo 协议的实例(后续还会有 ws / grpc 等)
在这里使用 daze.js
框架提供的 dubbo-provider
扩展来提供 dubbo
通信能力
$ npx @dazejs/cli create dubbo_project 复制代码
$ cd dubbo_project $ npm install --save-dev @dazejs/dubbo-provider 复制代码
将扩展加入到 daze.js
配置文件中,配置文件位于 src/config/app.ts
import { DubboServiceProvider } from '@dazejs/dubbo-provider' export default { // ... providers: [ // ... DubboServiceProvider ] }; 复制代码
直接在 src/config/
目录下创建 dubbo.ts
, 可以在其中定义需要用到的注册中心地址:
export default { default: { // 字段名即为注册中心命名 type: 'zookeeper', // 注册中心类型,目前只支持 zookeeper host: '127.0.0.1:2181', // zookeeper host地址,hostname+port port: 20880 // 对外提供的 dubbo 服务端口 } }; 复制代码
在 src/app/
目录下创建 exmple-consumer.ts
(框架会自动读取该目录下的文件进行加载)
import { DubboConsumer, dubbo } from '@dazejs/dubbo-provider'; @dubbo.registry('default') // 上面 dubbo.ts 提供的注册中心地址 @dubbo.interface('com.alibaba.dubbo.demo.DemoProvider', '1.0.0') // 提供者接口地址, 1.0.0 为接口版本号 export class ExampleConsumer extends DubboConsumer { // ... } 复制代码
ExampleConsumer
必须继承自 DubboConsumer
才能被框架识别为一个 dubbo 消费者
在 src/app
下创建一个控制器,我们在控制器方法里面消费 java 数据
import { Controller, http, inject } from '@dazejs/framework'; import DemoConsumer from '../dubbo/consumers/demo'; export class ExampleController extends Controller { @inject(DemoConsumer) demoConsumer: DemoConsumer; // 注入消费者实例 @http.get() async index() { // 消费方法,参数使用数组的形式传入 // 调用 java com.alibaba.dubbo.demo.DemoProvider 类的 sayHello 方法 const res = await this.demoConsumer.invoke('sayHello', ['world']); return res; } } 复制代码
框架会转换简单的参数的类型为 java 类型,推荐使用 java.String('world')
进行手动转换
我们也可以创建提供者来供其他方来调用
import { DubboProvider, dubbo } from '@dazejs/dubbo-provider'; @dubbo.registry('default') @dubbo.interface('com.alibaba.dubbo.demo.NodeDemoProvider', '1.0.0') export default class extends DubboProvider { @dubbo.method() sayHello(name: string) { return `Hello ${name}`; } } 复制代码
java 调用, 这里省略了 api 与 xml 的定义
NodeDemoProvider demoService = (NodeDemoProvider) context.getBean("demoProvider"); // 获取远程服务代理 String hello = demoService.sayHello("world"); // 执行远程方法 hello = 'Hello world' 复制代码