Node.js通過Dubbo2.js呼叫Java

Kalengo發表於2019-04-02

1. Dubbo 是啥?

Dubbo 是一個由阿里開源的 RPC 框架。

簡單說下RPC框架的背景。

From dubbo.apache.org

Dubbo 是一種 RPC 框架,應用在分散式服務。

Node.js通過Dubbo2.js呼叫Java

2. 使用 Dubbo 實現 Java 互調

​ 首先我們可以先嚐試下同語言下的 Dubbo 呼叫,從容易開始。

​ 可以參考下 dubbo 官方文件 dubbo.apache.org/zh-cn/docs/…

​ 這邊簡單嘗試下,主要有兩步:

  1. 首先建立一個服務提供方, 也就是上圖 Provider 的角色;

  2. 接下來建立一個服務消費者, 也如同上圖的 Consumer 的角色;

服務提供方建立 Provider

1.0 使用Spring Boot 建立一個Spring 微服務 (可以參考)yuchenzhen.github.io/2018/08/24/…

**1.1. 建立一個 Interface **

// TestProviderService.java

package com.dubbo.learn.dubbo;

public interface TestProviderService {
    String Hello (String who);
}
複製程式碼

1.2 實現這個TestProviderServiceImpl

// TestProviderServiceImpl
package com.dubbo.learn.dubbo.impl;

import com.dubbo.learn.dubbo.TestProviderService;
import com.alibaba.dubbo.config.annotation.Service;

@Service(version="1.0.0")
public class TestProviderServiceImpl implements TestProviderService  {
    public String Hello(String who) {
        return "Hello world ! Dear Programer " + who ;
    }
}

複製程式碼

1.3 啟動程式主入口新增@EnableDubbo註解

// ProviderApplication.java
package com.dubbo.learn;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo;

@SpringBootApplication
@EnableDubbo
public class ProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }

}	
複製程式碼

​ 為了引入這個@EnableDubbo註解,需要我們引入com.alibaba的包

<!--pom.xml-->
<dependency>
  <groupId>com.alibaba.boot</groupId>
  <artifactId>dubbo-spring-boot-starter</artifactId> 
  <version>0.2.1.RELEASE</version>
</dependency>
<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>dubbo</artifactId>
  <version>2.6.5</version>
</dependency>
<dependency>
  <groupId>org.apache.curator</groupId>
  <artifactId>curator-framework</artifactId>
  <version>2.11.1</version>
</dependency>
複製程式碼

curator-framework是dubbo所使用的訊息中心Zookeeper所需要的包
dubbo-spring-boot-starter是 dubbo spring 的配置包

1.4 最後我們把dubbo 的啟動配置寫到application.properties裡面

# application.properties
server.port = 8829
#
dubbo.application.name=provider
dubbo.registry.protocol=zookeeper
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.scan.base-packages=com.dubboo.learn
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
dubbo.consumer.check=false
複製程式碼

整個專案結構如圖:

Node.js通過Dubbo2.js呼叫Java

然後,啟動就好。

啟動之後,通過 dubbo Admin 網頁客戶端可以看見Provider的介面在 Regitry 裡面註冊成功。

Node.js通過Dubbo2.js呼叫Java

服務消費者Consumer

1.0 使用Spring Boot 建立一個Spring 消費者的微服務

1.1 定義介面,這裡的介面路徑位置和包名最好一致 (不然要自己調整)

// TestProviderService.java
package com.dubbo.learn.dubbo;
public interface TestProviderService {
    String Hello (String who);
}
複製程式碼

1.2 定義一個 Service呼叫該dubbo 介面

// TestConsumerService.java
package com.dubbo.learn;

import com.alibaba.dubbo.config.annotation.Reference;
import com.dubbo.learn.dubbo.TestProviderService;
import org.springframework.stereotype.Component;

@Component
public class TestConsumerService {
    @Reference(version = "1.0.0")
    TestProviderService testProviderService;

    public void consumer (String who) {
        String res = testProviderService.Hello(who);
        System.out.println("consumer : provider says " + res);
    }
}
複製程式碼

在主程式函式呼叫該Service 的函式

// DubboConsumerApplication.java
package com.dubbo.learn;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import com.dubbo.learn.TestConsumerService;

