Как настроить постоянное соединение для оболочки amqplib через ловушки / сервисы в приложении Feathers - PullRequest
0 голосов
/ 04 июня 2019

Я пишу некоторые микросервисы, используя Перья.Довольно плохо знаком с Feathers (и Node в целом) и столкнулся с проблемой.

Для связи между микросервисами (т. Е. Набором независимых приложений Feathers) я собираюсь использовать RabbitMQ (брокер сообщений AMQP).).После вызова определенных методов обслуживания я хотел бы опубликовать сообщение через AMQP.Точно так же я хотел бы, чтобы приложение подписывалось на обмен в брокере и вызывало метод обслуживания при получении определенного сообщения.

Поскольку у меня есть около десятка микросервисов, я решил написать библиотеку, которая обрабатываеттакие вещи, как усиление структуры темы и повторное подключение и т. д. Библиотека - это всего лишь оболочка для amqplib.Я знаю, что несколько плавающих модулей с открытым исходным кодом amqp плавают вокруг, но ни один из них не делает именно то, что я хочу.

В библиотеке есть метод connect (), метод publish () и подписка () метод.Метод 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 (), он не гарантирован.

Итак, каков правильный способ импорта модуля с постоянным соединением, который доступен везде вПерья?Могу ли я как-то сохранить его в объекте 'app'?

Редактировать

Следовал предложению Даффа, и это работает, но просто хотел расширить полное решение:

Так как мой amqpWrapper () возвращает модуль библиотеки module.exports, я сохраняю соединение в /src/app.js, используя app.set('amqp', amqpWrapper.connect()), а затем в моем foo.hooks.js, я просто делаю:

module.exports = {
  after: {
    all: [],
    find: [],
    get: [],
    create: [context => {context.app.get('amqp').publish();}],
    update: [],
    patch: [],
    remove: []
  },
//etc
};

1 Ответ

1 голос
/ 05 июня 2019

Для этого можно использовать app.get и app.set src/app.js:

const amqpWrapper = require('amqpWrapper')
const connection = amqpWrapper.connect();

app.set('amqp', connection);

Теперь везде, где у вас есть доступ к app, можно использовать app.get('amqp') для получения соединения.В hook это будет context.app.get ('amqp') .

...