[졸프] Spring batch, 크롤링 트러블슈팅
상황
신경쓰지 못한 부분에서 에러가 나고 있었다.
실패한 레코드들을 기록하고 있었는데, 일부 기록이 되지 않았다.
120,103,crawlStep,119,2025-02-19 19:53:21.213935,2025-02-19 19:53:21.217935,2025-02-19 20:08:39.572548,COMPLETED,101,100,0,32,0,0,68,68,COMPLETED,"",2025-02-19 20:08:39.575546
batch step에서는 68개의 레코드 실패 기록이 남아있었는데
오늘 날짜로 기록된 실패 레코드가 36개밖에 없었다.
실패하며 batch에서 rollback하고, 실패 레코드도 기록되지 않으면
남아있는 레코드를 계속 다시 검색하는 무한 루프에 빠지니
꽤 큰 문제였다.
나의 Batch Reader 작동 방식은 (의미만 전달되도록 작성한 쿼리)
SELECT
FROM
WHERE crawl complete = false AND not in failed_record
돌려놓고 모니터링 하지 않은 나의 실수..
얼른 고쳐보자
원인
크롤링중에 로그를 계속 보고 있지 않아서 잡지 못했었던 것 같다.
생각보다 원인을 금방 파악할 수 있었는데,
레코드 기록 실패 -> 리스너 기록 실패
의 경우였다.
한마디로 에러 메세지가 너무 길어서 failed record를 기록하지 못하는 버그였다.
해결
processor에서 실패 -> 리스너에서 실패
이 두가지가 문제였고
하나씩 해결하면
리스너
- 간단하게 FailedRecord의 errormessage 최대 길이를 늘려줬다.
@Column(length = 1024)
private String errorMessage;
- 1024자는 안넘을것 같지만 예외처리도 추가
@Transactional(propagation = REQUIRES_NEW)
@Override
public void onProcessError(Restaurant item, Exception e) {
if (e.getMessage().length() > 1024) {
e = new Exception(e.getMessage().substring(0, 1024));
}
FailedRecord failedRecord = FailedRecord.builder()
.recordType("PROCESS")
.recordDataId(item.getRestaurantId())
.errorMessage(e.getMessage())
.build();
failedRecordRepository.save(failedRecord);
}
Processor
조금 더 근본적인 문제는 Model Mapper에 있었다.
Model Mapper에서 문제가 생기고 -> 리스너로 간 것
String to long -> 매핑 전략을 Strict로 설정해서 생긴 문제다.
매핑 전략을 바꾸는 방법도 있지만 좀더 직관적인 에러 메세지를 보고 싶었고
예기치 못하는 오류가 발생하는 것 같아서 Model Mapper를 사용하지 않도록 수정했다.
Model Mapper를 사용하지 않도록 수정하니 2가지 에러로 나뉘었다.
- For input String:
String-> long parse error
이부분은 Model Mapper 사용할때는 문제없었던 걸 보니
“1,234” 이런 숫자를 1234로 변환하는 작업을 Model Mapper에서 지원하는 것 같다.
replace로 간단하게 해결 - Cannot invoke “String.trim()” because “in” is null 에러
null -> double 변환
즉 널포인터 익셉션
1번이 String -> long이니 기록된 에러고
2번이 에러 메세지가 길어서 기록되지 않은 에러였던 것 같다.
결과
외에도 자잘한 버그를 해결하고 시도해보니
모든 레코드가 정상적으로 기록되고
성공률도 약 80%로 많이 올라갔다.
개선 후 좀더 표본을 쌓은 모습
자잘한 느낀점
결국 SQL
만능 JPA라고 생각했는데 요즘들어 아닌 것 같다.
스키마가 복잡해지고, 데이터가 점점 많아지니까
생 SQL이 그립다는 생각이 들었다.
오늘 식당 응답스펙을 변경하며 이런 생각을 했는데
이번 프로젝트에서 좋은 경험을 하는 것 같다.
특히 spring에서 지원하는 데이터베이스 접근기술을 JPA말고 사용해본적이 없는데
이 부분을 공부해봐야 할 것 같다.