【问题标题】:How to split Nest.js microservices into separate projects?如何将 Nest.js 微服务拆分为单独的项目?
【发布时间】:2019-02-15 09:26:23
【问题描述】:

假设我想创建一个简单的影院管理平台。它需要很少的微服务:moviescinemaspayments 等。

你会如何在 Nest.js 中做这件事?我不希望它们在同一个大文件夹中,因为这感觉就像制作一个整体。我希望它们成为独立的 Nest.js 项目,拥有自己的 git 存储库,以便我以后可以使用 Kubernetes 编排它们。

怎么样?如果它们是两个独立的项目并且仅共享,例如Redis,如何从服务cinemas连接到服务movies

编辑: 这不是关于一般微服务的问题。这是 Nest.js 特有的问题。我阅读了文档,我知道有像@Client 这样的装饰器用于连接到传输层。我只是想知道在哪里使用该装饰器,并且可能会看到关于“拥有两个单独的 Nest.js 存储库如何将它们连接在一起以便它们可以相互通信”的简短 sn-p 代码。

我不关心传输层,我可以自己解决这个问题。我只需要关于框架本身的一些建议,因为我认为缺少文档。

【问题讨论】:

  • 微服务不应共享任何数据库,而应仅使用网络(HTTP、消息传递等)进行通信
  • @JesseCarter “假设 Redis”指向特定的传输层。 “你有没有读过文档”——请不要侮辱我。我当然做了。我仍然认为文档缺乏关于如何采用一个微服务并使用@Client(或其他东西)连接到不同微服务的示例。 GitHub (3-microservices) 中的示例仅使用一个项目,并且是一个混合应用程序。这就是我在这里发帖的原因。
  • 我不能给你答案,因为我不使用 Nest.js,但我可以和你分享一些想法。因此,微服务应该只使用网络进行通信,使用隐藏对方使用的技术的协议。因此,如果一个微服务使用 Nest.js(或其他框架),则不应假设其他微服务也使用 Nest.js。而且,当一个微服务处理一个请求时,它不应该在那个请求期间从另一个微服务请求数据如果你想要弹性;换句话说,它应该已经从其他微服务收集了所有数据。
  • 我明白了,+1 来自我
  • 我可以看到实际的微服务示例没有显示多个服务。不过,这绝对超出了 StackOverflow 问题的范围。如果你给它一个赏金,我会整理一个 git repo,你可以用作参考资料

标签: node.js typescript microservices nestjs


【解决方案1】:

我让它工作了。基本上这样做的方法是创建两个单独的项目。假设 - 一个是createMicroservice,另一个只是一个 HTTP 应用程序(但很容易成为另一个微服务)。我使用了一个“普通”应用程序,以便可以轻松调用它进行测试。

这是创建微服务的main.ts 文件。

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { Transport } from '@nestjs/common/enums/transport.enum';

async function bootstrap() {
  const app = await NestFactory.createMicroservice(AppModule, {
    transport: Transport.REDIS,
    options: {
      url: 'redis://localhost:6379',
    },
  });
  await app.listen(() => console.log('MoviesService is running.'));
}
bootstrap();

还有一位控制器:

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @MessagePattern({ cmd: 'LIST_MOVIES' })
  listMovies(): string[] {
    return ['Pulp Fiction', 'Blade Runner', 'Hatred'];
  }
}

现在 - 在微服务中,您声明控制器应响应哪些类型的事件 (@MessagePattern)。在“正常”服务中,当您想向其他微服务请求某些东西时,您可以在控制器中执行此操作(main.ts 是使用@nestjs/cli 创建新项目时获得的最简单示例。

控制器代码:

@Controller()
export class AppController {
  private readonly client: ClientProxy;

  constructor(private readonly appService: AppService) {
    this.client = ClientProxyFactory.create({
      transport: Transport.REDIS,
      options: {
        url: 'redis://localhost:6379',
      },
    });
  }

  @Get()
  listMovies() {
    const pattern = { cmd: 'LIST_MOVIES' };

    return this.client.send<string[]>(pattern, []);
  }
}

只要client 连接到与微服务相同的传输层,它们就可以使用@MessagePattern 相互通信。

要获得更好的代码,您可以将 this.client 部分从构造函数移动到提供程序,然后通过在模块中声明提供程序来使用依赖注入。

【讨论】:

  • 您可能需要考虑使用 Nats 而不是 Redis,这样您就可以继续将 pub/sub 与同一服务的多个节点/实例一起使用(即,您只希望其中一个处理给定的消息.想想用户登录或数据操作)。 Nats 允许您将相同的服务/模块添加到它们自己的队列中,因此只有给定服务的一个实例会接收一条消息。
猜你喜欢
  • 2016-09-28
  • 2020-05-14
  • 1970-01-01
  • 1970-01-01
  • 2022-06-17
  • 2021-02-16
  • 2015-10-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多