nodejs基于RabbitMq的RPC调用

在微服务架构中,SpringCloud,Eureka,Dubbo,ZooKeeper这些框架再熟悉不过了,其中面向接口的远程方法调用是其主要核心功能之一,而MQ主要用来应用解耦,削峰填谷等作用;最近在RabbitMq官网上看到,竟然还支持RPC调用,处于好奇,动手用js跑了一遍。

共三个文件:RpcUtil.js, server.js,client.js

client.js

const { RpcUtil } = require('./rpcUtil');

const rpcUtil = new RpcUtil(userName, password, host, port);
rpcUtil.init().then(() => {
    setInterval(() => {
        for (let i = 0; i < 100; i++) {
            rpcUtil.sendMsg(rpcUtil.generateUuid(), {
                method,
                params,
            }, result => {
            	console.log(i + '<<>>' + JSON.stringify(result))
            });
        }
    }, 3000);
}).catch(e => console.log(e));

server.js

class DealerMsgRpcUtil extends RpcUtil {
    // @Override
    async dealerMsg(msgContent) {
        msgContent = JSON.parse(msgContent);
        const { method, params } = msgContent;
        let result;
        try {
        	// 这里调用各种方法
            if (method === 'listMember') {
            	result = await foo(params);
            } else {
                result = { code: -1, msg: '找不到对应方法' };
            }
        } catch (e) {
            result = { code: -1, msg: e.message };
        }

        return result;
    }
}

const rpcUtil = new DealerMsgRpcUtil(rabbitMQAccount, rabbitMQPassword, proxy_host, port);
rpcUtil.init().then(() => {
    rpcUtil.listenMsg();
}).catch(e => LOG(e));

RpcUtil.js

const amqp = require('amqplib/callback_api');

class RpcUtil {
    constructor(rabbitMQAccount, rabbitMQPassword, rabbitMQHost, rabbitMQPort) {
        this.connection;
        this.channel;
        this.rpcQueueServer = 'rpc_queue_server';
        this.rpcQueueClient = 'rpc_queue_client';
        this.correlationIdPool = new Map();
        this.amqpUrl = 'amqp://' + rabbitMQAccount + ':' + rabbitMQPassword + '@' + rabbitMQHost + ':' + rabbitMQPort;
    }

	// 创建通道
    async _createChannel() {
        this.channel = await new Promise(resolve => {
            this.connection.createChannel((err, channel) => {
                resolve(channel);
            });
        });
    }

	// 发送端生成correlationId
    generateUuid() {
        return Math.random().toString() +
            Math.random().toString() +
            Math.random().toString();
    }

	// 初始化
    async init() {
        await new Promise((resolve, reject) => {
            amqp.connect(this.amqpUrl, (error, conn) => {
                if (error) {
                    reject(error);
                } else {
                    this.connection = conn;
                    resolve();
                }
            });
        });
        await this._createChannel();
    }
    
	// 被调用端,子类需要重写
    async dealerMsg(msgContent) {
        msgContent = JSON.parse(msgContent);
        return { code: 200, msg: '', data: msgContent };
    }

    // 被调用端监听消息
    async listenMsg() {
        this.channel.assertQueue(this.rpcQueueServer, { durable: false });
        this.channel.prefetch(1);

        this.channel.consume(this.rpcQueueServer, async msg => {
            const msgContent = msg.content.toString();

            let dealerResult;
            try {
                dealerResult = await this.dealerMsg(msgContent);
            } catch (e) {
                dealerResult = { code: -1, msg: e.message };
            }
            this.channel.sendToQueue(msg.properties.replyTo, Buffer.from(JSON.stringify(dealerResult)), {
                correlationId: msg.properties.correlationId,
            });
        }, { noAck: true });
    }
    
    // 调用端发送消息
    async sendMsg(correlationId, params, cb) {
        const q = await new Promise(resolve => {
            this.channel.assertQueue(this.rpcQueueClient, { exclusive: true }, (e, q) => {
                resolve(q);
            });
        });
        this.correlationIdPool.set(correlationId, cb);
        this.channel.consume(q.queue, msg => {
            if (this.correlationIdPool.has(msg.properties.correlationId)) {
                const cb = this.correlationIdPool.get(msg.properties.correlationId);
                cb(msg.content.toString());
                this.correlationIdPool.delete(msg.properties.correlationId);
            }
        }, { noAck: true });

        this.channel.sendToQueue(this.rpcQueueServer, Buffer.from(JSON.stringify(params)), {
            correlationId,
            replyTo: q.queue,
        });
    }
}

exports.RpcUtil = RpcUtil;

以上代码仅学习用,生产环境不建议mq去实现rpc。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值