如何在 Feathers 应用程序中跨挂钩/服务为 amqplib 包装器设置持久连接
How to set up a persistent connection for an amqplib wrapper across hooks / services in Feathers app
我正在使用 Feathers 编写一些微服务。 Feathers(和一般的 Node)的新手,运行 遇到了问题。
为了在微服务(即一堆独立的 Feathers 应用程序)之间进行通信,我将使用 RabbitMQ(一个 AMQP 消息代理)。调用某些服务方法后,我想通过 AMQP 发布一条消息。同样,我希望应用程序订阅代理上的交换并在收到特定消息时调用服务方法。
因为我有十几个微服务,所以我决定编写一个库来处理诸如强制执行主题结构和进行重新连接等事情。该库主要是 amqplib 的包装器。我知道有一些开放源代码的羽毛 amqp 模块四处漂浮,但 none 它们完全符合我的要求。
该库有一个 connect() 方法、publish() 方法和一个 subscribe() 方法。 connect() 方法接受一个 url,连接到代理,并将连接对象存储在模块变量中。
计划将 publish() 方法注册为每个相关服务中的挂钩。例如,如果我有一个名为 foo 的服务,它可能有一个 foo.hooks.js:
module.exports = {
before: {
all: [],
find: [],
get: [],
create: [amqpWrapper.publish()],
update: [amqpWrapper.publish()],
patch: [amqpWrapper.publish()],
remove: [amqpWrapper.publish()]
}
//etc
};
其中 publish() 方法正在获取上下文对象,提取它需要的信息,然后通过 amqp 将其丢弃。
还有一个foo.service.js:
// Initializes the `crunch` service on path `/foo`
const createService = require('feathers-nedb');
const createModel = require('../../models/crunch.model');
const hooks = require('./crunch.hooks');
module.exports = function (app) {
const Model = createModel(app);
const paginate = app.get('paginate');
const options = {
Model,
paginate
};
// Initialize our service with any options it requires
app.use('/foo', createService(options));
// Get our initialized service so that we can register hooks
const service = app.service('foo');
service.hooks(hooks);
};
我可能有一个名为 bar 的非常相似的服务,它也在其挂钩中发布。
问题在于您应该为每个进程只维护一个到 rabbitmq 的连接。打开和关闭连接很慢,所以理想情况下,我只想在应用程序启动时调用一次 connect() 方法,并让它持续存在并可从我所有不同的服务全局访问。
我当然可以
const amqpWrapper = require('amqpWrapper')
在所有 [service].hooks.js 文件中,以及在顶层 index.js 中,我也会调用 connectMethod(),但这似乎不正确大部头书。 Javascript 并没有真正的单例,虽然它为 require() 使用缓存,但不能保证。
那么,在 Feathers 中导入具有可随处访问的持久连接的模块的正确方法是什么?我能以某种方式将它存储在 'app' 对象中吗?
编辑
听从了 Daff 的建议,这很有效,但只是想扩展完整的解决方案:
由于我的 amqpWrapper() returns 库的 module.exports,我使用 app.set('amqp', amqpWrapper.connect())
在 /src/app.js 中保存连接,然后在我的 foo.hooks.js, 我就是这样:
module.exports = {
after: {
all: [],
find: [],
get: [],
create: [context => {context.app.get('amqp').publish();}],
update: [],
patch: [],
remove: []
},
//etc
};
这就是app.get and app.set的用途。在 src/app.js
:
const amqpWrapper = require('amqpWrapper')
const connection = amqpWrapper.connect();
app.set('amqp', connection);
现在,您可以访问 app
的任何地方都可以使用 app.get('amqp')
来检索连接。在hook this would be context.app.get('amqp').
我正在使用 Feathers 编写一些微服务。 Feathers(和一般的 Node)的新手,运行 遇到了问题。
为了在微服务(即一堆独立的 Feathers 应用程序)之间进行通信,我将使用 RabbitMQ(一个 AMQP 消息代理)。调用某些服务方法后,我想通过 AMQP 发布一条消息。同样,我希望应用程序订阅代理上的交换并在收到特定消息时调用服务方法。
因为我有十几个微服务,所以我决定编写一个库来处理诸如强制执行主题结构和进行重新连接等事情。该库主要是 amqplib 的包装器。我知道有一些开放源代码的羽毛 amqp 模块四处漂浮,但 none 它们完全符合我的要求。
该库有一个 connect() 方法、publish() 方法和一个 subscribe() 方法。 connect() 方法接受一个 url,连接到代理,并将连接对象存储在模块变量中。
计划将 publish() 方法注册为每个相关服务中的挂钩。例如,如果我有一个名为 foo 的服务,它可能有一个 foo.hooks.js:
module.exports = {
before: {
all: [],
find: [],
get: [],
create: [amqpWrapper.publish()],
update: [amqpWrapper.publish()],
patch: [amqpWrapper.publish()],
remove: [amqpWrapper.publish()]
}
//etc
};
其中 publish() 方法正在获取上下文对象,提取它需要的信息,然后通过 amqp 将其丢弃。
还有一个foo.service.js:
// Initializes the `crunch` service on path `/foo`
const createService = require('feathers-nedb');
const createModel = require('../../models/crunch.model');
const hooks = require('./crunch.hooks');
module.exports = function (app) {
const Model = createModel(app);
const paginate = app.get('paginate');
const options = {
Model,
paginate
};
// Initialize our service with any options it requires
app.use('/foo', createService(options));
// Get our initialized service so that we can register hooks
const service = app.service('foo');
service.hooks(hooks);
};
我可能有一个名为 bar 的非常相似的服务,它也在其挂钩中发布。
问题在于您应该为每个进程只维护一个到 rabbitmq 的连接。打开和关闭连接很慢,所以理想情况下,我只想在应用程序启动时调用一次 connect() 方法,并让它持续存在并可从我所有不同的服务全局访问。
我当然可以
const amqpWrapper = require('amqpWrapper')
在所有 [service].hooks.js 文件中,以及在顶层 index.js 中,我也会调用 connectMethod(),但这似乎不正确大部头书。 Javascript 并没有真正的单例,虽然它为 require() 使用缓存,但不能保证。
那么,在 Feathers 中导入具有可随处访问的持久连接的模块的正确方法是什么?我能以某种方式将它存储在 'app' 对象中吗?
编辑
听从了 Daff 的建议,这很有效,但只是想扩展完整的解决方案:
由于我的 amqpWrapper() returns 库的 module.exports,我使用 app.set('amqp', amqpWrapper.connect())
在 /src/app.js 中保存连接,然后在我的 foo.hooks.js, 我就是这样:
module.exports = {
after: {
all: [],
find: [],
get: [],
create: [context => {context.app.get('amqp').publish();}],
update: [],
patch: [],
remove: []
},
//etc
};
这就是app.get and app.set的用途。在 src/app.js
:
const amqpWrapper = require('amqpWrapper')
const connection = amqpWrapper.connect();
app.set('amqp', connection);
现在,您可以访问 app
的任何地方都可以使用 app.get('amqp')
来检索连接。在hook this would be context.app.get('amqp').