Nest: Microservices under the hood

Created on 6 Aug 2019  路  5Comments  路  Source: nestjs/nest

Explanation/Documentation request

I know that such type of questions need to ask in stackoverflow, but I think another people can't explain such as it can do the creator ;)

Can you explain all topology of microservices ? Maybe in schemas, docs or text message.
What is under the hood? How it works?

Does we need to create separate main.ts and microservice-la-la.ts for different instances ?
And what the difference when we connect microservice to main application instance and have several independent instances of services?
Does it create child process/cluster/worker/etc ?
What will be if my connected microservice will block event loop? Will it affect the main application?

Can you share your vision of the best practices?

I think this is very-very powerful tool of nest, but the docs are scarce. It's describe only exists transports and a very little part of concept.

needs triage type

Most helpful comment

@ed-fruty
Kamil is currently busy, so I try to answer some of your questions - but Kamil is definitely the person who can give you the best answer.

Does it create child process/cluster/worker/etc ?

We do not do that out of the box. We leave this task to the user, since it is too general on how you want to orchestrate your application.

Does we need to create separate main.ts and microservice-la-la.ts for different instances ? And what the difference when we connect microservice to main application instance and have several independent instances of services?

Combining your normal HTTP application with a microservice (NestApplication.connectMicroservice) brings on one hand the value of sharing common functionality between a microservice instance, but also allows to communicate using the microservice transport strategies (TCP, Redis, MQTT, etc.) from e.g. a HTTP Controller. Important to note is that this all runs in the same node instance. Read more about that in the Hybrid Application chapter.


Maybe an example I have recently used may give you more insights on how to structure your app. The following example is just how I use it. It definitely varies from your personal preferences and use-cases.
My application consists of two main parts:

  • REST API
    Consists of normal crud operations. Also triggers a database synchronization using TCP through a route POST api/v1/sync.
  • A service for database synchronization
    Listen to TCP messages, which runs a synchronization task.

The REST API is being create using the "normal" NestFactory.create(). It also connects to a microservice and sets the TCP connection up using NestApplication.connectMicroservice({ tcpOptions }).
I then inject the TCP Client into my sync controller. The @Post method of the controller will send then a message to my database sync service using TCP and waits for a response.

The database synchronization service is a microservice app using NestFactory.createMicroservice(). This is all in a dedicated main.ts file, totally separated from the REST APIs main.ts. This allows me to spawn a separated node process, so it is easier to manage using Docker / Kubernetes.
The synchronization service application only consists of a @Controller which listens to TCP messages from the REST API. See here. The service will just run the task once a message is being received. The task itself could be refactored into an own worker application, which then could be executed as a child process from the service.

The best way to orchestrate this whole architecture would definitely be a monorepo setup. For each application you would have an own package. I use this boilerplate for my monorepo setups though you can also use nrwl/nx

```
packages
|- api
| |- src
| | |- main.ts
| | |- Dockerfile
|- common
| |- src
| | |- index.ts // Just common modules/functionalities, so no need to have a dedicated Nest app
|- sync
| |- src
| | |- main.ts
| | |- Dockerfile
docker-compose.yml
````

This may give you a bit more guidance how the microservices architecture of Nest is meant to be used. As mentioned, it is hard to create a chapter on this topic, since it is quite opinionated. May a blog post would be feasible...

All 5 comments

@kamilmysliwiec , we are calling you ;)

@ed-fruty
Kamil is currently busy, so I try to answer some of your questions - but Kamil is definitely the person who can give you the best answer.

Does it create child process/cluster/worker/etc ?

We do not do that out of the box. We leave this task to the user, since it is too general on how you want to orchestrate your application.

Does we need to create separate main.ts and microservice-la-la.ts for different instances ? And what the difference when we connect microservice to main application instance and have several independent instances of services?

Combining your normal HTTP application with a microservice (NestApplication.connectMicroservice) brings on one hand the value of sharing common functionality between a microservice instance, but also allows to communicate using the microservice transport strategies (TCP, Redis, MQTT, etc.) from e.g. a HTTP Controller. Important to note is that this all runs in the same node instance. Read more about that in the Hybrid Application chapter.


Maybe an example I have recently used may give you more insights on how to structure your app. The following example is just how I use it. It definitely varies from your personal preferences and use-cases.
My application consists of two main parts:

  • REST API
    Consists of normal crud operations. Also triggers a database synchronization using TCP through a route POST api/v1/sync.
  • A service for database synchronization
    Listen to TCP messages, which runs a synchronization task.

The REST API is being create using the "normal" NestFactory.create(). It also connects to a microservice and sets the TCP connection up using NestApplication.connectMicroservice({ tcpOptions }).
I then inject the TCP Client into my sync controller. The @Post method of the controller will send then a message to my database sync service using TCP and waits for a response.

The database synchronization service is a microservice app using NestFactory.createMicroservice(). This is all in a dedicated main.ts file, totally separated from the REST APIs main.ts. This allows me to spawn a separated node process, so it is easier to manage using Docker / Kubernetes.
The synchronization service application only consists of a @Controller which listens to TCP messages from the REST API. See here. The service will just run the task once a message is being received. The task itself could be refactored into an own worker application, which then could be executed as a child process from the service.

The best way to orchestrate this whole architecture would definitely be a monorepo setup. For each application you would have an own package. I use this boilerplate for my monorepo setups though you can also use nrwl/nx

```
packages
|- api
| |- src
| | |- main.ts
| | |- Dockerfile
|- common
| |- src
| | |- index.ts // Just common modules/functionalities, so no need to have a dedicated Nest app
|- sync
| |- src
| | |- main.ts
| | |- Dockerfile
docker-compose.yml
````

This may give you a bit more guidance how the microservices architecture of Nest is meant to be used. As mentioned, it is hard to create a chapter on this topic, since it is quite opinionated. May a blog post would be feasible...

Great explanation @BrunnerLivio!

Can you share your vision of the best practices? I think this is very-very powerful tool of nest, but the docs are scarce. It's describe only exists transports and a very little part of concept.

We are working hard on the documentation, and hopefully, we'll be able to provide more detailed docs about how to properly use microservices package (including best practices, some orchestration strategies, etc).

Another useful resource to understand NestJS microservices by @brianjohnsonsr. Great job!
https://youtu.be/w7zJNMOIRbw

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings