Foundry
웹 크롤러 설계
심화
핵심

예의가 처리량을 정한다

한 줄에 섞으면 규칙을 지킬 수 없다

앞 단계에서 최소 386개 호스트를 동시에 다뤄야 한다는 결론이 나왔습니다. 그것을 어떻게 만드는지가 이 절입니다.

한 줄에 섞으면 규칙을 지킬 수 없다

주소를 한 줄에 섞으면 같은 호스트가 연달아 나오고 호스트별로 나누면 간격이 지켜진다 한 줄에 섞으면 가1 가2 가3 나1 가4 가 호스트가 연달아 나온다 큰 사이트의 주소가 앞을 다 차지한다 호스트마다 줄을 따로 세우면 가 큐 나 큐 다 큐 일꾼 1 일꾼 2 일꾼 3 한 큐는 한 일꾼만 본다 그 일꾼이 간격을 지킨다 큐 수가 곧 처리량이다 큐를 다 쓰지 못하면 일꾼이 놀고 예산이 남는다

방문할 주소를 한 줄에 넣으면 같은 호스트의 주소가 연달아 나옵니다. 큰 사이트에서 나온 주소가 목록의 대부분을 차지하기 때문입니다.

그러면 일꾼들이 같은 호스트를 동시에 두드립니다. 예의 규칙을 지키려면 매번 "이 호스트를 마지막으로 언제 봤나" 를 확인해야 하고, 그 확인이 모든 일꾼 사이에서 공유돼야 합니다.

호스트마다 줄을 따로 세운다

호스트별로 큐를 만들고 한 큐는 한 일꾼만 봅니다. 그러면 그 일꾼이 자기 큐의 간격만 지키면 규칙이 지켜집니다. 일꾼 사이에 공유할 상태가 없어집니다.

호스트 큐를 일꾼에게 배정한다
일꾼은 자기 큐에서 하나 가져와 처리하고 1초 기다린다

규칙 확인이 지역 문제가 되는 것이 이 구조의 값입니다. 앞의 아키타입들에서 반복된 방식이고, 여기서는 호스트가 그 단위입니다.

큐 수가 곧 처리량이다

일꾼 하나가 한 호스트에서 초당 한 페이지를 가져오므로, 동시에 살아 있는 큐 수가 초당 페이지 수입니다.

살아 있는 큐초당 페이지
100개100
386개386. 예산을 채운다
1,000개1,000. 예산보다 많다

큐가 부족하면 일꾼이 놀고 예산이 남습니다. 그래서 주소 목록이 여러 호스트에 고르게 퍼져 있어야 합니다. 한 호스트의 주소만 많이 들고 있으면 처리량이 나오지 않습니다.

큰 사이트가 목록을 채운다

주소는 대형 사이트에서 압도적으로 많이 나옵니다. 그대로 두면 목록이 소수 호스트로 채워지고, 큐 수가 줄어 처리량이 떨어집니다.

대응내용
호스트별로 목록 길이에 상한을 둔다한 사이트가 목록을 독점하지 못한다
새 호스트 발견을 우선한다큐 수를 늘려 처리량을 지킨다

대형 사이트를 다 가져오려는 것과 예산을 채우는 것이 충돌합니다. 요구사항이 넓은 범위를 원한다면 상한을 두는 편이 맞습니다.

간격을 호스트마다 다르게 준다

초당 한 번은 기본값입니다. 큰 사이트는 더 자주 받아도 괜찮고, 작은 사이트는 더 느리게 해야 할 수 있습니다.

상대가 알려 준 간격이 있으면 그것을 따른다
응답이 느려지거나 거절이 오면 간격을 늘린다

상대의 신호에 반응하는 것이 규칙을 숫자로 지키는 것보다 중요합니다. 상대가 힘들어하는데 규칙만 지키고 계속 두드리면 결국 차단됩니다.

면접에서 이렇게 나옵니다

