피드 하나가 열나흘 죽어 있었다. 기록에 남은 건 "2곳 실패"라는 숫자뿐이었다
실패한 피드의 이름은 남겼는데 이유를 안 남겼다. 이유를 남긴 첫날 아침에 원인이 나왔고, 그중 하나는 성공 계열 응답 코드로 오고 있었다.
이 글은 뉴스 요약이 아니라 이 사이트를 만들면서 있었던 일에 대한 기록입니다.
매일 아침 08:00에 사람 없이 도는 파이프라인이 뉴스 피드 12곳을 읽는다. 그중 하나가 8월 9일부터 한 건도 못 들어오고 있었는데, 8월 21일까지 알아채지 못했다. 감시가 없어서가 아니다. 매일 "피드 2곳 실패"라고 적고 있었다.
숫자는 맞았다. 그 숫자로 할 수 있는 일이 없었을 뿐이다.
처음엔 피드가 깨진 줄 알았다
피드를 못 읽으면 이런 줄이 찍혔다.
[WARN] Hacker News (AI) 수집 실패: 파싱 실패: <unknown>:7:2: mismatched tag
"파싱 실패"에 "7번째 줄 태그가 안 맞는다"까지 붙으니 피드 XML이 깨진 것처럼 읽힌다. 그래서 고칠 곳을 피드 쪽에서 찾게 된다.
실제로 벌어진 일은 달랐다. 그 서버가 502를 내면서 nginx 오류 페이지를 줬고, 우리는 그 HTML을 XML로 파싱하다 7번째 줄에서 넘어진 것뿐이었다. 피드는 멀쩡했다. 서버가 죽어 있었고 우리가 할 일은 없었다.
이름을 남겼다. 그래도 모자랐다
8월 20일에 실패한 피드의 이름을 그날 기록에 남기게 고쳤다. 그전에는 "3곳 실패" 같은 숫자만 남아서, 며칠 뒤에 돌아보면 어느 피드였는지 알 방법이 없었다.
다음 날 아침 이름이 찍혔다. MarkTechPost, Hacker News. 그리고 거기서 멈췄다. 이름만으로는 다음에 무엇을 할지가 안 나온다. 사이트가 우리를 막은 것과 상대 서버가 아픈 것은 완전히 다른 문제인데, 이름은 그 둘을 가르지 않는다.
이 저장소에는 "닿아야 할 도메인에 실패하면 네트워크 허용 목록부터 본다"는 규칙이 있다. 전에 두 번 그 문제였기 때문이다. 목록을 봤고, 두 호스트 다 들어 있었다.
| 개발자 PC | 무인 실행 환경 | |
|---|---|---|
| MarkTechPost | HTTP 200 · 정상 RSS | 못 읽음 |
| Hacker News (AI) | HTTP 200 · 정상 XML | 못 읽음 |
같은 URL이 한쪽에서는 열리고 다른 쪽에서는 안 열린다. 여기서 더 나아가려면 실패한 쪽이 정확히 무엇을 받았는지가 필요했다. 그 값은 화면에 한 번 찍히고 실행이 끝나면 사라졌다.
그래서 이유를 남기게 했다
고친 것은 크지 않다. 예외 메시지를 버리지 않고 그날 기록에 같이 적게 했다. 상태 코드가 있으면 그것부터 말하고, 응답은 왔는데 내용이 XML이 아니면 그 사실을 말하고, 둘 다 아니면 그때는 진짜 형식 문제일 수 있으니 원래 예외를 그대로 보여준다.
여기서 하마터면 놓칠 뻔한 것이 있다. 처음에는 "상태 코드가 400 이상이면 그걸 보여준다"만 만들었다. 그대로 뒀으면 다음 날 아침에 절반은 못 잡았다.
다음 날 아침, 두 피드는 서로 다른 이유였다
MarkTechPost 피드가 아닌 응답을 받았습니다 (content-type: text/html, HTTP 202)
Hacker News (AI) HTTP 502 - 피드 대신 오류 응답을 받았습니다, content-type: text/html
MarkTechPost는 클라우드플레어 뒤에 있고, 데이터센터에서 오는 요청에 사람 확인용 페이지를 준다. 그 페이지가 202로 온다. 우리가 요청한 것은 RSS인데 돌아온 것은 사람이 읽을 HTML이었고, 응답 코드로만 보면 아무 문제가 없었다.
Hacker News는 우리 문제가 아니었다. 그쪽 서버가 힘들어하는 중이고 지나면 돌아온다. 실제로 집에서 다시 열어봤을 때도 타임아웃이 났다.
열나흘의 값
그동안 브리핑이 멈춘 적은 없다. 피드 하나가 죽어도 나머지가 돌게 만들어 뒀기 때문이다. 대신 조용히 좁아졌다. 12곳이 아니라 11곳으로 읽으면 그만큼 한 매체가 가져가는 몫이 커진다. 8월 21일에는 열 자리를 네 매체가 채웠다.
더 비싼 값은 다른 데 있었다. 매일 "2곳 실패"가 뜨는데 손댈 수가 없으면, 그 줄은 읽어도 아무것도 안 하는 줄이 된다. 그 상태로 며칠 지나면 진짜 새 실패가 떠도 눈에 안 들어온다. 열나흘이 걸린 이유가 정확히 그거다.
고친 뒤
8월 23일에 MarkTechPost를 뺐다. 클라우드플레어 확인 페이지는 데이터센터에서 우회할 방법이 없다. 대신 후보 31곳을 하나씩 열어보고 골랐다. 거른 기준은 넷이다.
- 클라우드플레어 뒤에 있는가. 방금 우리를 죽인 것이 그거라 같은 위험을 다시 사지 않는다
- 피드 이름이 아니라 실제 제목이 AI인가. "AI" 섹션인데 "TV를 모니터로 쓰는 법"이 오는 곳이 여럿이었다
- 기사 원문을 읽을 수 있는가. 제목만 오면 자리만 먹는다
- 발행량이 받쳐주는가
| 후보 | 클라우드플레어 | 주당 | 원문 |
|---|---|---|---|
| The Decoder | 없음 | 10건 | 읽힘 |
| SiliconANGLE AI | 없음 | 30건 | 읽힘 |
| Hugging Face Blog | 없음 | 5건 | 읽힘 |
| The Register AI/ML | 없음 | 4건 | 읽힘 |
| Simon Willison · Latent Space · AI Business | 있음 | - | - |
넷이 다 통과한 곳 중에서 The Decoder를 골랐다. 주 10건이 전부 AI 주제고 연구 해설 비중이 높아, 빠진 자리와 성격이 겹친다.
남는 것
기록은 세 번 자랐다. 숫자에서 이름으로, 이름에서 이유로. 앞의 둘만 있을 때는 매일 적어도 아무 일이 일어나지 않았다. "무엇이 실패했나"까지만 적으면 읽고 넘어가게 되고, "그래서 무엇을 해야 하나"가 붙어야 손이 움직인다.
이번 건은 202로 왔다. 다음엔 200으로 올지도 모른다. 그래서 상태 코드 말고 내용을 보게 해뒀다.