node通过dubbo2.js调用java dubbo服务(rpc)

3,694 阅读3分钟

本文简单介绍dubbo,rpc是什么,在egg.js中使用dubbo2.js以及dubbo与zk交互流程。 开源项目dubbo2.js的github地址:github.com/apache/dubb…

1. dubbo是什么

随着网站规模的增大,系统发展一般会经历单一应用架构、垂直应用架构、分布式服务架构。随着垂直应用越来越多,应用之间的交互不可避免,将核心业务抽取出来作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。在分部署服务架构中如何处理微服务之间的通信以及提高业务的复用及整合是关键。在此情况下需要一个分布式服务框架(RPC)来应对这个问题。dubbo就是众多优秀的开源RPC框架之一。

2. 什么是RPC(片面理解)

Remote Procedure Call 远程过程(方法)调用

http调用:将后端资源发布成URI,前端通过URI去访问资源

RPC调用:向调用本地函数一样去使用远程的函数或方法。两台服务器,computer1、computer2;一个应用部署在computer1服务器上,想要调用computer2服务器上应用提供的函数或者方法;由于不在一个内存空间无法直接调用,这个时候就需要RPC框架来解决。可以通过http来实现,也可以通过socket自己实现一套协议来实现

dubbo本身是一个java分布式RPC框架,那我们在使用node作为消费者去调用dubbo服务时,就需要有一套机制能支持我们去跨语言进行dubbo RPC调用,dubbo2.js就是为了解决这个问题。

dubbo2.js实现原理本文暂不描述

3. dubbo2.js使用

dubbo2.js使用方式可以按照自己的需求进行封装,以下是在egg.js使用方式。还可以将dubbo.js写成egg插件的方式进行使用。

1. 接口方法映射信息

'use strict';
const java = require('js-to-java');
function HelloService(dubbo) {
  return dubbo.proxyService({
    dubboInterface:
      'com.linge.service.HelloService',
    timeout: 10,
    group: 'hello_app',
    methods: {
      sayHello(obj) {
        return [
          {
            $class: 'com.linge.service.req.HelloReqDTO',
            $: {
              name: java.Long(obj.name),
              age: java.Integer(obj.age),
              // ......
            },
          },
        ];
      },
    },
  });
}

2. 接口配置文件

// app/dubbo_interface/index.js
'use strict';
const { setting } = require('dubbo2.js');
const helloSrv = require('./helloSrv');
module.exports.service = {
  helloSrv,
};
module.exports.dubboSetting = setting
  .match(
    [
      'com.linge.HelloService', 
    ],
    { version: undefined }
  )

3. dubbo配置信息

 config.dubbo = {
    application: { name: 'bone' },
    register: '192.168.1.12:2181', // test环境的dubbo服务接口地址
    dubboVersion: '2.10.0x',
    root: 'dubbo',
    environment: 'test',
  };

4. dubbo初始化

service,dubboSetting,config信息

const { Dubbo } = require('dubbo2.js');
const { service, dubboSetting } = require('./app/dubbo_interface');
class AppBootHook {
    constructor(app) {
      this.app = app;
    }
    async didReady() {
      const opt = { dubboSetting, service };
      Object.assign(opt, this.app.config.dubbo);
      this.app.dubbo = new Dubbo(opt);
    }
}

4. zookeeper与dubbo2.js如何协同工作

1.zk的使用

1.mac安装zk

brew install zookeeper

2.启动zk

cd /usr/local/Cellar/zookeeper/3.4.13/bin

./zkServer start

3.连接连接测试环境ZK地址

cd /usr/bin
zkCli -server 192.168.1.12:2181

4.相关查看命令

ls  /dubbo
 
 // 列举出当前dubbo目录下所注册的服务
 // [com.linge.service.HelloService, com.linge.service.HelloService2]
 
ls /dubbo/com.linge.service.HelloService
 
 //选择某一个服务进行查看
 // [consumers, routers, providers, configurators]
 
ls /dubbo/com.linge.service.HelloService/providers
 
 // [dubbo://192.168.1.12:30881/com.linge.service.HelloService?anyhost=true&application=linge-main&default.group=hello&dubbo=2.8.4x&environment=test&generic=false&group=hello_app&interface=com.linge.service.HelloService&methods=sayHello&organization=dubbox&owner=programmer,wanghaidong01&pid=11561&retries=0&revision=1.1.3-SNAPSHOT&side=provider&timeout=10000&timestamp=1598720543276]

2.dubbo在zk中是符合保存的

3.dubbo与zk的交互流程

  1. 微服务启动时向注册中心(zk的providers目录下)注册自己能提供的服务
  2. 客户端(消费者)启动时,会去向zk订阅自己需要的服务信息,并将自己的信息写入到zk的consumers目录下。
  3. zk向客户端(消费者)返回对应的服务信息(服务地址,接口名称,配置等...)
  4. 客户端(消费者)拿到了服务相关信息,发起rpc调用

5. dubbo2.js使用中常见问题

1.zk get DubboSericeUrls result is empty with service path xxx

服务端没有将xxx服务注册到zk中,检查服务端xxx服务是否发布成功,发布环境是否正确

2.Could not find any agent worker with xxx

类似http接口的404,前端(消费者)配置使用的服务信息,与服务端提供的是否一致。检查环境,group,接口等,检查服务端xxx服务是否发布成功。

3.Fail to decode request due to

接口参数问题,参数名称不一致或参数类型不一致 1.检查自己的问题:结合接口文档及实际代码对照接口参数名称及类型是否正确 2.后端同学核对接口参数是否正确