How to split Nest.js microservices into separate projects?

14,890

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.

Share:
14,890

Related videos on Youtube

Tomasz Gałkowski
Author by

Tomasz Gałkowski

Programmer, full-stack web developer interested in functional and object oriented paradigms. After hours: RPG Game Master, indie rock fan and... programmer as well!

Updated on November 14, 2020

Comments

  • Tomasz Gałkowski
    Tomasz Gałkowski over 3 years

    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.

    • Constantin Galbenu
      Constantin Galbenu over 5 years
      the microservices should not share any database and should communicate only using the network (HTTP, messaging etc)
    • Tomasz Gałkowski
      Tomasz Gałkowski over 5 years
      @JesseCarter "let's say Redis" is pointing to a specific transport layer. "Did you even read the docs" - please don't insult me. Of course I did. I still think the documentation is lacking in example on how to take one microservice and use @Client (or something) to connect to different one. The sample in GitHub (3-microservices) is using only one project and is a hybrid app. That's why I posted here.
    • Tomasz Gałkowski
      Tomasz Gałkowski over 5 years
      @ConstantinGalbenu yes, they shouldn't share a database. That's why I want them as seperate as they can be. Nest.js supports multiple different transport layers including Transport.REDIS. That was just an example.
    • Constantin Galbenu
      Constantin Galbenu over 5 years
      I can't give you an answer because I don't use Nest.js but I could share with you some thoughts. So, the microservices should communicate only using the network, using a protocol that hides the technologies that are used by the other. So, if a microservice uses Nest.js (or another framework) it should not assume that the other microservice uses also Nest.js. And also, when a microservice processes a request, it should not ask for data from another microservice during that request if you want resilience; in other words, it should have all the data already gathered from other microservice.
    • Tomasz Gałkowski
      Tomasz Gałkowski over 5 years
      @ConstantinGalbenu I know how microservices work. I need to use Nest.js for microservices though and I don't grasp how to utilize their decorators. This is a Nest.js specific question (hence the tag). It's not the architecture I'm asking for but an example of two Nest.js microservices that can talk to one another but are in separate two Nest.js projects.
    • Constantin Galbenu
      Constantin Galbenu over 5 years
      I understand now, +1 from me
    • Jesse Carter
      Jesse Carter over 5 years
      I can see that the actual microservices example doesn't show multiple services.This is definitely still outside the scope of a StackOverflow question though. If you put a bounty on it I'll put together a git repo that you can use as reference material
    • Jesse Carter
      Jesse Carter over 5 years
      Good stuff! Glad you figured out how to put things together. After you asked this I decided to put together an example repo anyways. It's pretty barebones at the moment but provides a GraphQL client application that communicates with another microservice over Redis. Set up with all kinds of docker and docker-compose goodness so that people can reference a working example: github.com/WonderPanda/nestjs-microservice-architecture
  • Jubair
    Jubair over 3 years
    You might want to consider using Nats instead of Redis so that you can continue to use pub/sub with multiple nodes/instances of the same service (i.e. you only want one of them to handle a given message. think user login, or data manipulation). Nats allows you to add the same services/modules to their own queue so only one instance of a given service picks up a message.