특정 쇼핑몰이나 음식점에서 카카오톡 알림톡이나 친구톡을 종종 받는다. 쇼핑몰에 회원 가입, 결제했을 때 받는 알림톡이라던가, 특정 업체를 카카오톡에서 친구 추가했을 때 이벤트 알림을 받는 친구톡이라던가 일상 생활에서 다양하게 사용되고 있다.
이번에 알림톡 Agent가 변경이 필요해서 신규 개발을 하게 되어 정리를 해보고자 한다. 아래 이미지에서 알림톡 요청 DB를 Polling 하는 부분이다.
[주의사항]
→ 이벤트 발송 예약은 대용량일 경우가 많아 대용량 전송 로직 필요
알림톡 서비스를 사용하는 가맹점 중, 이벤트 발송을 하는 가맹점들은 대용량 메시지를 예약하는 경우가 있다.
보통 가입 회원에게 일괄 안내 메시지(이벤트 안내, 배송 지연, 휴무 예정)를 보내게 되는데, 가맹점 중 200만 이상의 회원이 있는 가맹점의 경우 대량 메시지를 일괄로 전송해야 할 때 가 있다.
한 건 전송하는 데 대략 0.8s로 계산해서 전송할 메시지가 5만건이라 가정했을 때, 0일 11시간 6분 40초가 소요된다…
그래서 병렬 처리하는 로직을 추가했다.
- 일반(즉시 발송), 이벤트 용 발송(대용량 발송)의 DB와 알림톡 Agent 서버 분리
- 메시지 전송 병렬 처리
DoWorkAsync를 TimerCallback으로 등록해서 일정 주기마다 실행 되도록 한다.
private async Task DoWorkAsync(object state)
{
// 작업 중 타이머 중지
Stop();
try
{
Util.WriteLog("[발송 대상 메세지 확인]", "");
// 발송대상 메세지 조회
List<Bm_Request> messageList= bmService.getBizMessage();
Util.WriteLog("[발송 대상 메세지]", messageList.Count.ToString() + "건");
// DB 실패 리스트 재시도
retryWork();
if (messageList.Count > 0)
{
// 발송대상 메세지를 Queue에 저장
var temp = messageList.ToDictionary(x => x.MSG_ID, x => x);
//동시에 실행되는 스레드의 최대 수 10으로 제어
Parallel.ForEach(temp, new ParallelOptions { MaxDegreeOfParallelism = 10 }, bmRequest =>
{
Util.WriteLog("[메세지 발송]", bmRequest.Key);
try
{
// 카카오톡 api 호출 서비스 비동기 처리
var result = Task.Run(async () => await bmService.postbizApi(bmRequest.Value)).Result;
Util.WriteLog("[메세지 발송 완료]", result.bm_request_result.MSG_ID);
// 발송 메시지 큐에서 삭제
dicMessageQueue.TryRemove(result.bm_request_result.MSG_ID, out _);
//정상처리 안됬을 경우 재시도용 실패 메시지에 추가
if (!result.result)
failMessage.TryAdd(result.bm_request_result.MSG_ID, result.bm_request_result);
}
catch (Exception ex)
{
// 예외 처리 및 로그 기록
Util.WriteLog("[메세지 발송 실패]", $"{bmRequest.Key}: {ex.Message}");
}
});
}
}
catch (Exception ex)
{
Util.WriteLog(" 작업 중 시스템 에러", ex.Message);
}
finally
{
// 작업 완료 후 타이머 시작
Start();
}
}
병렬 처리를 해서 5만건의 데이터 전송 테스트를 진행했을 때 ,
[실행 중]
- 평균 CPU 10~20%, 최대 CPU 33% / 메모리 총 (91%)
[실행 종료]
- 평균 CPU 5%이내
[실수행 시간]
- 대략 19분
대략 19분이라는 시간이 나왔다. 다른 방법도 시도해서 시간을 줄여봐야겠다.
300x250