주문 완료 문자가 간헐적으로 안 나갔다. 로그를 보니 한도 초과 응답이었다. 그런데 주문 쪽 하루 발송량은 한도의 절반도 안 됐다.
Table of contents
Open Table of contents
원인 — 다른 곳이 쓰고 있었다
같은 발송 업체를 쓰는 곳을 찾았다.
$ grep -rn "sms_client\|SmsClient" --include=*.php application/
네 군데였다.
주문 완료 문자
배송 시작 문자
재고 알림(관리자용)
가격 비교 사이트 순위 알림
마지막 것이 cron 으로 5분마다 돌면서 순위가 바뀌면 문자를 보내고 있었다. 순위가 자주 바뀌는 날에는 하루 수백 통이었다.
한도는 SmsClient 가 쓰는 계정 단위고 쓰는 곳은 넷이다. 한 곳이 많이 쓰면 나머지가 못 쓴다. 주문 쪽 발송량만 보고 있어서 이유를 못 찾고 있었다.
무엇이 우선인지 정했다
넷의 성격이 달랐다.
| 용도 | 못 나가면 |
|---|---|
| 주문 완료 | 고객이 확인을 못 받음 |
| 배송 시작 | 고객이 확인을 못 받음 |
| 재고 알림 | 관리자가 화면에서 볼 수 있음 |
| 순위 알림 | 다음 알림에서 알 수 있음 |
order 와 ship 은 대체 수단이 없고 stock 과 ranking 은 있다.
못 나갔을 때 대체 수단이 있는지가 기준이었다. 우선순위를 정하지 않으면 먼저 부른 쪽이 다 쓰는 구조가 그대로 남는다.
몫을 나눴다
용도별로 하루 한도를 정했다.
$quota = [
'order' => 2000,
'ship' => 2000,
'stock' => 200,
'ranking' => 300,
];
발송 전에 그날 몫을 썼는지 본다.
$used = $this->db->where('send_type', $type)
->where('DATE(send_date)', date('Y-m-d'))
->count_all_results('sms_log');
if ($used >= $quota[$type]) {
log_message('warning', "일일 한도 도달: {$type} ({$used}/{$quota[$type]})");
return false;
}
sms_log 를 세어 ranking 이 300통을 쓰면 거기서 멈추고 order 몫은 안 건드린다.
한도에 걸리면 조용히 안 나가므로 그것도 알게 했다. log_message 와 별개로 하루 한 번 사용량을 남겼다.
[문자 사용량 2014-11-30]
order 412 / 2000
ship 389 / 2000
stock 12 / 200
ranking 300 / 300 ← 한도 도달
전에는 문자가 안 나간 것을 며칠 뒤에 문의를 받고서야 알았다.
근본은 덜 보내는 것
ranking 이 매일 한도에 닿았다. 매일 닿으면 그건 몫이 부족한 것이 아니라 발송 조건이 잘못된 것이다.
실제로 그랬다. 순위가 1등 바뀌어도 문자가 나가고 있었다.
// 이전: 순위가 바뀌면
if ($newRank != $oldRank) { send(); }
// 이후: 순위 구간이 바뀌거나 5위 안에 들어오거나 나갈 때만
if (rankBand($newRank) != rankBand($oldRank)) { send(); }
rankBand 로 구간을 비교하니 하루 300통이 8통이 됐다.
몫을 나누는 것보다 애초에 덜 보내는 쪽이 나았다. 몫은 문제가 퍼지는 것을 막는 장치이고 근본은 발송 조건이었다.
업체가 주는 한도가 실제로 얼마인지도 확인했다. 문서에는 있는데 계약에 따라 다를 수 있어서 물어봤고 SmsClient 응답도 같이 봤다.
{"code":"200","remain":3218}
응답에서도 남은 양을 주고 있었다. remain 을 로그에 남기니 남은 양이 어떻게 줄어드는지 보였고 우리 계산과 업체 계산이 다른 것도 이걸로 발견했다.
실패한 발송도 한도를 먹고 있었다. 번호가 틀려서 실패한 것도 세진다.
정리
- 같은 한도를 여러 곳이 쓰면 한 곳이 다 쓸 수 있다
- 한 용도의 발송량만 보면 이유를 못 찾는다
grep -rn으로 그 계정을 쓰는 곳을 전부 찾는다- 못 나갔을 때 대체 수단이 있는지로 우선순위를 정한다
- 용도별로 몫을 나누면 한 곳이 다른 곳 몫을 안 먹는다
- 사용량을 매일 남긴다. 매일 한도에 닿는 용도는 몫이 아니라 조건이 문제다
- 몫을 나누는 것은 퍼지는 것을 막는 장치다. 근본은 덜 보내는 것이다
- 상대가 주는
remain을 로그에 남긴다. 우리 계산과 다를 수 있다 - 실패한 발송도 한도를 먹는다