MoleculerJs

5BRack·2023년 3월 21일

Moleculer

목록 보기
1/1

MoleculerJs 란?

  • Moleculer는 Node.js를 위한 마이크로서비스 프레임워크이다.
  • 효율적이고 안정적이며 확장 가능한 서비스를 구축하는 데 도움이 된다.

특징

  • Promise 기반 솔루션(async/await 호환)
  • 요청-응답 개념
  • 밸런싱으로 이벤트 기반 아키텍처 지원
  • 내장 서비스 레지스트리 및 동적 서비스 검색
  • 로드 밸런싱된 요청 및 이벤트(라운드 로빈, 랜덤, CPU 사용량, 대기 시간, 샤딩)
  • 많은 내결함성 기능(회로 차단기, 벌크헤드, 재시도, 시간 초과, 폴백)
  • 플러그인/미들웨어 시스템
  • 버전 서비스 지원
  • 스트림 지원
  • 서비스 믹스인
  • 빌트인 캐싱 솔루션(Memory, MemoryLRU, Redis)
  • 플러그형 로거(콘솔, 파일, Pino, Bunyan, Winston, 디버그, Datadog, Log4js)
  • 플러그 가능한 전송기(TCP, NATS, MQTT, Redis, NATS Streaming, Kafka, AMQP 0.9, AMQP 1.0)
  • 플러그형 직렬 변환기(JSON, Avro, MsgPack, 프로토콜 버퍼, Thrift)
  • 플러그형 매개변수 유효성 검사기
  • 노드/서버의 여러 서비스
  • 마스터리스 아키텍처, 모든 노드는 동일합니다.
  • 가장 빠른 유효성 검사기 로 매개변수 유효성 검사
  • 리포터(Console, CSV, Datadog, Event, Prometheus, StatsD)가 포함된 내장 메트릭 기능
  • 내보내기 기능 내장(Console, Datadog, Event, Jaeger, Zipkin)
  • 공식 API 게이트웨이데이터베이스 액세스 및 기타 여러 모듈…

핵심 개념

서비스

  • 비즈니스 로직을 포함하는 독립적인 자바 스크립트 모듈

노드

  • 로컬 또는 외부 네트워크에서 실행되는 단순한 OS 프로세스

로컬 서비스

  • 한 노드내에 둘 이상의 서비스는 로컬 서비스로 간주

원격 서비스

  • 여러 노드에 분산된 서비스는 원격 서비스로 간주 이경우, Transporter를 이용해 통신이 이루어짐

서비스 브로커

  • 서비스 간의 관리 및 통신을 담당, 각 노드에서 Service 인스턴스가 존재
  • 노드에는 하나 이상의 서비스 브로커가 존재

Transporter

  • 서비스가 메시지를 교환하는데 사용하는 통신 버스
  • 서비스 브로커내에 존재

게이트웨이

  • Http, Websocket 서버를 실행하는 Moleculer 서비스
  • 주로 Mixin으로 사용

아키텍처

<사진 출처 : Moleculer 공식 홈페이지>

  1. 클라이언트가 GET / 요청
  2. 게이트웨이에서 요청된 서비스에 작업에 매핑
  3. 서비스 브로커에서 로컬 서비스인지 외부 서비스 인지 판단
  4. 외부 서비스 이므로, Transporter를 이용해 메시지 브로커 통신
  5. 매핑되어 전달 받은 메시지를 전달받은 노드의 서비스 브로커에서 해당 비즈니스 로직 수행
  6. 로직 수행 후 클라이언트 반환

아키텍처로 미루어 보았을 때 Moleculer를 사용하는 이유

마이크로서비스에서는 각 서비스간의 통신이 중요한데 이러한 통신적인 부분들을  
Moleculer 프레임워크에서 처리해 주므로, 개발자는 주요한 비즈니스 로직에만 집중
을 하면 되기 때문

상세 개요

브로커

  • 서비스를 처리하고 작업을 호출하며 이벤트를 내보내고 원격 노드와 통신을 담당
  • 모든 노드에서는 각 한개의 서비스 브로커가 필요하다.

주요 브로커 옵션

moleculer.config 파일을 이용하여 브로커 옵션을 설정할 수 있다.
  • namespace : 동일한 네트워크에서 노드를 분할하기 위한 노드의 네임스페이스
  • nodeId : 고유한 노드 식별자
  • logger : 로커 클래스
  • logLevel : 로거의 로그 수준
  • transporter : 트랜스 포터 구성
  • requestTimeout : 오류가 있는 요청을 거부하기 전에 대기하는 시간
  • 그 외 옵션들

https://moleculer.services/docs/0.14/configuration.html


서비스

  • 비즈니스 로직을 처리하는 마이크로 서비스
  • 작업을 처리하고 이벤트를 구독할 수 있다.

주요 스키마

name

  • 서비스명, 액션을 호출할 때 액션 이름의 첫부분

예시 코드

export default class UsersService extends Service{
    constructor(broker: ServiceBroker) {
        super(broker);
        this.parseServiceSchema({
            name: serviceConfig.user.serviceName, //서비스명 정의
        });
    }  
}

호출 예시

await this.broker.call("서비스명.액션명");


version

  • 선택적 속성, 동일한 서비스에서 여러 버전을 실행하는 데 사용, 사용할 경우 액션을 호출할 때 액션 이름앞에 버전을 명시해 주어야 한다.

예시 코드

export default class UsersService extends Service{
    constructor(broker: ServiceBroker) {
        super(broker);
        this.parseServiceSchema({
            name: serviceConfig.user.serviceName,
            version: "v1",
        });
    }  
}

