npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

kigo-dubbo2-client

v1.0.0

Published

node dubbo client

Downloads

2

Readme

@melot/dubbo-client

dubbo 客户端

Log4js category:

Dubbo

Install with:

$ cnpm install @melot/dubbo-client

Usage

package com.melot.dubbo.service;

import com.melot.dubbo.entry.User;
import org.apache.dubbo.config.annotation.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HelloServiceImpl implements HelloService {
    static Logger logger = LoggerFactory.getLogger(HelloServiceImpl.class);

    public String hello(String name) {
        return "hello " + name;
    }

}

假设有这么一个 dubbo 接口, 我们如何使用 dubbo-client 对其进行 rpc 调用呢

编写相对应的 Service

'use strict'

const util = require('util');

const dubbo = require('@melot/dubbo-client');

const java = dubbo.java;
const Service = dubbo.Service;

// Service 函数签名参数必须是 dubbo application 对象
/**
 * @param {Dubbo} [cxt] dubbo 对象
 */
function HelloService(app) {
  Service.call(this, app);
  // 注册到 nacos 的服务名称
  this.serviceName = 'provider-service';
  // 服务接口名
  this.interfaceName = 'com.melot.dubbo.service.HelloService';
  // 服务版本
  this.version = '1.0.0';
}

// 继承自 dubbo 的 Service
util.inherits(HelloService, Service);

module.exports = HelloService;

HelloService.prototype.hello = function(name, cb) {
  const methodName = 'hello';
  const args = [name];
  // 没有 return 的话不支持 async/await 调用
  return this.invoke(methodName, args, cb);
}

注册到 dubbo application

'use strict'

const dubbo = require('@melot/dubbo-client');

const Application = dubbo.Dubbo;
const java = dubbo.java;

const app = new Application({
  // 应用名称
  name: 'dubbo-js',
  // dubbo 版本
  version: '2.0.2',
  // 注册中心配置
  register: {
    protocol: 'nacos',
    serverList: '127.0.0.1:8848',
    namespace: 'public'
  }
})

// 假设我们编写的 HelloService 放在 service/ 目录下
// 注册到 dubbo 容器
const HelloService = require('./service/HelloService');
app.registerService(HelloService);

// 从 dubbo 容器中获取 service 对象
// 默认名称为 service 名称首字母小写, 也可以在 Service 中显示声明
const helloService = app.getService('helloService');

// callback 方式调用
helloService.hello('world', function(err, res) {

});

// async/await 方式调用
(async function() {
  let res = null;
  try {
    res = await helloService.hello('world');
  } catch(e) {

  }
})()

泛化调用

'use strict'

const dubbo = require('@melot/dubbo-client');

const Application = dubbo.Dubbo;

const app = new Application({
  // 应用名称
  name: 'dubbo-js',
  // dubbo 版本
  version: '2.0.2',
  // 注册中心配置
  register: {
    protocol: 'nacos',
    serverList: '127.0.0.1:8848',
    namespace: 'public'
  }
})

app.$invoke({
  serviceName: 'provider-service',
  interfaceName: 'com.melot.dubbo.service.HelloService',
  version: '1.0.0',
  methodName: 'hello',
  args: ['world'],
}, function(err, res) {

})

(async function main() {
  let res = null;
  try {
    res = await app.$invoke({
      serviceName: 'provider-service',
      interfaceName: 'com.melot.dubbo.service.HelloService',
      version: '1.0.0',
      methodName: 'hello',
      args: ['world'],
    })
  } catch(e) {

  }
})()

配置

负载均衡

缺省是随机 random, 可配置

  • random 加权随机
  • roundrobin 轮询
  • weightroundrobin 加权轮询
  • leastactive 最不活跃优先
  • consistenthash 一致性哈希

接口级别配置

app.configure('com.melot.dubbo.service.HelloService', 'loadbalance', 'roundrobin');

方法级别配置

app.configure('com.melot.dubbo.service.HelloService', 'hello', 'loadbalance', 'roundrobin');

超时

缺省请求超时时间为 5s

接口级别配置

app.configure('com.melot.dubbo.service.HelloService', 'timeout', 3000);

方法级别配置

app.configure('com.melot.dubbo.service.HelloService', 'hello', 'timeout', 3000);

服务治理(只支持方法级别)

缓存

app.configure('com.melot.dubbo.service.HelloService', 'hello', 'cache', {
  capacity: 500, // 容量
  ttl: 60000 // 缓存时间
});

降级

app.configure('com.melot.dubbo.service.HelloService', 'hello', 'degrader', true);

熔断器

app.configure('com.melot.dubbo.service.HelloService', 'hello', 'circuitbreaker', {
  failWindowTime: 60000, // 滑动窗口时间
  requestVolumeThreshold: 10, // 滑动窗口时间内的请求数阈值
  failThresholdPercentage: 60, // 失败率阈值
  sleepWindowTime: 5000 // 自动恢复时间间隔
});

直连提供者(服务级别配置)

为了避免复杂化线上环境,不要在线上使用这个功能,只应在测试阶段使用

app.setUrl('provider-service', 'dubbo://127.0.0.1:3050');

app.setUrl('provider-service', {
  host: '127.0.0.1',
  port: 3050
});

Filter

过滤器有前置和后置过滤器, 前置后置是相对于内置的过滤器, 而不是请求, 请求永远在最后执行。

内置过滤器依次为缓存过滤器, 降级过滤器, 熔断过滤器

过滤器函数签名为

async function(app, rpcRequest, next) {

}

过滤器必须返回 await next() 的结果

前置过滤器

app.before(async function(app, rpcRequest, next) {
  const start = Date.now();
  const res = await next();
  console.log(`do ${rpcRequest.getDubboInterface()}.${rpcRequest.getMethodName()} use ${Date.now() - start}`);
  return res;
})

后置过滤器

app.after(async function(app, rpcRequest, next) {
  if (Math.random() > 0.5) {
    throw new Error('server error');
  }
  return await next();
})

APIs

  • new Dubbo(opts)
    • opts {Object}
      • [name] {String} application name, default is dubbo-node
      • version {String} dubbo version
      • [naming] {NamingClient} registry naming client
      • [register] {Object}
        • [protocol] {String} register protocol, default is nacos
        • [namespace] {String} 命名空间 default is public
        • serverList {String|Array} server list, if type is string, split by ','
      • [timeout] {Number} rpc request timeout, default is 5000
      • [retryMax] {Number} socket retry max, default is 20
      • [retryDelay] {Number} socket retry delay, default is 1000
      • [retryDelayMax] {Number} socket retry delay max, default is 60000
      • [heartInterval] {Number} socket heart interval, default is 60000
  • registryService(Service) 注册服务
    • Service {Dubbo.Service}
  • registerServiceByPath(path) 递归注册目录下所有 service
    • path {String} 全路径
  • getService(name) 获取服务对象
    • name {String} 默认类名首字母小写
  • configure(interfaceName, [methodName], key, value) 配置
    • interfaceName
    • [methodName]
    • key
    • value
  • setUrl(serviceName, url) 配置直连模式
    • serviceName {String}
    • url {String|Object} if type is string, pattern is 'dubbo://host:port'
      • host {String}
      • port {Number}
  • before(filter) 添加前置过滤器
    • filter [Function|Array]
  • after(filter) 添加后置过滤器
    • filter [Function|Array]