[Eureka] NestJs 서비스와 유레카 서비스 디스커버리 연결(eureka-js-client)

Seung Hyeon ·2024년 2월 26일
0

백엔드

목록 보기
13/19
post-custom-banner

nestjs-eureka에서 eureka-js-client으로

💥 문제 상황

현재 진행하고 있는 프로젝트는 MSA로 개발 중이었고 그 중 하나의 인스턴스를 담당하여 nestjs로 개발하고 있었다.
인스턴스(서비스)를 Java로 구현된 Eureka 서비스 디스커버리에 등록하여 각 서비스들이 통일된 게이트웨이 서버에서 구동되도록 하고자 했다.

// src/configs/eureka.module.ts

@Module({
  imports: [
    EurekaModule.forRootAsync({
      imports: [ConfigModule],
      useFactory: async (configService: ConfigService) => ({
        service: {
          name: 'common-service-dev',
          port: +configService.get('PORT1') 
          host: configService.get('HOST'),
        },
        eureka: {
          host: configService.get('Eureka_HOST'),
          port: +configService.get('Eureka_PORT'),
          servicePath: '/eureka/apps/',
        },
      }),
      inject: [ConfigService],
    }),
  ],
  exports: [EurekaModule],
})
export class ServiceDiscoveryModule {}

기존에는 nestjs-eureka라이브러의 EurekaModule을 이용하여 유레카 서비스 디스커버리에 연결했었다.

배포한 서비스 로그를 확인해보니 위와 같이 유레카 디버그 로그가 너무 많이 차지해버려서 다른 로그들을 볼 수 없었다.
따라서 로그 수준을 info까지만 출력되게 수정하고 싶었다.

// src/configs/eureka-module.ts

@Module({
  imports: [
    EurekaModule.forRootAsync({
      imports: [ConfigModule, WinstonModule],
      useFactory: async (configService: ConfigService) => ({
        service: {
          name: 'common-service-dev',
          port: +configService.get('PORT1') || +configService.get('PORT2'),
          host: configService.get('HOST'),
        },
        eureka: {
          host: configService.get('Eureka_HOST'),
          port: +configService.get('Eureka_PORT'),
          servicePath: '/eureka/apps/',
          registryFetchInterval: Eureka_Registery_Interval,
          heartbeatInterval: Eureka_Heartbeat_Interval,
          logger: winstonLogger, // 추가했지만 적용 실패
        },
      }),
      inject: [ConfigService],
    }),
  ],
  exports: [EurekaModule],
})
export class ServiceDiscoveryModule {}

이전에 미리 구현했던 winston 로그(prod환경에서는 info까지만 출력)를 유레카에 적용하고 싶었지만 구글링을 찾아보면서 몇 시간 동안 여러 방법을 시도해봤지만 적용이 되지 않았다. (레퍼런스도 많이 없었다..)


🤗 Soultion

그러던 중, nest-eureka yarn 문서에 들어가보니 아래와 같은 문구가 있었다.

nest-eureka is a NestJS module that provides an integration with eureka-js-client
('nest-eureka'는 NestJS 모듈로, 'eureka-js-client'와의 통합을 제공합니다.)

즉 nest-eureka 대신 eureka-js-client라이브러리를 사용하여 유레카를 연결할 수 있다.

  • 'nests-eureka'는 NestJS 애플리케이션을 Netflix의 Eureka 서비스 디스커버리와 통합할 수 있도록 도와주는 모듈
  • 'eureka-js-client'는 JavaScript로 작성된 Eureka 서비스 디스커버리 클라이언트 라이브러리이다. 이 모듈을 사용하면 NestJS 애플리케이션을 Eureka 서비스 디스커버리에 등록하고, 다른 서비스들과 통신할 때 Eureka를 사용하여 서비스 위치를 검색할 수 있다.

