-
[Intern] 캐싱 및 redis 사용 검색 속도 향상 적용Intern/Project 2024. 12. 12. 21:15
✏ 근무 내용
- 최종 코드 구현 확인
- 캐싱 및 redis 사용해 cctp api 사용해 조회시 검색 속도 향상 적용
⭐근무 결과
- 메소드 별 실행 시간 측정
async getTransactionInfoFromRange(txHash: string) { const start = Date.now(); // 시작 시간 기록 const url = '<https://usdc.range.org/usdc/api/transfers>'; const { data } = await firstValueFrom( this.httpService.get(url, { params: { txHash, txnType: 'MAINNET', limit: 1, direction: 'first', source: 'ethereum,base,arbitrum', // 소스 네트워크 destination: 'ethereum,base,arbitrum', // 목적지 네트워크 status: '', min_usd: '', max_usd: '' } }).pipe( catchError((error: AxiosError) => { const errMsg = "Failed to fetch transaction info from Range API\\nMessage: " + error.message; console.error(errMsg); throw new CCTPapiError(errMsg); }) ) ); const duration = Date.now() - start; // 실행 시간 계산 console.log(`getTransactionInfoFromRange 실행 시간: ${duration}ms`); return data.resources[0]; }
getTransactionInfoFromRange 실행 시간: 2874ms
⇒ 속도 개선 방법 : 캐싱을 사용해 검색 성능 향상 시킴
//-- api.service.ts 파일 import NodeCache from 'node-cache'; import * as http from 'http'; private cache: NodeCache; private httpAgent: http.Agent; constructor( private readonly httpService: HttpService, private readonly methodMapperService: MethodMapperService ) { // 캐싱을 위한 NodeCache 인스턴스 초기화 this.cache = new NodeCache({ stdTTL: 300 }); // TTL 5분 // HTTP Keep-Alive를 위한 에이전트 설정 this.httpAgent = new http.Agent({ keepAlive: true }); } //... 생략 기존 코드와 동일
async getTransactionInfoFromRange(txHash: string) { const start = Date.now(); // 시작 시간 기록 // 캐싱된 데이터 확인 const cachedData = this.cache.get(txHash); if (cachedData) { console.log("캐시 사용"); console.log(`getTransactionInfoFromRange 실행 시간 (캐시): ${Date.now() - start}ms`); return cachedData; } const url = '<https://usdc.range.org/usdc/api/transfers>'; try { // HTTP 요청 시작 const { data } = await firstValueFrom( this.httpService.get(url, { params: { txHash, txnType: 'MAINNET', limit: 1, direction: 'first', source: 'ethereum,base,arbitrum', destination: 'ethereum,base,arbitrum', status: '', min_usd: '', max_usd: '' }, headers: { 'Accept-Encoding': 'gzip, deflate, br', // 데이터 압축 요청 }, timeout: 3000, // 요청 타임아웃 설정 (3초) httpAgent: this.httpAgent, // Keep-Alive 설정 }).pipe( // 에러 처리 catchError((error: AxiosError) => { const errMsg = "Failed to fetch transaction info from Range API\\nMessage: " + error.message; console.error(errMsg); throw new Error(errMsg); }) ) ); // 응답 데이터 캐싱 this.cache.set(txHash, data.resources[0]); console.log(`getTransactionInfoFromRange 실행 시간: ${Date.now() - start}ms`); return data.resources[0]; } catch (error) { console.error("getTransactionInfoFromRange 에러:", error.message); console.log(`getTransactionInfoFromRange 실패 시간: ${Date.now() - start}ms`); throw error; } }
- 캐싱(NodeCache):
- 동일한 txHash 요청에 대해 캐싱된 데이터를 반환하여 불필요한 HTTP 요청 방지.
- TTL(Time To Live)을 5분으로 설정.
- HTTP Keep-Alive:
- 지속적인 연결을 유지하여 네트워크 지연 감소.
- 압축 활성화:
- Accept-Encoding 헤더를 추가하여 Gzip, Brotli 등의 압축 데이터 요청.
- 타임아웃 설정:
- timeout: 3000으로 타임아웃을 설정하여 비정상적인 대기 시간 방지.
- 성능 로그 추가:
- 실행 시간을 기록하여 성능을 지속적으로 모니터링.
결과는 아래와 같다.
getTransactionInfoFromRange 실행 시간: 2113ms
기대 효과
- 캐싱 적용으로 동일한 요청에 대해 실행 시간이 획기적으로 단축.
- HTTP Keep-Alive로 네트워크 연결 지연 최소화.
- 데이터 압축과 타임아웃 설정으로 요청 효율성 및 안정성 향상.
더 속도를 올릴 수 없을까 해서 Redis를 사용해보기로 했다.
import { createClient } from 'redis'; //... private redisClient: any; constructor( private readonly httpService: HttpService, private readonly methodMapperService: MethodMapperService ) { // 캐싱을 위한 NodeCache 인스턴스 초기화 this.cache = new NodeCache({ stdTTL: 300 }); // TTL 5분 // HTTP Keep-Alive를 위한 에이전트 설정 this.httpAgent = new http.Agent({ keepAlive: true }); // Redis 클라이언트 초기화 this.redisClient = createClient(); this.redisClient.connect().catch((err) => { console.error("Redis 연결 실패:", err); }); }
Redis 서버 실행후 프로젝트 실행시켜야 함
redis-server
async getTransactionInfoFromRange(txHash: string) { const start = Date.now(); // 시작 시간 기록 // Redis 캐시 확인 const redisCachedData = await this.redisClient.get(txHash); if (redisCachedData) { console.log("Redis 캐시 사용"); console.log(`getTransactionInfoFromRange 실행 시간 (Redis 캐시): ${Date.now() - start}ms`); return JSON.parse(redisCachedData); } // NodeCache 확인 const nodeCachedData = this.cache.get(txHash); if (nodeCachedData) { console.log("NodeCache 캐시 사용"); console.log(`getTransactionInfoFromRange 실행 시간 (NodeCache): ${Date.now() - start}ms`); return nodeCachedData; } // 캐싱된 데이터 확인 const cachedData = this.cache.get(txHash); if (cachedData) { console.log("캐시 사용"); console.log(`getTransactionInfoFromRange 실행 시간 (캐시): ${Date.now() - start}ms`); return cachedData; } const url = '<https://usdc.range.org/usdc/api/transfers>'; try { // HTTP 요청 시작 const { data } = await firstValueFrom( this.httpService.get(url, { params: { txHash, txnType: 'MAINNET', limit: 1, direction: 'first', source: 'ethereum,base,arbitrum', destination: 'ethereum,base,arbitrum', status: '', min_usd: '', max_usd: '' }, headers: { 'Accept-Encoding': 'gzip, deflate, br', // 데이터 압축 요청 }, timeout: 3000, // 요청 타임아웃 설정 (3초) httpAgent: this.httpAgent, // Keep-Alive 설정 }).pipe( // 에러 처리 catchError((error: AxiosError) => { const errMsg = "Failed to fetch transaction info from Range API\\nMessage: " + error.message; console.error(errMsg); throw new Error(errMsg); }) ) ); // 응답 데이터 Redis와 NodeCache에 캐싱 const cachedValue = JSON.stringify(data.resources[0]); await this.redisClient.set(txHash, cachedValue, { EX: 300 }); // Redis TTL 5분 this.cache.set(txHash, data.resources[0]); // NodeCache 저장 console.log(`getTransactionInfoFromRange 실행 시간: ${Date.now() - start}ms`); return data.resources[0]; } catch (error) { console.error("getTransactionInfoFromRange 에러:", error.message); console.log(`getTransactionInfoFromRange 실패 시간: ${Date.now() - start}ms`); throw error; } }
Redis 캐시 사용 getTransactionInfoFromRange 실행 시간 (Redis 캐시): 5ms
추가된 최적화 내용:
- Redis 캐싱:
- Redis를 활용하여 데이터를 저장 및 검색하며, TTL을 설정해 주기적으로 갱신.
- NodeCache와 함께 사용하여 Redis가 사용 불가능할 경우 로컬 캐싱도 활용 가능.
- 병렬 처리:
- getMultipleTransactions 메서드 추가로 여러 트랜잭션을 동시에 처리.
- 캐싱 계층 구조:
- Redis > NodeCache 순으로 데이터 조회를 시도하여 캐싱 효율성을 극대화.
기대 효과:
- Redis 캐싱과 Keep-Alive 설정으로 네트워크 및 데이터 처리 속도 개선.
- 병렬 처리를 통한 다중 요청 효율화.
Redis 캐시를 사용한 성능 개선의 주요 포인트
- 원래 소요 시간: 2874ms
- API 호출, 네트워크 지연, 데이터 처리 등이 포함된 시간.
- 이 과정이 생략되지 않고 실행되면 오래 걸릴 수밖에 없습니다.
- 개선된 소요 시간: 5ms
- Redis 캐시에서 데이터를 가져오므로 네트워크 요청 및 데이터 처리가 생략됨.
- 메모리에서 읽기만 수행하므로 매우 빠르게 결과를 반환.
어떻게 개선되었는지 정리
- Redis 캐싱 적용:
- 동일한 txHash에 대해 한 번만 API 호출.
- 이후 요청은 Redis에서 바로 데이터를 가져와 반환.
- 네트워크 지연 제거:
- API 호출 과정이 제거되어 네트워크와 서버 응답 시간이 사라짐.
- 데이터 처리 시간 단축:
- API로 받은 데이터를 정리하는 단계가 생략됨.
반응형'Intern > Project' 카테고리의 다른 글
[Intern] Squid router API 데이터 분석 (0) 2024.12.17 [Intern] Squid 브리지 api 연동 및 데이터 확인 (0) 2024.12.13 [Intern] Source 트랜잭션 value 값 확인 및 검증 (0) 2024.12.11 [Intern] Range api 트랜잭션 반환 데이터 확인 / 해시값 조회시 출발 및 도착 체인 정보 반환하도록 구현 (0) 2024.12.11 [Intern] Moralis api 데이터 검증 / 대체 api 찾기 (0) 2024.12.09