Я пытаюсь использовать NestJS и микросервис NATS. Есть хороший документация для настройки базового запроса-ответа.
Я сделал следующее:
Запустил локальный сервер NATS.
Настройте мой main.ts для подключения к серверу:
async function bootstrap() {
const app = await NestFactory.createMicroservice(AppModule, {
options: {
url: "nats://localhost:4222",
},
transport: Transport.NATS,
});
app.listen(() => console.info("Microservice is listening"));
}
bootstrap();
Создал ClientProxyFactory для отправки обратных сообщений:
export const NatsClientProvider: Provider = {
inject: [ConfigService],
provide: NatsClientProviderId,
useFactory: async (config: ConfigService) =>
ClientProxyFactory.create({
options: {
servers: config.getNatsConfig().servers,
},
transport: Transport.NATS,
}),
};
Настройте контроллер app.controller.ts, чтобы он реагировал на определенный шаблон:
@Controller()
export class AppController {
constructor(
private readonly appService: AppService,
@Inject(NatsClientProviderId) private readonly natsClient: ClientProxy,
) {}
@MessagePattern("hello")
async getHello(data: string) {
console.info("data: ", data);
console.info("getHello!!");
await this.natsClient.send("hello", this.appService.getHello());
return this.appService.getHello();
}
async onModuleInit() {
await this.natsClient.connect();
console.info("Nats connected!");
}
Настройте тестовый файл, чтобы попытаться отправить сообщение запрос-ответ:
import { connect } from "ts-nats";
async function start() {
const nc = await connect({
servers: ["nats://localhost:4222"],
});
const msg = await nc.request("hello", 5000, "me");
console.info("msg: ", msg);
}
start();
Когда я запускаю приложение Nest, я вижу правильно созданную подписку в журналах сервера NATS.
Когда я запускаю файл test.ts, время ожидания истекает с NatsError: Request timed out.. Тем не менее, я могу видеть свои журналы консоли (хотя данные undefined, хотя я указываю это в опубликованном сообщении.
Ни return, ни client.send методы не работают для получения сообщений от приложения.
Любая помощь приветствуется!
Обновлено: Все еще изучаю и застрял в этом вопросе. В разделе «Отправка сообщений» Документы по микросервису говорится: «Шаблон должен быть равен шаблону, определенному в декораторе @MessagePattern(), а полезная нагрузка — это сообщение, которое мы хотим передать другому микросервису». Если я это сделаю, приложение Nest обнаружит сообщение, которое оно отправляет, и застрянет в бесконечном цикле отправки сообщения и получения одного и того же сообщения туда и обратно навсегда.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


При использовании ClientProxy send и emit возвращают Observables. Вам нужно «активировать» их, чтобы они могли что-то делать. Таким образом, вы можете либо subscribe им, либо изменить его на Обещание.
так как вы используете await вы, вероятно, хотите сделать
await this.natsClient.send("hello", this.appService.getHello()).toPromise();
Чтобы избежать бесконечного цикла в вашем контроллере, удалите оператор natsClient.send. MessagePattern автоматически отправит ответ с данными, которые вы возвращаете из функции, в вашем случае this.appService.getHello():
@MessagePattern("hello")
async getHello(data: string) {
console.info("data: ", data);
return "Hello World!";
}
Nest требует, чтобы вы отправили длинный атрибут id (подойдет любая строка), чтобы он мог ответить на сообщение. Просто включите его в данные json:
// Nest expects the data to have the following structure
const reply = await nc.request("hello", 500, JSON.stringify({ data: "Hello", id: "myid" }));
console.info({ reply });
В журнале гнезда вы увидите следующую запись журнала:
data: Hello
В тестовом сценарии вы увидите следующее:
{ reply:
{ subject: '_INBOX.GJGL6RJFYXKMCF8CWXO0HB.GJGL6RJFYXKMCF8CWXO0B5',
sid: 1,
reply: undefined,
size: 50,
data: '{"err":null,"response":"Hello World!","id":"myid"}'
} }
Здесь не используется шаблон запроса-ответа: github.com/nats-io/nats.ts. Я просто должен иметь возможность использовать let msg = await nc.request('greeter', 1000, 'me');, который позаботится о полной подписке, публикации и ответе. Вы, возможно, поняли мою проблему с данными, хотя.
Чтобы уточнить, если я отправлю запрос следующим образом: const msg = await nc.request(JSON.stringify({ cmd: "hello" }),5000,JSON.stringify({data: "me",})); я могу записать в консоль правильные данные, но мое приложение Nest не отправляет ответ обратно.
Кроме того, я попробовал подход, который вы упомянули, я получаю ответ от тестового сценария, но это тот же сценарий, который получает свое собственное сообщение, и приложение Nest ничего не получает должным образом. Приложению Nest необходимо отправить ответ на мой сервер NATS, который клиент (тестовый сценарий) получает и регистрирует.
Извините, вы правы, это было неправильно. Пожалуйста, смотрите мое редактирование. Недостающим битом было поле id.
Спасибо за помощь! Есть ли способ также получить тему входного сообщения в Nest? Например, если я хочу подписаться на user.get.>, чтобы получать сообщения на user.get.MY_USER_ID и видеть, что MY_USER_ID было в теме.
Не то, что я знаю из. :/ Работает ли он даже с подстановочными знаками в гнезде?
Если это не работает с подстановочными знаками, это не для меня. Я обошел эту проблему, реализовав свой собственный общедоступный/подуровень NATS, но мне бы хотелось использовать инфраструктуру Nest. Я открою вопрос с Nest по этому поводу. Спасибо за помощь.
Я только что проверил, и он действительно работает с подписками с подстановочными знаками, как в приведенном мной примере (@MessagePattern('hello.>') и тема запроса hello.world). Теперь, если я смогу распечатать тему, я буду готов.
Я не думаю, что это часть API, но вы можете открыть для него вопрос (или даже запрос на извлечение). Не должно быть сложно, я думаю.
Хм, спасибо за информацию. Я попробовал это, и я все еще получаю бесконечный цикл, когда служба продолжает отвечать на свое собственное сообщение (похоже, это связано с тем, что сообщение
@MessagePatternсовпадает с отправляемой темой. Хотя я предполагаю, что это должно быть вот так, чтобы работал запрос-ответ, только не понимаю, как сделать, чтобы он не отвечал сам на себя, так как и ClientProxy, и микросервис Nest подключены к одному и тому же NATS-серверу.