If you want to use a microservice framework for your Node.js project, I recommend Moleculer for its rich functionality, well-documented, efficient performance and flexible configuration. Let’s start by looking at the architecture diagram:

The figure above depicts the following application scenarios:

  1. User requests arrive at the API gateway layer through HTTP protocol
  2. The Gateway service parses the request and gives the data and instructions to the Broker
  3. The Broker calls the microservice internal function through the Transporter to return the processed data

As can be seen from this figure, Moleculer takes over the internal service registration and discovery, message communication between services, load balancing and other low-level complex logic. Users only need to write core business logic, which greatly improves development efficiency.

The core concept

Service Service

A service is an independent business unit, essentially a JS object. For example, the following code implements complete addition, subtraction, multiplication, and division, which we might call a Math service:

module.exports = {
  name: 'math'.actions: {
    add(ctx) {
      const { a, b } = ctx.params
      return a + b
    },
    subtract(ctx) {
      const { a, b } = ctx.params
      return a - b
    }
    // omit the code}},Copy the code

Node Node

A Node is a Node process locally or on the network, and each Node can host multiple services internally. For example, two services, math and statistic, are defined and placed in the services directory. The directory structure is as follows:

Services ├ ─ ─ math. Service. Js └ ─ ─ statistic. Service. JsCopy the code

Now start it in the same Node process.

const { ServiceBroker } = require('moleculer')
const broker = new ServiceBroker()
broker.loadServices('./services')
broker.start().catch((e) = > console.error(e))
Copy the code

Then the initiated Node is a Moleculer Node.

Local services

Services on the same node are local services to each other, sharing hardware resources and communicating over a local bus without any network latency. For example, the math and statistic services are local services to each other. Math methods can be directly invoked within a statistic.

module.exports = {
  name: 'statistic'.actions: {
    calculate(ctx) {
      return ctx.call(`math.add`, { a: 3.b: 4})},}},Copy the code

Remote Services

Services on different nodes are remote services that communicate with each other through some kind of transport medium, such as messaging middleware. For example, we have a Node process loaded with the user and Account services:

Services ├ ─ ─ account. Service. Js └ ─ ─ the user. The service. JsCopy the code

User and Math are then remote services to each other because they are not under the same Node process, so calling another process’s math.multiply method in user.get, for example, would have to communicate over the transport medium.

module.exports = {
  name: 'user'.actions: {
    async get(ctx) {
      return ctx.call('math.multiply', { a: 3.b: 10})},}},Copy the code

A Service Broker

Service mediations are at the heart of Moleculer’s framework and are responsible for communication between services (both local and remote). Each node has a service mediator.

const { ServiceBroker } = require('moleculer')
const broker = new ServiceBroker()
Copy the code

There are many methods for broker instances, such as:

  • throughloadServiceMethod to load the service
  • throughemitMethod firing event
  • throughcallMethod to send a request

Transport media Transporter

Transport media is responsible for the communication between nodes and is the communication bus for transmitting messages between services. It can trigger events, send requests, and receive responses.

That is, if the user service on Node1 wants to send messages to the Math service on Node2, it needs to communicate through transport media. Moleculer provides a variety of transport media, for example:

  • The nats (yarn add nats )
  • Redis (yarn add ioredis)
  • Kafka,yarn add kafka-node)
  • MQTT (yarn add mqtt)
  • It (yarn add amqplib)
  • And so on, you can also customize the transmission media
const { ServiceBroker } = require('moleculer')
const broker = new ServiceBroker({
  transporter: 'nats://localhost:4222'.// Use nATS transmission media
  // transporter: 'redis://localhost:6379', // Use redis transport media
  // transporter: 'kafka://localhost:2181', // Use kafka transport medium
  // transporter: 'MQTT ://localhost:1883', // use MQTT transport media
  Transporter: "amqp://localhost:5672", // Use the amQP transport medium
})
Copy the code

The Gateway of Gateway

The gateway exposes the internal service to the end user, which is exactly a regular Moleculer service that integrates HTTP or WebSocket functions to forward user requests to the internal service. A RESTful API gateway is officially provided:

yarn add moleculer-web # 或者 npm i moleculer-web 
Copy the code

Usage:

const { ServiceBroker } = require('moleculer')
const ApiService = require('moleculer-web')
const broker = new ServiceBroker({ transporter: 'nats://localhost:4222' })
broker.createService(ApiService)
broker.start()
Copy the code

A RESTful HTTP service is enabled on port localhost:3000 by default:

curl 'localhost:3000/math/subtract? a=5&b=3'
Copy the code

If the Math service is started, then the request is forwarded by Moleculer to the Math. subtract method for processing and returns result 2.

Command line tool

The most popular feature of Moleculer for developers is that it provides a very powerful command line tool, moleculer-repl, which automatically loads xxx.service.js files in the services directory using conventions that are larger than the configuration, and supports hot loading in the development environment. That is to say, it automatically listens for code changes and saves and updates the service without restarting it. The configuration in package.json is as follows:

"scripts": {
  "dev": "moleculer-runner --repl --hot services"."start": "moleculer-runner"
},
Copy the code

Moleculer-repl provides the command line to see all the methods and events:

You can also debug various methods directly, for example:

call "math.add" --a 5 --b 6 Command line pass parameter
call "math.add" --load my-params.json Load parameters from a file
call "math.add" --save my-response.json Save the result to a file
Copy the code

Moleculer-runner can be directly installed in the production environment, with functions such as log management, error debugging, cache, parameter verification, etc.

Database connection

Moleculer encapsulates Moleculer-DB library, packages THE LOGIC of CRUD into it, and interconnects with Mongo, Mongoose and Sequelize ORM frameworks, so you don’t need to write a line of code for adding, deleting, modifying and checking, as long as you introduce corresponding libraries and adapters:

const DbService = require('moleculer-db')
const mongoose = require('mongoose')
const MongooseAdapter = require('moleculer-db-adapter-mongoose')
Copy the code

Then, when creating the service, add the following parameters:

broker.createService({
  name: 'order'.mixins: [DbService],
  adapter: new MongooseAdapter('mongodb://localhost:27017/test'),
  model: mongoose.model(
    'order',
    mongoose.Schema({
      orderNo: { type: String },
      price: { type: Number.default: 0})}})),Copy the code

The count, create, find, get, INSERT, list, remove, and update methods are automatically generated out of the box.

The middleware

Moleculer also supports middleware, the framework has built-in middleware, and users can define their own middleware, as well as the onion model familiar to Express:

In Moleculer, middleware is essentially an object containing higher-order functions that can be applied to methods, events, etc., such as the following error-catching middleware:

module.exports = {
  name: 'error'.localAction(next, action) {
    return async function (ctx) {
      try {
        return await next(ctx)
      } catch (e) {
        console.log('Action gone wrong', action.name)
        throw e
      }
    }
  }
}
Copy the code

This is just a preliminary introduction to the core knowledge of Moleculer, but there are many more powerful functions, if you are interested, you can refer to the official documentation.

In this paper, the example code address: git clone [email protected]: keliq/moleculer – demo. Git