@SpringBootApplication
public class DubboConsumerApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(DubboConsumerApplication.class, args);
        TestConsumerService testConsumer = run.getBean(TestConsumerService.class);
        testConsumer.consumer("White");
    }

}
複製程式碼

@Reference這個註解就是用來呼叫 dubbo 對應的介面的。所以也是要引入跟服務端的那幾個包

<!--pom.xml-->
<dependency>
  <groupId>com.alibaba.boot</groupId>
  <artifactId>dubbo-spring-boot-starter</artifactId> 
  <version>0.2.1.RELEASE</version>
</dependency>
<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>dubbo</artifactId>
  <version>2.6.5</version>
</dependency>
<dependency>
  <groupId>org.apache.curator</groupId>
  <artifactId>curator-framework</artifactId>
  <version>2.11.1</version>
</dependency>  
複製程式碼

1.3 最後我們把dubbo 的啟動配置寫到application.properties裡面

#application.properties
server.port=8830
dubbo.application.name=consumer
#註冊中心地址
dubbo.registry.address=zookeeper://127.0.0.1:2181

dubbo.scan.base-packages=com.dubboo.learn.dubbo
dubbo.protocol.port=20880
複製程式碼

專案目錄結構如下:

Node.js通過Dubbo2.js呼叫Java

啟動後效果如下:

Node.js通過Dubbo2.js呼叫Java

3. Node.js 如何通過 Dubbo 呼叫 Java

Node 這邊通過 dubbo呼叫 Java 的 provider 的介面,我們嘗試呼叫了幾個包:sofa-rpc-node,node-zookeeper-dubbo,和dubbo2.js 。
其中 sofa-rpc-node 的對使用 egg.js框架的比較友好,node-zookeeper-dubbo 使用起來跟 sofa-rpc-node 差不多;但是有點麻煩的就是這兩個包都需要寫 proto3的介面定義。
而 dubbo2.js則比較方便,以下是使用 dubbo2.js 的示列

const { Dubbo, java, setting } = require('dubbo2.js')
const interfaceName = 'com.dubbo.learn.dubbo.TestProviderService'
const interfaceVersion = '1.0.0'
const dubboSetting = setting.match(
  interfaceName, { version: interfaceVersion }
)
const dubboService = dubbo => dubbo.proxyService({
  dubboInterface: interfaceName,
  version: '1.0.0',
  methods: {
    Hello (who) {
      return [
        java.String(who)
      ]
    }
  }
})
const service = {dubboService}
// 例項化Dubbo, 入參主要是名稱和 dubbo 介面的設定
const dubbo = new Dubbo({
  application: {name: 'dubbo-node-test'},
  register: '127.0.0.1:2181',
  dubboSetting,
  service
})

module.exports = dubbo

複製程式碼

程式碼就是這麼簡單, 把 Java 服務裡面通過 dubbo 提供出來的介面(包括介面名,介面版本資訊,介面方法) 註冊一下。
得到Dubbo 例項之後,呼叫對應的 service就可以使用。
如下:

await dubbo.service.dubboService.Hello(who)
複製程式碼

我們簡單寫了一個介面:

const KoaRouter = require('koa-router')
const dubbo = require('./dubbo')
const router = new KoaRouter({prefix: '/api/v1'})

router.use('/')

router.get('/testNodeDubbo', async (ctx, next) => {
  console.info(`[testNodeDubbo]:==:> start`)
  let {who} = ctx.request.query
  const res = await dubbo.service.dubboService.Hello(who)
  ctx.body = res
})

module.exports = router

複製程式碼

呼叫結果:

Node.js通過Dubbo2.js呼叫Java

這樣就完成了 node 作為消費者通過 dubbo 去呼叫 java 的介面了。

4. Node.js 通過介面呼叫 Java 與 通過 Dubbo 呼叫 Java 的對比

Node.js通過Dubbo2.js呼叫Java

這邊嘗試使用了呼叫了同樣邏輯的 dubbo 和 http 介面, 對比了一下兩個實現的返回時間。
其中紅色的是 dubbo 介面, 藍色的是 http 介面。

其他:

專案地址:
github.com/yuchenzhen/…
github.com/yuchenzhen/…
github.com/yuchenzhen/…

相關文章