Node.js 를 이용 하여 파일 순환 복 사 를 어떻게 실현 합 니까?

머리말
이번에 Node.js 프로젝트 를 작성 할 때 로그 모듈 을 사 용 했 는데 작은 문제 가 발생 했 습 니 다.
이것 은 정시 에 자동화 작업 을 설정 할 수 있 는 프로젝트 이기 때문에 출력 정보 가 계속 증가 하고 로그 파일 이 시간 에 따라 계속 커진다 는 것 을 의미한다.로그 파일 크기 를 제어 하지 않 으 면 서버 의 디스크 가 조만간 가득 찰 것 입 니 다.그래서 파일 크기 를 제한 하 는 것 이 필요 합 니 다.
가장 이상 적 인 제어 방식 은 파일 크기 가 제한 을 초과 할 때 가장 먼저 기 록 된 데 이 터 를 지 우 는 것 이다.FIFO 와 유사 한 대기 열 입 니 다.

#        
- 1 xxx
 ......
 100 abc
#         
+ 101 xxxx
log4js 의 file rolling
기록 로그 라 고 하면 많은 Node.js 개발 자 들 이 log4js 를 찾 을 것 입 니 다.먼저 log4js 가 이 문 제 를 어떻게 처리 하 는 지 보 겠 습 니 다.
log4js 는 많은 appenders(로 그 를 기록 하 는 매개체 로 이해 할 수 있 음)로 나 뉘 는데 file rolling 기능 은 함수 로 설정 할 수 있 습 니 다.
file rolling 기능 은 날짜 와 파일 크기 두 가지 방식 이 있 습 니 다.
파일 크기 를 조절 하려 면 후 자 를 선택해 야 합 니 다.
이 기능 이 우리 의 요 구 를 만족 시 키 는 지 시험 하기 위해 서 순환 코드 를 써 서 로 그 를 씁 니 다.

