2009-04-24 17 views
1

나는 Musicbrainz 웹 서비스에 요청하는 앱을 개발 중입니다. musicbrainz 매뉴얼에서 초당 하나의 요청을 webservice에 보내지 않거나 클라이언트 IP가 차단됩니다.시간 제한 서비스

이 제한을 서비스 클라이언트에 투명하게 만들기 위해 어떤 아키텍처를 제안하십니까?

  • 메서드 (예 : getAlbuns)를 호출하고 싶습니다. 마지막 요청 후 1 초만 요청해야합니다.
  • 또한 한 번에 10 개의 요청을 호출하고 서비스가 대기열을 처리하여 avaiable (Non-blocking) 일 때 결과를 반환해야합니다.

감사합니다.

+0

난 당신이 데스크톱 응용 프로그램을 만드는 가정 queueBlockingQueue<? extends Request> 인 경우에는 다음과 같이 보일 수 있는가? –

+0

네, 맞습니다! –

답변

1

때문에 호출 사이에 필요한 지연, 나는 java.util.Timer 또는 java.util.concurrent.ScheduledThreadPoolExecutor 건의 할 것입니다. Timer을 매우 간단하며 완벽하게 적합합니다 유스 케이스. 그러나 나중에 추가 일정 요구 사항이 확인되면 단일 Executor이 모두를 처리 할 수 ​​있습니다. 두 경우 모두 고정 속도 방법이 아닌 고정 지연 방법을 사용하십시오.

되풀이 작업 polls 요청 개체에 대한 동시 대기열. 보류중인 요청이 있으면 태스크가이를 실행하고 콜백을 통해 결과를 리턴합니다. 호출 할 서비스 및 콜백에 대한 쿼리는 요청 객체의 멤버입니다.

응용 프로그램이 공유 대기열에 대한 참조를 유지합니다. 요청을 예약하려면 대기열에 요청을 추가하기 만하면됩니다.


예약 된 작업이 실행될 때 큐가 비어 있으면 요청하지 않습니다. 간단한 접근법은 작업을 끝내는 것일 뿐이며 스케줄러는 1 초 후에 작업을 다시 호출하여 다시 확인합니다.

그러나 최근에 요청이 처리되지 않은 경우에도 작업을 시작하는 데 최대 1 초가 걸릴 수 있습니다. 이 불필요한 대기 시간을 참작 할 수 없다면, Timer 또는 ScheduledThreadPoolExecutor을 사용하는 것보다 나만의 스레드를 작성하는 것이 좋습니다. 요청을 사용할 수있을 때까지 빈 큐에서 차단하도록 선택한 경우 사용자는 자신의 타이밍 루프에서 일정을보다 잘 제어 할 수 있습니다. 내장 타이머는 이전 실행 후 1 초를 기다릴 수 없습니다. 으로 끝납니다. 그들은 일반적으로 시작 작업 시간과 관련하여 일정을 계획합니다.

두 번째 사례가 염두에 두어야 할 경우 run() 메서드에 루프가 포함됩니다. 각 반복은 요청이 수신 될 때까지 큐에서 blocking부터 시작한 다음 시간을 기록합니다. 요청을 처리 한 후 시간을 다시 확인합니다. 시간차가 1 초 미만이면 나머지는 sleep입니다. 이 설정은 한 요청의 시작과 다음 요청 사이에 1 초 지연이 필요하다고 가정합니다. 한 요청의 끝과 다음 요청 사이에 지연이 필요한 경우 시간을 확인할 필요가 없습니다. 잠깐만 자고.

한 가지 더 주목할 점은 서비스가 단일 요청으로 여러 쿼리를 수락 할 수 있으므로 오버 헤드가 줄어들 수 있다는 것입니다. 그렇다면 첫 번째 요소에 대해 take()을 차단 한 다음 poll()을 사용하여 매우 짧은 차단 시간 (5ms 정도)을 사용하여 응용 프로그램이 더 이상 요청을하는지 확인하십시오. 그렇다면 서비스 요청을 한 번에 번들로 묶을 수 있습니다.

Collection<Request> bundle = new ArrayList<Request>(); 
    bundle.add(queue.take()); 
    while (bundle.size() < BUNDLE_MAX) { 
     Request req = queue.poll(EXTRA, TimeUnit.MILLISECONDS); 
     if (req == null) 
     break; 
     bundle.add(req); 
    } 
    /* Now make one service request with contents of "bundle". */ 
+0

하지만 매 초마다 요청하지 않으려합니다. 클라이언트가 요청할 때 마지막 1 초 후에 만 ​​실행되도록 확인하고 싶습니다. –

+0

오른쪽, Marcio. 나는 그것을 암시하는 것을 의미하지는 않았다. 내가 명확하게 대답을 업데이 트됩니다. – erickson

1

로컬 클라이언트가 호출 할 로컬 "프록시 서비스"를 정의해야합니다.

로컬 프록시는 요청을 받아 실제 서비스로 전달합니다. 그러나 초당 하나의 메시지 비율로만.

이 작업 방법은 사용 가능한 tecnoligy에 따라 다릅니다.

간단한

는 정적와 mutithreaded 자바 서비스하고 LastRequestTime 긴 동기화 것이다. "타임 스탬프 변수 (당신이 순서에있는 당신의 요청을 유지하기 위해 몇 가지 코드 곡예를해야하지만)

더 정교한 서비스가있을 수 있습니다. 작업자 스레드 요청을 받아 요청을 따기 단일 스레드 큐에 그들을 배치하고 실제 서비스에 그들을 전달합니다.