第1.3章 node调用dubbo

node-zookeeper-dubbo,执行下面的命令安装,我使用的是dubbox,需要修改一下源码:

npm install node-zookeeper-dubbo --save

1 修改后node-zookeeper-dubbo/libs/encode.js

/**
 * Created by panzhichao on 16/8/18.
 */
'use strict';
const Encoder     = require('hessian.js').EncoderV2;
const DEFAULT_LEN  = 8388608; // 8 * 1024 * 1024 default body max length

function Encode(opt) {
  this._opt = opt;
  const body = this._body(opt._method, opt._args);
  
  const head = this._head(body.length);
  
  return Buffer.concat([head, body]);
}

Encode.prototype._head = function (len) {
  const head = [0xda, 0xbb, 0xc2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
  let i    = 15;
  if (len > DEFAULT_LEN) {
    throw new Error(`Data length too large: ${len}, max payload: ${DEFAULT_LEN}`);
  }
  while (len >= 256) {
    head.splice(i--, 1, len % 256);
    len >>= 8;
  }
  head.splice(i, 1, len);
  return new Buffer(head);
}

Encode.prototype._body = function (method, args) {
  const body = new Encoder();
  body.write(this._opt._dver || '2.5.3.6');
  body.write(this._opt._interface);
  body.write(this._opt._version);
  body.write(this._opt._method);
  // add by dzm at 2017-01-13
  if (args && args.length) {
    body.write(args.length);
  } else{
    body.write(0);
  }
  // 
  // body.write(this._argsType(args)); note by dengzm at 2017-01-16
  
  // end 
  if (args && args.length) {
    for (var i = 0, len = args.length; i < len; ++i) {
      body.write(args[i]);
    }
  }
  // edit by dzm at 2017-01-13 调整attachments的位置到
  body.write(this._attachments());
  
  return body.byteBuffer._bytes.slice(0, body.byteBuffer._offset);
}

Encode.prototype._argsType = function (args) {
  if (!(args && args.length)) {
    return '';
  }

  const typeRef = {
    boolean: 'Z', int: 'I', short: 'S',
    long   : 'J', double: 'D', float: 'F'
  };

  let parameterTypes = '';
  let type;
  for (var i = 0, l = args.length; i < l; i++) {
    type = args[i]['$class'];
    parameterTypes += type && ~type.indexOf('.')
        ? 'L' + type.replace(/\./gi, '/') + ';'
        : typeRef[type];

    // note by dzm at 2017-01-12
    // if (type.charAt(0) === '[') {
    //   parameterTypes += '[L' + type.slice(1).replace(/\./gi, '/') + ';';
    // } else {
    //   parameterTypes += type && ~type.indexOf('.')
    //     ? 'L' + type.replace(/\./gi, '/') + ';'
    //     : typeRef[type];
    // }
  }
  console.log('parameterTypes is ' + JSON.stringify(parameterTypes));

  return parameterTypes;
}

Encode.prototype._attachments = function () {
  const implicitArgs = {interface: this._opt._interface, path: this._opt._interface, timeout: this._opt._timeout}
  this._opt._version && (implicitArgs.version = this._opt._version)
  this._opt._group && (implicitArgs.group = this._opt._group);

  return {
    $class: 'java.util.HashMap',
    $     : implicitArgs
  }
}

exports.Encode = Encode;

2 更改node-zookeeper-dubbo/libs/register.js

/**
 * Created by panzhichao on 16/6/30.
 */
'use strict';

const url = require('url');
const os  = require('os');

const CREATE_MODES = {
  /**
   * The znode will not be automatically deleted upon client's disconnect.
   */
  PERSISTENT: 0,

  /**
   * The znode will not be automatically deleted upon client's disconnect,
   * and its name will be appended with a monotonically increasing number.
   */
  PERSISTENT_SEQUENTIAL: 2,

  /**
   * The znode will be deleted upon the client's disconnect.
   */
  EPHEMERAL: 1,

  /**
   * The znode will be deleted upon the client's disconnect, and its name
   * will be appended with a monotonically increasing number.
   */
  EPHEMERAL_SEQUENTIAL: 3
};

function isLoopback(addr) {
  return /^(::f{4}:)?127\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/
      .test(addr) ||
    /^fe80::1$/.test(addr) ||
    /^::1$/.test(addr) ||
    /^::$/.test(addr);
}

function ip() {
  const interfaces = os.networkInterfaces();
  return Object.keys(interfaces).map(function (nic) {
    const addresses = interfaces[nic].filter(function (details) {
      return details.family.toLowerCase() === 'ipv4' && !isLoopback(details.address);
    });
    return addresses.length ? addresses[0].address : undefined;
  }).filter(Boolean)[0];
}

function consumer() {
  const self  = this;
  const paths = [];
  const host  = ip();

  const dependencies = self.dependencies;
  let serv; //临时存储服务

  const info = {
    protocol: 'consumer',
    slashes : 'true',
    host    : '',
    query   : {
      application: self.application.name,
      category   : 'consumers',
      check      : 'false',
      dubbo      : self.dubboVer,
      interface  : '',
      revision   : '',
      version    : '',
      side       : 'consumer',
      timestamp  : (new Date()).getTime()
    }
  };

  for (const s in dependencies) {
    if (dependencies.hasOwnProperty(s)) {
      serv = dependencies[s];
    }
    info.host = `${host}/${serv.interface}`;

    info.query.interface = serv.interface;
    info.query.revision  = serv.version;
    info.query.version   = serv.version;
    // edit by dzm at 2017-01-17 解决dubbox注册的问题
    if (serv.group){
      info.query.group     = serv.group;
    }
    // end edit
    paths.push(`/${self._root}/${serv.interface}/consumers/${encodeURIComponent(url.format(info))}`);
  }

  for (let i = 0, l = paths.length; i < l; i++) {
    (function (path) {
      self.client.exists(path, function (err, stat) {
        if (err) {
          console.log(err.stack);
          return;
        }

        if (stat) {
          console.log('Node exists.');
          return;
        }
        self.client.create(path, CREATE_MODES.EPHEMERAL, function (err, node) {
          if (err) {
            console.error('Reg consumer failed:' + err.stack);
          }
        });
      });
    })(paths[i]);
  }
}

exports.consumer = consumer;

3 node调用代码示例
我采用的是express框架,所以下面的代码只是我路由代码,其他的不用改。

var express = require('express');
var router = express.Router();
const nzd=require('node-zookeeper-dubbo');


const opt={
  application:{name:'wcnapi'},
  // register:'192.168.5.128:2181,192.168.5.128:2182,192.168.5.128:2183',
  register:'192.168.5.172:2181,192.168.5.173:2181',
  dubboVer:'2.8.4',
  root:'dubbo',
  dependencies:{
    WcnService:{interface:'com.test.wcn.api.service.WcnService',version:'1.0.0',timeout:6000}
  }  
}

const Dubbo = new nzd(opt);


// const Dubbo=new nzd(opt);
/* 微信系统接口 */
router.get('/getLoginQrcode', function(req, res, next) {
  var arg1={$class:'java.lang.String',$:'1300000067'};
  Dubbo.WcnService.getLoginQrcode(arg1).then(function(data){
    res.send(data);
  }).catch(function(err){
    res.send(err);
  })
});

router.get('/test/1', function(req, res, next) {
  var arg1={$class:'java.lang.String',$:'1300000067'};
  var arg2={$class:'java.lang.Integer',$:1};
  var arg3={$class:'java.lang.Integer',$:10};
  Dubbo.WcnService.testApi(arg1,arg2,arg3).then(function(data){
    res.send(data);
  }).catch(function(err){
    res.send(err);
  })
});

router.get('/test03', function(req, res, next) {
  var arg = {
  	$class:'com.test.wcn.dto.TestDto',
  	$:{
  		id:{$class:'java.lang.String',$:'0101'},
  		name:{$class:'java.lang.String',$:'0101'},
  		age:{$class:'java.lang.Integer',$:10},
  		sex:{$class:'java.lang.Boolean',$:true}
  	}
  }
  Dubbo.WcnService.test03(arg).then(function(data){
    res.send(data);
  }).catch(function(err){
    res.send(err);
  })
});

module.exports = router;

4 应用到实际生产环境的用法
上面只是一个基本的用法,但是如果实际投产还是要设计一下;
第一步 express路由分离
app.js中的代码

var routes = require('./routes/routes');
var app = express();
routes(app);

routes.js的代码

// dubbo接口配置
const nzd=require('node-zookeeper-dubbo');
var config = require('../libs/config');
const opt={
  application:config.dubbo.application,
  register:config.dubbo.register,
  dubboVer:config.dubbo.dubboVer,
  root:config.dubbo.root,
  dependencies:{
    CmsService:{interface:'com.test.cms.api.service.CmsService',version:'1.0.0',timeout:6000},
    WcnService:{interface:'com.test.wcn.api.service.WcnService',version:'1.0.0',timeout:6000}
  }  
}
const Dubbo = new nzd(opt);
// 
var infoRoutes = require('./page/infoRoutes');
var indexRoutes = require('./page/indexRoutes');
var dubbo = require('./dubbo');
module.exports = function(app){
	dubbo(app,Dubbo);
	// 首页
	indexRoutes(app);
}

第二步 引入dubbo的接口

// 内容管理接口系统
var cms = require('./dubbo/cms');
// 微信接口系统
var wcn = require('./dubbo/wcn');
// // 
module.exports = function(app,Dubbo){
	cms(app,Dubbo);
	wcn(app,Dubbo);
	
}

第三步 dubbo接口的通用设计
下面定义的cms.js,同时支持http服务以及dubbo服务。既可以对外调用,又可以对内。

let dubbox;
function _queryArticleList(columnId,page,rows, callback){
  dubbox.CmsService.queryArticleList(columnId,page,rows).then(function(data){
      let resp = {success:true,msg:''};
      resp.data = data;
      callback(resp);
    }).catch(function(err){
      let resp = {success:false,msg:err};
      callback(resp);
    })
}

function _queryContent(articleId,callback){
  dubbox.CmsService.queryContent(articleId).then(function(data){
    let resp = {success:true,msg:''};
    resp.data = data;
    callback(resp);
  }).catch(function(err){
    let resp = {success:false,msg:err};
    callback(resp);
  })
}
/*输出区域*/
module.exports = function(app,Dubbo){
  dubbox = Dubbo;
  // 获取文章列表
  app.get('/cms/queryArticleList', function(req, res, next) {
    let columnId={$class:'java.lang.String',$:req.query.columnId};
    let page={$class:'java.lang.Integer',$:parseInt(req.query.page)};
    let rows={$class:'java.lang.Integer',$:parseInt(req.query.rows)};
    _queryArticleList(columnId,page,rows,function(resp){
      res.send(resp);
    })
  });

  app.get('/cms/queryContent', function(req, res, next) {
    let articleId={$class:'java.lang.String',$:req.query.articleId};
    _queryContent(articleId,function(resp){
      res.send(resp);
    })
  });
  
}
module.exports.queryArticleList = _queryArticleList;
module.exports.queryContent = _queryContent;

你可能感兴趣的:(node)