2016-05-15 17 views
0

私のサービスへのHttpコールを行うライブラリで作業しています。サービスマシンが応答しない場合(ソケットタイムアウトや接続タイムアウトがあります)、私は私のローカルblockListにそれらを追加し、マシンが5回ブロックされている場合、私はそれらに電話をかけません。特定の時間間隔の間、眼鏡のマシンをブロックする

それでは、machineA(throwing RestClientException)が応答しない場合、私はmachineAそうであれば、閾値としてonFailure方法毎回を呼び出し、カウンタをインクリメント維持し、その後再びmachineAへの呼び出しをしながら、私はホスト名としてmachineAを渡すことでisBlocked方法をチェックして、5になるとしましょう5回ブロックされてしまったので、私は彼らに電話をしません。私のライブラリはマルチスレッドなので、すべてのスレッドに同じ値を見せたいので、ここではvolatileを使用しています。以下は

は、私がDataMappingクラスに持っているものです。

public static volatile ConcurrentHashMap<String, AtomicInteger> blockedHosts = 
     new ConcurrentHashMap<String, AtomicInteger>(); 

boolean isBlocked(String hostname, int threshold) { 
    AtomicInteger count = blockedHosts.get(hostname); 
    return count != null && count.get() >= threshold; 
} 

void onFailure(String hostname) { 
    AtomicInteger newValue = new AtomicInteger(); 
    AtomicInteger val = blockedHosts.putIfAbsent(hostname, newValue); 
    // no need to care about over-reaching 5 here 
    (val == null ? newValue : val).incrementAndGet(); 
} 

void onSuccess(String hostname) { 
    blockedHosts.remove(hostname); 
} 

問題文: -

今私はある1つの以上の機能を追加したい - machineAがブロックされている場合(そのブロック・カウントので、 > = 5)、私はそれをx間隔でブロックしておきたいと思います。私は別のパラメータ(key.getInterval())を持っています。このマシンはブロックされたままにしておきたい時間を教えてくれるでしょう。そして、そのインターバルが経過した後、私は彼らに電話をかけ始めます。この機能を追加する方法を理解できません。

以下は、私がDataMappingメソッドを使用してホスト名がブロックされているかどうかをチェックし、ホスト名をブロックするための主なスレッドコードです。

@Override 
public DataResponse call() { 
    ResponseEntity<String> response = null; 

    List<String> hostnames = some_code_here; 

    for (String hostname : hostnames) { 
     // If hostname is in block list, skip sending request to this host 
     if (DataMapping.isBlocked(hostname)) { 
      continue; 
     } 
     try { 
      String url = createURL(hostname); 
      response = restTemplate.exchange(url, HttpMethod.GET, key.getEntity(), String.class); 
      DataMapping.onSuccess(hostname); 

      // some code here to return the response if successful 
     } catch (RestClientException ex) { 
      // adding to block list 
      DataMapping.onFailure(hostname); 
     } 
    } 

    return new DataResponse(DataErrorEnum.SERVER_UNAVAILABLE, DataStatusEnum.ERROR);   
} 
私は特定の期間のために特定のマシンをブロックし、その間隔が経過するとすぐにその後、それらだけに通話を発信し始めることができますどのように

+0

あなたはそれが間隔が経過した場合、それがブロックされているだけではなく、かどうかを、伝えるためにブロックさになったときを追跡する必要があります。 –

答えて

1

特定のタイムアウト後にカウンタのリセットをScheduledExecutorServicescheduleにすることができます。

あなたのDataMappingクラス内でこれを宣言することができます。

private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); // or perhaps the thread pool version ? 

をそして、あなたのonFailure()メソッド内であなたがにしたいかどうかを決めることができますがまたはちょうどデクリメント特定のタイムアウト後にカウンタをリセット

void onFailure(String hostname) { 
    // you can use `computeIfAbsent` in java8 
    AtomicInteger val = blockedHosts.computeIfAbsent(hostname, key -> new AtomicInteger()); 
    int count = val.incrementAndGet(); 
    // the test here is `==` to make sure the task is scheduled only once 
    if (count == threshold) { 
     scheduler.schedule(() -> blockedHosts.remove(hostname), 5L, TimeUnit.MINUTES); // or you may choose to just decrement the counter 
    } 
} 

blockedHostsvolatileのような理由はありません。その参照は決して変更されません。代わりにfinalにする必要があります。おそらくprivateです。 java7で


、上記のコードは次のようになります。

void onFailure(String hostname) { 
    AtomicInteger newValue = new AtomicInteger(); 
    AtomicInteger val = blockedHosts.putIfAbsent(hostname, newValue); 
    int count = (val == null ? newValue : val).incrementAndGet(); 
    // the test here is `==` to make sure the task is scheduled only once 
    if (count == threshold) { 
     scheduler.schedule(new Runnable() { 
      @Override public void run() { 
       blockedHosts.remove(hostname); // or you may choose to just decrement the counter 
      } 
     }, 5L, TimeUnit.MINUTES); 
    } 
} 
+0

残念ながら私はまだJava 7を使用しており、Java 8に移行することはできません。Java 7ではどのように見えますか? – john

+0

'computeIfAbsent'ときちんとしたラムダ構文を除いて、ほとんど同じです。'Callable'(または' Runnable')をインスタンス化してそれをexecutorサービスに提出する必要があります。 –

+0

これをJava 7の提案でも更新できますか?私はまだ上記のコードが何をするのか理解しようとしています。私が理解していることを確認するために、Java 7で一度確認しておきたい質問はほとんどありません。 – john

関連する問題