💥 문제 상황
현재 진행하고 있는 프로젝트는 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라이브러리를 사용하여 유레카를 연결할 수 있다.
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
(필수): 애플리케이션의 포트 번호
vipAddress
(필수): 가상 IP 주소로 애플리케이션을 식별, 일반적으로 애플리케이션 이름과 동일
statusPageUrl
(선택): 애플리케이션의 상태 페이지 URL
dataCenterInfo
(필수): 애플리케이션의 데이터 센터 정보를 정의
eureka : Eureka 서버에 대한 설정
host
(필수): 유레카 서버의 호스트 주소(IP주소, 도메인 등)
port
(필수): 유레카 서버의 포트 번호
servicePath
(필수): 유레카 서버에서 애플리케이션 등록을 위한 경로. 일반적으로 '/eureka/apps/'
heartbeatInterval
(선택): 애플리케이션이 유레카 서버로부터 하트비트를 보내는 주기. 기본값은 3000 (30초). 기본값 유지하는 게 좋을 것 같음(경험담)
registeryFetchInterval
(선택): Eureka 서버에서 등록 정보를 가져오는 주기. 기본값은 3000(30초). 기본값 유지하는 게 좋을 것 같음(경험담)
비록 winston로그에는 적용이 안되어 아쉽지만(계속 방법을 찾아보는 중..) Debug 로그가 이제는 출력되지 않아 다른 로그를 보기 편해졌다.