const log4js = require('log4js')
//   log4js
log4js.configure({
 appenders: {
 everything: {
 type: 'file',
 filename: 'a.log',
 maxLogSize: 1000,
 backups: 0
 },
 },
 categories: {
 default: {
 appenders: ['everything'],
 level: 'debug'
 }
 }
});
const log = log4js.getLogger();
for (let i = 0; i < 41; i++) {
 const str = i.toString().padStart(6, '000000');
 log.debug(str);
}
실행 후 두 개의 파일 a.log 와 a.log.1 을 생 성 합 니 다.
그 중에서 a.log.1 은 20 줄 의 데이터 가 있 고 실제 크기 는 1kb 이 며 a.log 는 1 줄 의 데이터 만 있다.
파일 크기 를 확실히 제 어 했 지만 두 가지 문 제 를 가 져 올 수 있 습 니 다.
  • 백업 파일 을 추가 로 만 들 고 디스크 공간 을 차지 하면 파일 제한 을 초과 합 니 다.
  • 로그 파일 내용 의 크기 가 바 뀌 었 습 니 다.로 그 를 조회 할 때 백업 파일 과 함께 조회 해 야 할 수도 있 습 니 다(예 를 들 어 위의 상황 로그 파일 은 1 줄 데이터 만 있 습 니 다).
  • log4js 의 실현 논 리 는 다음 과 같 을 것 으로 추정 된다.
  • 로그 파일 이 제 한 된 크기 에 이 르 렀 는 지 확인 하고 백업 파일 을 삭제 하지 않 으 면 로그 파일 을 계속 기록 합 니 다.
  • 로그 파일 의 이름 을 백업 파일 로 바 꿉 니 다.
  • 이것 은 분명히 수 요 를 완전히 만족 시 킬 수 없다.
    문자열 바 꾸 기?
    메모리 에서 순환 복사 작업 을 완료 하려 면 문자열 이나 Buffer 를 사용 하면 됩 니 다.
  • 문자열/Buffer 길 이 를 추가 하고 크기 를 초과 하면 캡 처 합 니 다.
  • 로그 파일 을 기록 하고 덮어 씁 니 다.
  • 그러나 매우 큰 문제 가 하나 있다.메모 리 를 점용 하 는 것 이다.
    예 를 들 어 파일 크기 를 1GB 로 제한 하고 로그 파일 10 개 를 동시에 기록 하면 최소 10GB 메모리 공간 을 차지 합 니 다!
    메모리 가 디스크 공간 보다 더 귀중 하 다.이렇게 뚜렷 한 성능 문 제 는 분명히 가장 좋 은 해결 방법 이 아니다.
    file roll
    수요 에 따라 실현 절 차 를 두 단계 로 나 눌 수 있다.
  • 파일 끝 에 최신 데 이 터 를 추가 합 니 다.(Node.js 의 fs 모듈 은 해당 함수 가 있 습 니 다)
  • 파일 삭제 시작 이 제한 부분 을 초과 합 니 다.(Node.js 응답 함수 없 음
  • 이 두 단 계 는 우선 순 위 를 가리 지 않 지만 Node.js 는 파일 의 시작 부분 을 삭제 하기 위해 API 를 제공 하지 않 고 파일 이 지정 한 위 치 를 수정 하 는 함수 만 제공 합 니 다.
    파일 의 시작 부분 내용 을 삭제 할 수 없 으 니 생각 을 바 꾸 어 파일 의 끝 부분 만 유지 합 니 다(크기 제한 을 초과 하지 않 습 니 다).
    뭐?이것 은 같은 뜻 이 아 닙 니까?
    약간 차이 가 있어 요.
    삭 제 는 기 존 파일 에서 이 루어 지 는 작업 이 며,보존 내용 은 임시 파일 을 통 해 이 루어 집 니 다.
    그래서 생각 은:
  • 임시 파일 을 만 듭 니 다.임시 파일 의 내용 은 로그 파일 에서 나 옵 니 다.
  • 임시 파일 에 데 이 터 를 추가 합 니 다.
  • 임시 파일 에서 파일 크기 제한 에 부합 되 는 내용 을 뒤로(오프셋 형식 으로)읽 고 로그 파일 로 복사 하여 덮어 씁 니 다.
  • 추가 디스크 공간 을 차지 하지 않 기 위해 쓰기 작업 이 완료 되면 임시 파일 을 삭제 합 니 다.
  • 이렇게 하면 로그 4js 처럼 로그 파일 의 내용 이 완전 하지 않 고 추가 임시 파일 도 보존 하지 않 습 니 다.하지만 IO 에 대한 조작 이 늘 어 납 니 다.
    쓰기 동작 에 대해 tail 명령 을 사용 하여 실현 할 수 있 습 니 다.최종 구현 코드 는 다음 과 같 습 니 다.
    
    private write(name: string, buf?: Buffer | string) {
     // append buf to tmp file
     const tmpName = name.replace(/(.*\/)(.*$)/, '$1_\.$2\.tmp');
     if (!existsSync(tmpName)) {
     copyFileSync(name, tmpName);
     }
     buf && appendFileSync(tmpName, buf);
     // if busy, wait
     if (this.stream && this.stream.readable) {
     this.needUpdateLogFile[name] = true;
     } else {
     try {
      execSync(`tail -c ${limit} ${tmpName} > ${name}`);
      try {
      if (this.needUpdateLogFile[name]) {
       this.needUpdateLogFile[name] = false;
       this.write(name);
      } else {
       existsSync(tmpName) && unlinkSync(tmpName);
      }
      } catch (e) {
      console.error(e);
      }
     } catch (e) {
      console.error(e);
     }
     }
    }
    총결산
    이 기능 을 완성 하면 두 가지 깨 달 음 이 있다.
  • 양 적 변 화 는 질 적 변 화 를 일으킨다.데이터 양 이 커지 면 많은 간단 한 처리 방식 을 사용 할 수 없다.예 를 들 어 파일 을 쓰 는 것 이다.만약 에 writeFile 을 직접 사용 하면 대량의 메모 리 를 차지 하고 심지어 메모리 가 부족 할 수도 있다.그래서 적당 한 방식 으로 나 누 려 면 나 누 는 과정 에서 여러 가지 문제 에 부 딪 힐 수 있다.예 를 들 어 본 고 에서 문서 내용 을 캡 처 하 는 요구
  • 힘 을 빌 릴 줄 안다.군자 성 은 다 르 지 않 고 물건 에 가 짜 를 잘 둔다.한 점 에서 조작 을 완성 할 수 없 을 때 외부 조건 을 통 해 이 루어 질 수 있다.예 를 들 어 본 논문 에서 임시 파일 을 사용 하여 데이터 내용 을 저장 할 수 있다.
  • 자,이상 이 이 글 의 모든 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가 치 를 가지 기 를 바 랍 니 다.여러분 의 저희 에 대한 지지 에 감 사 드 립 니 다.

    좋은 웹페이지 즐겨찾기