호출 예시

await this.broker.call("버전명.서비스명.액션명");


settings

  • 서비스에 대한 모든 설정/옵션을 저장할 수 있는 정적 저장소, this 를 이용하여 사용한다.

예시 코드

export default class UsersService extends Service{
    constructor(broker: ServiceBroker) {
        super(broker);
        this.parseServiceSchema({
            name: serviceConfig.user.serviceName,
						settings : {
							host : String(process.env.DATABASE_HOST),
			        db_port : Number(process.env.DATABASE_PORT),
					  },
        });
    }  
}

사용시

adatper : new SqlAdapter({
	dialect: "mariadb",
	host: this.settings.host,
	port: this.settings.db_port
})

actions

  • 서비스의 호출가능 / 공용 메서드
  • `broker.call() 또는 [ctx.call](http://ctx.call)()` 메서드로 호출할 수 있다.
  • 작업을 명시하는 방법은 여러가지가 존재한다.
  • 여러 서비스 인스턴스가 존재하는 경우 브로커는 자체적으로 인스턴스 간의 요청 부하를 분산한다.
  • 내부에 before hook(액션 호출 전), after hook(액션 호출 후) 을 설정하여 이벤트를 발생시킬 수 있다.

예시 코드

actions:{
			get:{
            rest : "GET /test/:message",
            params: {
                message : "string | max: 10",
            },
            async handler(ctx:Context) : Promise<void>{
                // 비즈니스 로직 정의
            }
      }
}

events

  • 서비스 정의 단계에서 서비스 이벤트를 구독(subscribe)할 수 있다.

컨테이너 환경에서 같은 이벤트를 가진 동일한 서비스가 존재하더라도 하나의 서비스만 Broker가 자체적으로 선택하여 이벤트를 호출한다.

  • broker.emit()을 통해 이벤트를 호출할 수 있다.
  • broker.boadcast() 를 통해 모든 서비스의 이벤트를 호출할 수 있다.

예시 코드

events: {
        // Subscribe to "user.created" event
        "user.created"(ctx) {
            this.logger.info("User created:", ctx.params);
            // Do something
        },
},

Methods

  • 서비스 내부에서만 사용하는 메서드를 정의
  • method는 외부에 메서드를 내보내지 않으므로, 내부 서비스에서만 this를 이용하여 호출할 수 있다.

예시코드

{
    name: "mailer",
    actions: {
        send(ctx) {
            // Call the `sendMail` method
            return this.sendMail(ctx.params.recipients, ctx.params.subject, ctx.params.body);
        }
    },

    methods: {
        // Send an email to recipients
        sendMail(recipients, subject, body) {
            return new Promise((resolve, reject) => {
                ...
            });
        }
    }
};

Lifecycle Events

created

  • 서비스 객체가 만들어졌을 때 이벤트가 발생.

started

  • 브로커가 모든 로컬 서비스를 시작할 때 이벤트가 발생.
  • 주로 DB 연결, 서버 listen 등의 작업을 한다.

stopped

  • 모든 로컬 서비스를 종료할 때 이벤트 발생
  • 데이터 베이스 연결을 닫고 소켓을 닫는 작업 등을 한다.

Dependencies

  • 서비스가 다른 서비스에 종속되어 있는 경우 설정
  • 서비스는 시작된 라이프 사이클 이벤트 핸들러를 호출하기 전에 종속 서비스의 시작을 기다린다.

예시 코드

export default class AuthService extends Service {
    constructor(broker:ServiceBroker){
        super(broker);
        this.parseServiceSchema({
            name: serviceConfig.auth.serviceName,
            actions,
            methods,
            dependencies: ["users"], // users 서비스가 시작되고 Auth 서비스 시작
            created : authServiceCreated,
            started : authServiceStarted,
            stopped : authServiceStopped,
        });
    }
}

네트워크

  • 다른 노드와 통신을 하려면 Transporter를 구성해야 한다.
  • 지원되는 대부분의 Transporter는 원격 노드 간에 신뢰할 수 있는 메시지 교환 방법을 제공하는 중앙 메시지 브로커에 연결이 된다.
  • 이러한 메시지 브로커는 pub/sub 메시지 패턴을 지원한다.

Transporter

  • 다른 노드와 통신을 하기 위해 만들어진 모듈
  • 이벤트를 전송하고 요청을 호출하고 응답을 처리하는 등의 작업을 수행

지원하는 Transporter

  • TCP Transporter
  • NATS Transporter
  • Redis Transporter
  • MQTT Transporter
  • AMQP (0.9) Transporter
  • AMQP 1.0 Transporter
  • Kafka Transporter
  • NATS Streaming (STAN) Transporter
  • 등 커스텀 Transporter 또한 지원한다.

또한 Moleculer는 Registry & Discovery 및 캐싱 등 여러가지 msa 서비스를 구성하기 위한 기능들을 제공한다.

참고 실행 스크립트(각각의 다른 프로세스로 실행)

"dev_gateway": "ts-node ./node_modules/moleculer/bin/moleculer-runner.js -E env/local/gateway.service.local.env --config services/gateway/moleculer.gateway.config.ts --hot --repl services/gateway/gateway.service.ts",
"dev_auth": "ts-node ./node_modules/moleculer/bin/moleculer-runner.js -E env/local/auth.service.local.env --config services/auth/moleculer.auth.config.ts --hot --repl services/auth/*.service.ts",
"dev_io": "ts-node ./node_modules/moleculer/bin/moleculer-runner.js -E env/local/io.service.local.env --config services/io/moleculer.io.config.ts --hot --repl services/io/*.service.ts",

0개의 댓글