2013-03-28 2 views
0

상호 작용하는 서비스에서 처리량 한도에 도달하는 것을 피하기 위해 제한 알고리즘을 구현해야합니다.처리량 측정

한계는 N이 10^6 크기의 N 인 경우 1 일 이상 N 요청으로 지정됩니다.

저는 서비스와 상호 작용하는 클라이언트의 분산 시스템을 가지고 있기 때문에 측정 값을 공유해야합니다.

정확한 해결책은 모든 이벤트를 기록하고 서비스 호출 이벤트가 발생할 때를 계산하는 것보다 중요합니다. 물론이 방법은 너무 비싸서 대략적인 솔루션을 찾고 있습니다.

내가 처음으로 발견 한 것은 사건의 탐지를 이산화하는 것을 의미한다 : 예를 들어 최대 24 개의 카운터를 유지하고 요청 횟수를 기록하는 것은 1 시간 이내에 발생했다.

허용.

그러나 나는 더 우아한 것은 비록 다른 "힘"에 의해 이끌린 다 할지라도 연속체에 대한 접근을 쇠퇴시키는 것이라고 생각합니다.

마지막 N 이벤트를 기록하면«현재»처리량을 쉽게 추측 할 수 있습니다. 물론이 알고리즘은 몇 시간 전에 발생했던 과거 사건에 대한 누락 된 고려로 인해 어려움을 겪습니다. 노화 알고리즘으로 개선 할 수 있지만 ... 내 질문에 따라 진행할 수 있습니다.

Q : 이벤트 발생률이 높고 장기간에 걸친 서비스 처리량을 예측하는 문제에 대한 우아한 근사 솔루션이 있습니까?»

+0

고객이 중심점을 돌고 있습니까? 아니면 제한된 서비스와 직접 대화하고 있습니까? – James

+0

한계를 초과했을 때의 행동은 무엇입니까? 클라이언트를 모니터링하거나 속도를 제한하기 만하면됩니까? – James

+0

물론 화자는 응용 클라이언트가 사용하는 공통 구성 요소 내에서 중앙 집중화됩니다. 한도에 도달하면 OVER_QUOTA 오류 메시지와 함께 모든 호출이 무시됩니다. –

답변

0

내 의견에 따라 모니터를 사용하여 15 분마다 값을 샘플링하거나 요청 횟수를 합리적으로 추측해야합니다.

나는 여기에 뭔가를 조롱했으나 테스트하지는 않았으므로 초보자를 제공해야합니다.

import java.util.LinkedList; 
import java.util.Queue; 
import java.util.Timer; 
import java.util.TimerTask; 

public class TestCounter { 

private final Monitor monitor; 

private TestCounter() { 
    monitor = new Monitor(); 
} 

/** The thing you are limiting */ 
public void myService() { 
    if (monitor.isThresholdExceeded()) { 
     //Return error 
    } else { 
     monitor.incremenetCounter(); 
     //do stuff 
    } 
} 

public static void main(String[] args) { 
    TestCounter t = new TestCounter(); 
    for (int i = 0; i < 100000; i++) { 
     t.myService(); 
    } 

    for (int i = 0; i < 100000; i++) { 
     t.myService(); 
    } 
} 

private class Monitor { 
    private final Queue<Integer> queue = new LinkedList<Integer>(); 

    private int counter = 1; 

    /** Number of 15 minute periods in a day. */ 
    private final int numberOfSamples = 76; 

    private final int threshold = 1000000; 

    private boolean thresholdExceeded; 

    public Monitor() { 
     //Schedule a sample every 15 minutes. 
     Timer t = new Timer(); 
     t.scheduleAtFixedRate(new TimerTask() { 
      @Override 
      public void run() { 
       sampleCounter(); 
      } 
     }, 0l, 900000 /** ms in 15 minutes */ 
     ); 
    } 

    /** Could synchroinise */ 
    void incremenetCounter() { 
     counter++; 
    } 

    /** Could synchroinise */ 
    void sampleCounter() { 
     int tempCount = counter; 
     counter = 0; 
     queue.add(tempCount); 

     if (queue.size() > numberOfSamples) { 
      queue.poll(); 
     } 

     int totalCount = 0; 
     for (Integer value : queue) { 
      totalCount += value; 
     } 
     if (totalCount > threshold) { 
      thresholdExceeded = true; 
     } else { 
      thresholdExceeded = false; 
     } 
    } 

    public boolean isThresholdExceeded() { 
     return thresholdExceeded; 
    } 
} 
}