스크랩하고 구문 분석 한 다음 결과 데이터를 데이터베이스에 저장해야하는 웹 페이지 목록이 있습니다. 총계는 약 5,000,000입니다.
이것에 접근하는 가장 좋은 방법은 ~ 100 EC2 인스턴스를 배포하고 각 인스턴스에 50,000 페이지를 스크래핑 한 다음 실행되도록 남겨두고 프로세스가 완료되면 데이터베이스를 병합하는 것입니다. 실행하는 데 하루가 걸릴 것으로 가정합니다 (각 페이지를로드, 구문 분석 및 저장하는 데 600ms).
제한된 시간 내에 대량의 페이지 스크래핑을 수행 한 경험이 있습니까? 나는 (1.5m) 전에 많은 수의 작업을 수행했지만 단일 시스템에서 수행되었으며 완료하는 데 일주일이 걸렸습니다.
내 상황의 병목 현상은 페이지를 다운로드하는 것입니다. 파싱은 2ms 이상 걸리지 않으므로 페이지 다운로드 프로세스를 능률화 할 수있는 것이 내가 찾고있는 것입니다.
답변
다운로드 시간 (따라서 대역폭 사용량)이 제한 요소라는 가정하에 다음과 같이 제안합니다.
먼저 m1.large 인스턴스를 선택하십시오. m1.large 및 m1.xlarge 인스턴스는 세 가지 ‘레벨’I / O 성능 (대역폭 포함) 중 ‘높은’I / O 성능을 제공합니다. 작업이 CPU에 국한된 것이 아니므로 가장 저렴한 방법이 선호됩니다.
둘째, 인스턴스는 모든 사이트가 페이지를 제공 할 수있는 것보다 훨씬 빠르게 다운로드 할 수 있습니다. 주어진 인스턴스에서 한 번에 한 페이지를 다운로드하지 않고 작업을 동시에 실행합니다. 동시에 20 페이지 이상을 동시에 수행 할 수 있어야합니다. , 어려움없이 50-100을 할 수 있다고 생각합니다. (댓글에서 포럼에서 다운로드하는 예를 들어보십시오. 서버 생성에 시간이 걸리는 동적 페이지이며 해당 사이트 대역폭을 사용하는 다른 사용자가 있습니다.) 인스턴스 대역폭의 한계에 도달 할 때까지 동시성을 계속 늘리십시오. (물론 동일한 사이트에 여러 개의 동시 요청을하지 마십시오).
실제로 성능을 극대화하려는 경우 지리적으로 적절한 영역에서 인스턴스를 시작하여 대기 시간을 최소화하는 것이 좋습니다 (그러나 모든 URL을 지리적으로 배치해야하지만 실용적이지 않을 수 있음).
한 가지 주목할 점은 인스턴스 대역폭이 가변적이며, 때로는 성능이 향상되고, 다른 경우 성능이 저하된다는 것입니다. 더 작은 인스턴스에서는 실제 링크가 더 많은 서버에서 공유되고 그 중 하나가 사용 가능한 대역폭을 감소시킬 수 있기 때문에 성능 변화가 더 중요합니다. EC2 네트워크 (동일한 가용 영역) 내에서 m1.large 인스턴스간에 이론적 인 기가비트 처리량에 근접해야합니다.
일반적으로 AWS를 사용하면 여러 인스턴스가 필요한 여러 장애 조치와 같은 것을 특별히 고려하지 않는 한 여러 개의 작은 인스턴스가 아닌 더 큰 인스턴스를 사용하는 것이 거의 항상 효율적입니다.
나는 당신의 설정이 무엇을 의미하는지 모르지만, 이전에 이것을 시도했을 때 (1 ~ 2 백만 링크 사이, 주기적으로 업데이트 됨), 내 접근 방식은 링크가 발견되면 새 링크를 추가하고 프로세스를 분기시키는 링크 데이터베이스를 유지하는 것이 었습니다 페이지를 긁어 내고 구문 분석합니다. URL은 (임의로) 검색되어 데이터베이스에서 진행중인 것으로 표시되고, 스크립트는 페이지를 다운로드하며, 성공한 경우 URL을 데이터베이스에 다운로드 된 것으로 표시하고 페이지를 구문 분석 한 다른 스크립트로 새 링크를 보냅니다. 찾은대로 데이터베이스에 추가되었습니다. 여기서 데이터베이스의 장점은 중앙 집중화였습니다. 여러 스크립트가 데이터베이스를 동시에 쿼리 할 수 있으며 (트랜잭션이 원자적인 한) 각 페이지가 한 번만 다운로드되도록 보장 할 수 있습니다.
몇 가지 추가 언급-한 번에 실행할 수있는 온 디맨드 인스턴스 수에 제한이 있습니다 (20 번 생각)-이 제한을 초과 할 계획 인 경우 AWS에 계정을 늘리도록 요청해야합니다 제한. 스팟 인스턴스를 실행하고 스팟 가격이 낮을 때 숫자를 확장하는 것이 훨씬 더 경제적입니다 (모든 인스턴스를 구성하고 나머지 스팟 인스턴스를 유지하는 온 디맨드 인스턴스 일 수 있음).
시간이 비용보다 우선 순위가 높은 경우 클러스터 컴퓨팅 인스턴스는 10Gbps 대역폭을 제공하며 가장 큰 다운로드 대역폭을 제공해야합니다.
요약 : 많은 작은 인스턴스 대신 몇 개의 큰 인스턴스를 시도하고 각 인스턴스에서 여러 개의 동시 다운로드를 실행하십시오. 대역폭이 제한되어 있으면 더 많은 인스턴스를 추가하고 CPU / 메모리가 바인드되면 더 큰 인스턴스로 이동하십시오.
답변
우리는 비슷한 것을 시도했지만 여기 5 센트가 있습니다.
-
예를 들어 대역폭을 지불하지 않는 2 ~ 3 개의 저렴한 계량 서버를 확보하십시오.
-
파이썬을 asyncore와 함께 사용하십시오. Asyncore는 오래된 방법이지만 다른 방법보다 빠르게 작동합니다. 단점은 DNS 조회가 차단되고 있다는 것입니다. 즉 “병렬”이 아닙니다. asyncore를 사용하여 단일 XEON 4 코어, 8GB RAM을 사용하여 1M URL을 40 분 동안 긁었습니다. 서버의로드 평균은 4보다 적었습니다 (4 코어에 우수함).
-
asyncore가 마음에 들지 않으면 gevent를 사용해보십시오. 심지어 DNS 비 차단도 수행합니다. gevent를 사용하여 1M이 동일한 하드웨어에서 약 50 분 동안 다운로드되었습니다. 서버의로드 평균은 엄청났습니다.
grequests, curl, liburl / liburl2와 같은 많은 Python 라이브러리를 테스트 했지만 Twisted 테스트 는 하지 않았습니다 .
- 우리는 PHP + curl + 여러 프로세스를 테스트했지만 약 1 시간 동안 작업을 수행했지만 서버의 평균로드는 엄청났습니다.