Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to split Nest.js microservices into separate projects?

Let's say I want to create a simplistic cinema-management platform. It needs few microservices: movies, cinemas, payments, etc.

How would you go about doing it in Nest.js? I don't want them in the same big folder as that feels like making a monolith. I want them to be separate Nest.js projects with their own git repositories so I can orchestrate them with Kubernetes later on.

How? How to connect from service cinemas to service movies if they are two separate projects and only share, let's say, Redis?

Edit: This is not a question about microservices in general. This is a question Nest.js specific. I read the documentation, I know there are decorators like @Client for connecting to the transport layer. I just want to know where to use that decorator and maybe see a short snippet of code on "having two separate Nest.js repositories how to connect them together so they can talk to each other".

I don't care about the transport layer, that thing I can figure out myself. I just need some advice on the framework itself as I believe the documentation is lacking.

like image 595
Tomasz Gałkowski Avatar asked Sep 10 '18 22:09

Tomasz Gałkowski


People also ask

Is NestJS good for Microservices?

Looking at the capabilities of an application, a microservice-based architecture has gained popularity in recent years. NestJS is a Node. JS framework based on ExpressJS, but it's more than that. In fact, NestJS gives you everything you need to create microservices easily.

How do you communicate between Microservices in NestJS?

You need to set up a message broker, something like RabbitMQ or Kafka, ie for RabbitMQ enter the command below and create a RabbitMQ container. Now when a client sends a message on myqueue with my_pattern pattern, the data that client sends will be data which comes from @playload() annotation.

Is NestJS monolithic?

In addition to traditional (sometimes called monolithic) application architectures, Nest natively supports the microservice architectural style of development.

Is NestJS a backend?

NestJS is a relatively new option in backend development, with many features for building and deploying enterprise services quickly and following the principles of SOLID and 12-factor applications.


1 Answers

I got it working. Basically the way to do it is to create two separate projects. Let's say - one is a createMicroservice and another is just an HTTP app (but could easily be another microservice). I used a "normal" app just so I can call it easily for testing.

Here is the main.ts file that creates microservice.

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();

And one of the controllers:

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

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

Now - in the microservice you declare to what kinds of events should controllers react to (@MessagePattern). While in the "normal" service you do this in the controller when you want to ask other microservices for something (the main.ts is the simplest example that you get when you create a new project using @nestjs/cli.

The controller code:

@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, []);
  }
}

So as long a client is connected to the same transport layer as the microservice - they can talk to each other by using the @MessagePattern.

For nicer code you can move the this.client part from a constructor to a provider and then use dependency injection by declaring the provider in the module.

like image 133
Tomasz Gałkowski Avatar answered Oct 02 '22 15:10

Tomasz Gałkowski