eureka-js-client 문서를 레퍼런스로 하여 기존에 구현한 EurekaModule을 eureka-js-client의 Eureka 인스턴스로 변경하였다.

// src/configs/eureka-config.ts

import { Eureka_Heartbeat_Interval, Eureka_Registery_Interval } from 'src/utils/constant';
import { Eureka } from 'eureka-js-client';

const env = process.env.NODE_ENV;

const appName = `COMMON-SERVICE${env === 'product' ? '-DEV' : ''}`;
const executeUrl = `${process.env.HOST}:${process.env.PORT1}`;

export const eurekaClient = new Eureka({
  instance: {
    app: appName,
    hostName: process.env.HOST,
    ipAddr: process.env.HOST,
    port: {
      $: process.env.PORT1,
      '@enabled': true,
    },
    vipAddress: appName,
    statusPageUrl: `http://${executeUrl}/info`,
    dataCenterInfo: {
      '@class': 'com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo',
      name: 'MyOwn',
    },
  },
  eureka: {
    host: process.env.Eureka_HOST,
    port: process.env.Eureka_PORT,
    servicePath: '/eureka/apps/',
    heartbeatInterval: Eureka_Heartbeat_Interval,
    registryFetchInterval: Eureka_Registery_Interval,
  },
});


// src/main.ts

try {
  await app.listen(port);
  if (env === 'product') {
    eurekaClient.logger.level('log');
    eurekaClient.start();
  }
  winstonLogger.log(`Server is listening on port ${port} successfully`);
} catch (e) {
  winstonLogger.error(e);
  winstonLogger.error('Failed to start the app server');
}

eureka-js-client로 변경을 결심한 이유는,
이 라이브러리로 로그 수준을 쉽게 설정할 수 있기 때문이다.

client.logger.level('debug');  // 유레카 로그 수준을 debug까지 출력
client.logger.level('log');  // 유레카 로그 수준을 info까지 출력

instance : 현재 애플리케이션의 인스턴스에 대한 설정

  • app(필수) : 1️⃣ 서비스(애플리케이션) 이름

  • hostName(필수): 2️⃣ 애플리케이션의 호스트 이름 (localhost 아니면 도메인 이름, ip주소 적어도 됨)

  • ipAddr(필수): 애플리케이션 IP 주소

  • port(필수): 애플리케이션의 포트 번호

    • @enabled: 해당 포트가 활성화되어있는가
  • vipAddress(필수): 가상 IP 주소로 애플리케이션을 식별, 일반적으로 애플리케이션 이름과 동일

  • statusPageUrl(선택): 애플리케이션의 상태 페이지 URL

    • 2️⃣에서 URL링크를 담당
  • dataCenterInfo(필수): 애플리케이션의 데이터 센터 정보를 정의

    • MyOwn, Amazon, Netflix 등 여러가지가 올 수 있음. (사용자 정의 불가)
    • MyOwn은 기본 데이터 센터 이름

eureka : Eureka 서버에 대한 설정

  • host(필수): 유레카 서버의 호스트 주소(IP주소, 도메인 등)

  • port(필수): 유레카 서버의 포트 번호

  • servicePath(필수): 유레카 서버에서 애플리케이션 등록을 위한 경로. 일반적으로 '/eureka/apps/'

  • heartbeatInterval(선택): 애플리케이션이 유레카 서버로부터 하트비트를 보내는 주기. 기본값은 3000 (30초). 기본값 유지하는 게 좋을 것 같음(경험담)

  • registeryFetchInterval(선택): Eureka 서버에서 등록 정보를 가져오는 주기. 기본값은 3000(30초). 기본값 유지하는 게 좋을 것 같음(경험담)

비록 winston로그에는 적용이 안되어 아쉽지만(계속 방법을 찾아보는 중..) Debug 로그가 이제는 출력되지 않아 다른 로그를 보기 편해졌다.

profile
안되어도 될 때까지
post-custom-banner

0개의 댓글