Q.예의 규칙을 어떻게 지키시겠습니까

호스트별로 큐를 만들고 한 큐는 한 일꾼만 봅니다.

주소를 한 줄에 섞으면 같은 호스트가 연달아 나오고, 일꾼들이 같은 호스트를 동시에 두드립니다. 그것을 막으려면 "이 호스트를 마지막으로 언제 봤나" 를 모든 일꾼이 공유해야 합니다.

호스트 큐를 일꾼에게 배정한다
일꾼은 자기 큐에서 하나 가져와 처리하고 기다린다

규칙 확인이 지역 문제가 되는 것이 이 구조의 값입니다. 일꾼 사이에 공유할 상태가 없어집니다.

흔한 실수: 공유 저장소에 마지막 방문 시각을 두고 매번 확인하는 것. 동작하지만 모든 가져오기에 왕복이 붙고 그 저장소가 병목이 됩니다. 큐를 나누면 그 왕복이 사라집니다.

Q.큐 수와 처리량의 관계는 무엇인가요

동시에 살아 있는 큐 수가 곧 초당 페이지 수입니다.

일꾼 하나가 한 호스트에서 초당 한 페이지를 가져오기 때문입니다.

살아 있는 큐초당 페이지
100개100
386개예산을 채운다

큐가 부족하면 일꾼이 놀고 예산이 남습니다. 그래서 주소 목록이 여러 호스트에 고르게 퍼져 있어야 합니다.

흔한 실수: 처리량이 부족할 때 일꾼을 늘리는 것. 큐가 386개인데 일꾼을 1,000개로 늘려도 초당 386이 상한입니다. 늘려야 하는 것은 다루는 호스트 수입니다.

Q.대형 사이트가 목록을 채우면 어떻게 하나요

호스트별 목록 길이에 상한을 두고 새 호스트 발견을 우선합니다.

주소는 대형 사이트에서 압도적으로 많이 나옵니다. 그대로 두면 목록이 소수 호스트로 채워지고 큐 수가 줄어 처리량이 떨어집니다.

대응내용
호스트별 상한한 사이트가 목록을 독점하지 못한다
새 호스트 우선큐 수를 늘려 처리량을 지킨다

대형 사이트를 다 가져오려는 것과 예산을 채우는 것이 충돌합니다.

흔한 실수: 상한을 두지 않고 목록이 커지는 것만 관리하는 것. 목록 크기를 견뎌도 한 호스트에 몰린 목록은 처리량으로 바뀌지 않습니다. 얼마나 들고 있는지와 얼마나 쓸 수 있는지는 다릅니다.

Q.가져오기 간격을 어떻게 정하시겠습니까

기본값을 두고 상대의 신호에 반응합니다.

초당 한 번은 기본값이고, 상황에 따라 조절해야 합니다.

상대가 알려 준 간격이 있으면 그것을 따른다
응답이 느려지거나 거절이 오면 간격을 늘린다

상대의 신호에 반응하는 것이 숫자를 지키는 것보다 중요합니다. 상대가 힘들어하는데 규칙만 지키고 계속 두드리면 결국 차단됩니다.

반대로 큰 사이트는 더 자주 받아도 괜찮은 경우가 있습니다. 그때는 간격을 줄여 예산을 효율적으로 씁니다.

흔한 실수: 간격을 고정값으로 두는 것. 사이트마다 감당하는 양이 크게 다릅니다. 그리고 응답이 느려지는 것은 상대가 힘들다는 신호인데, 고정 간격은 그 신호를 무시합니다.

먼저 스스로 답해보고 아래 답변과 견줘보세요. 막히는 부분은 문제로 확인할 수 있어요.

읽었으면 문제로 확인해보세요

웹 크롤러 설계 문제를 풀면 틀린 문제가 자동으로 노트에 쌓입니다. 가입 없이 5문제를 먼저 풀어볼 수도 있어요.