【问题标题】:NestJS NATS request-responseNestJS NATS 请求-响应
【发布时间】:2019-10-26 05:31:38
【问题描述】:

我正在尝试使用 NestJS 和 NATS 微服务。有一个很好的 documentation 用于设置基本的请求-响应。

我所做的是:

运行本地 NATS 服务器。

设置我的main.ts 连接到服务器:

async function bootstrap() {
  const app = await NestFactory.createMicroservice(AppModule, {
    options: {
      url: "nats://localhost:4222",
    },
    transport: Transport.NATS,
  });
  app.listen(() => console.log("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.log("data: ", data);
    console.log("getHello!!");
    await this.natsClient.send("hello", this.appService.getHello());
    return this.appService.getHello();
  }

  async onModuleInit() {
    await this.natsClient.connect();
    console.log("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.log("msg: ", msg);
}

start();

当我运行我的 Nest 应用程序时,我可以在 NATS 服务器日志中看到正确创建的订阅。

当我运行test.ts 文件时,它会以NatsError: Request timed out. 超时。但是,我可以看到我的控制台日志(尽管数据是 undefined,尽管我在发布的消息中指定了它。

returnclient.send 方法都无法从应用接收消息。

感谢任何帮助!

编辑: 仍在研究并坚持这个问题。在Microservice docs 的“发送消息”部分,它说“模式必须等于在@MessagePattern() 装饰器中定义的模式,而有效负载是我们想要传输到另一个微服务的消息。”。如果我这样做,Nest 应用程序会检测到它发送的消息并陷入无限循环,即发送消息并永远来回接收相同的消息。

【问题讨论】:

    标签: javascript node.js typescript nestjs nats.io


    【解决方案1】:

    使用 ClientProxy 时,sendemit 返回 Observables。你需要“激活”那些让他们做任何事情。所以你可以subscribe给他们,或者把它改成一个Promise。

    因为您使用的是await,所以您可能想要这样做

    await this.natsClient.send("hello", this.appService.getHello()).toPromise();
    

    【讨论】:

    • 嗯,谢谢你的信息。我试过这个,我仍然得到服务不断响应自己的消息的无限循环(似乎这是由于@MessagePattern消息与正在发送的主题相同。虽然我认为它会像这样为了请求-响应工作,我只是不明白如何让它不响应自己,因为 ClientProxy 和 Nest 微服务都连接到同一个 NATS 服务器。
    【解决方案2】:

    要避免控制器中的无限循环,请删除 natsClient.send 语句。 MessagePattern 将自动发送回复,其中包含您从函数返回的数据,在您的情况下为 this.appService.getHello()

    @MessagePattern("hello")
    async getHello(data: string) {
      console.log("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.log({ 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 字段。
    • 我认为这不是 API 的一部分,但您可以为它打开一个问题(甚至拉取请求)。我认为应该不会太难。
    猜你喜欢
    • 2019-06-03
    • 1970-01-01
    • 2019-08-21
    • 2020-04-24
    • 1970-01-01
    • 1970-01-01
    • 2021-03-02
    • 2018-08-17
    • 1970-01-01
    相关资源
    最近更新 更多