2014-01-14 21 views
1

我目前有兩個標誌。一個是remoteFlag,另一個是secondaryFlag。默認情況下,它們都是真實的,客戶可以在他們打電話給我們的應用程序時更改它們。所以可能發生的組合是 -如何以遞歸方式高效地調用服務器,直到我得到正確的響應爲止?

remoteFlag  secondaryFlag 

true    true 
true    false 
false   false 
false   true 

默認情況下,它總是true和true。

我應該對我們的服務器進行HTTP調用(所有的服務器都是Ubunutu機器)。假設下面是我的服務器的完全合格主機名在UNIX上對應於hostname -f

String hostname1 = hostname1; 
String hostname2 = hostname2; 

String hostname3 = hostname3; 
String hostname4 = hostname4; 

我有對夫婦對此我應該做的情況下,如下所述 -

  1. 假設如果remoteFlagsecondaryFlag都是true然後我 我應該通過打以上所有服務器中的一個直到我們從服務器獲得 響應。假設含義是hostname1下 所以我們不會從服務器得到任何迴應回來了,它會 拋出一個異常,這樣的話我們會去hostname2,以獲取 相同的數據,但想,如果hostname2也下來了,然後我們會去 hostname3取數據,但如果假設hostname3也是 下來,那麼我們將去hostname4取數據。但是如果 中的任何一個服務器能夠給出響應,那麼我們將通過做出適當的響應並返回 來說明我們已經獲得了數據。 如果沒有服務器能夠提供迴應,那麼我們 將發出錯誤響應,表示所有服務器都關閉。
  2. 現在,如果remoteFlagtruesecondaryFlagfalse,然後 我們只會去hostname1hostname3。如果hostname1是 下來,那麼我們會去hostname3得到答覆。如果兩個 都關閉,那麼我們將發出ERROR響應,說服務器 已關閉。
  3. 現在,如果remoteFlagfalsesecondaryFlagfalse,然後 我們只會去hostname1,僅此而已。如果hostname1出現故障, 那麼我們將發出ERROR響應,表示服務器關閉。
  4. 現在,如果remoteFlagfalsesecondaryFlagtrue,然後 我們只會去hostname1hostname2,僅此而已。如果 hostname1已關閉,則我們將轉至hostname2以獲取 響應。如果兩者都關閉,那麼我們將發出ERROR 響應,表示服務器已關閉。

下來我的意思是服務器不起來,所以這就是爲什麼他們沒有迴應。我嘗試了其中一臺服務器發生故障,如果我嘗試擊中該服務器,則RestTemplate會引發異常。

以下是我的代碼到目前爲止只適用於如果remoteFlagsecondaryFlag都是真實的,但它又不看我的好代碼,因爲我只是在下面的代碼中重複的東西。我不知道如何在遞歸調用服務器時繼續調用服務器,如果其中任何一個服務器出現故障。但是,如果他們中的任何一個已經啓動並得到適當的響應,則通過用我得到的實際數據進行SUCCESS響應來返回調用。

下面是

public class ClientTask implements Callable<ClientResponse> { 

    public ClientTask(ClientKey clientKeys) { 
     this.clientKeys = clientKeys; 
    } 

    @Override 
    public ClientResponse call() throws Exception { 
     .... 

     boolean remoteFlag = clientKeys.isRemoteFlag(); 
     boolean secondaryFlag = clientKeys.isSecondaryFlag(); 

     RestTemplate restTemplate = new RestTemplate(); 
     String response = null; 
     ... 

     String hostname1 = hostname1; 
     String hostname2 = hostname2; 

     String hostname3 = hostname3; 
     String hostname4 = hostname4; 

     // first use case when both are true 
     if(remoteFlag && secondaryFlag) { 
      if(hostname1 != null) { 
       try { 
        String url = generateURL(hostname1);    
        response = restTemplate.getForObject(url, String.class); 

        return new ClientResponse(response, ClientError.NONE, ClientStatus.SUCCESS); 
       } catch(Exception ex) { 
        ex.printStackTrace(); // use logger 
       } 
      }    
      // hostname1 is down 
      if(response == null && hostname2 != null) { 
       try { 
        String url = generateURL(hostname2);    
        response = restTemplate.getForObject(url, String.class); 

        return new ClientResponse(response, ClientError.NONE, ClientStatus.SUCCESS); 
       } catch(Exception ex) { 
        ex.printStackTrace(); // use logger 
       } 
      } 
      // hostname1 and 2 both are down 
      if(response == null && hostname3 != null) { 
       try { 
        String url = generateURL(hostname3);    
        response = restTemplate.getForObject(url, String.class); 

        return new ClientResponse(response, ClientError.NONE, ClientStatus.SUCCESS); 
       } catch(Exception ex) { 
        ex.printStackTrace(); // use logger 
       } 
      } 
      // hostname1, 2, 3 are down 
      if(response == null && hostname4 != null) { 
       try { 
        String url = generateURL(hostname4);    
        response = restTemplate.getForObject(url, String.class); 

        return new ClientResponse(response, ClientError.NONE, ClientStatus.SUCCESS); 
       } catch(Exception ex) { 
        ex.printStackTrace(); // use logger 
       } 
      } 
     } 

     // not sure how to add other use case logic here as well properly 
    } 

    /** 
    * Method to generate the url to hit the servers. 
    * 
    */ 
    private String generateURL(final String hostname) { 
     StringBuffer url = new StringBuffer(); 
     url.append("http://" + hostname + ":8080/user?userId=" + clientKeys.getUserId() + "&page_id=" + clientKeys.getPageId()); 

     Set<Entry<String, String>> params = clientKeys.getAttributeMap().entrySet(); 

     for(Entry<String, String> e : params){ 
      url.append("&" + e.getKey()); 
      url.append("=" + e.getValue()); 
     } 

     return url.toString(); 
    } 
} 

ProblemStatement: -

在上面的代碼,我只是重複的東西的時候,不知道我怎麼遞歸繼續調用服務器,直到我得到反饋回來。還有,我如何在上面的代碼中適合其他用例。最初我想在其他用例中添加相同的塊。然後,我認爲我的整個代碼將填補只有塊。

任何想法如何有效地解決這個問題?

回答

2

在代碼中有很多鍋爐板。只需填寫if語句中的主機列表即可輕鬆避免它們。之後,您遍歷該列表:

List<String> hostnames = new ArrayList<>(); 
if(remoteFlag && secondaryFlag) { 
    hostnames.add(hostname1); 
    hostnames.add(hostname2); 

} else if … 

for (String hostname : hostnames) { 
    if(hostname == null) { 
     continue; 

    } 
    try { 
     String url = generateURL(hostname1);    
     response = restTemplate.getForObject(url, String.class); 
     break; 

    } catch(Exception ex) { 
     ex.printStackTrace(); // use logger 

    } 
} 
if (response == null) { 
    // do error handling 

} 
return new ClientResponse(response, ClientError.NONE, ClientStatus.SUCCESS); 

個人而言,我更喜歡另一種解決方案。構建表示狀態轉換並鏈接這些組件的組件:

public class FallbackCall() { 

    private String hostname; 

    private String secondaryHostname; 

    private FallbackQuery next; 

    public ClientResponse call(boolean remote, boolean secondary) { 
     ClientResponse response = getResponse(hostname); 
     if (response == null && secondary) { 
      reponse = getResponse(secondaryHostname); 

     } 
     if (response == null && remote) { 
      reponse = next.call(remote, secondary); 

     } 
     return response; 
    } 

    private ClientResponse getResponse(String hostname) { 
     // your boiler plate 
    } 

} 
+0

謝謝你的建議。現在我會選擇你的第一個建議。在你的例子中,如果所有的服務器都關閉了,那麼我怎樣才能做出一個ERROR響應並將它發回給客戶?目前它不會做任何事.. – AKIWEB

+0

只要最後一個結果爲空就拋出異常。 –

+0

我應該在for循環之後拋出並檢查我的最後結果。正確嗎? Bcoz那是我能看到我最後結果的地方.. – AKIWEB

0

一個想法是提取檢索到的另一種方法(甚至可能是「靜態」),像這樣

// I don't recognize your library... 
public ClientResponse call(String hostname) throws Exception { 
    if (hostname == null) { 
    return null; 
    } 
    // You might also make generateURL static 
    String url = generateURL(hostname); 
    String response = restTemplate.getForObject(url, 
     String.class); 
    if (response == null) { // add more logic here to test your response. 
    return null; 
    } 
    return new ClientResponse(response, 
     ClientError.NONE, ClientStatus.SUCCESS); 
} 

然後你就可以在你的網址逐一傳遞,直到你獲得良好的響應。像這樣,

// String hostname1 = hostname1; 
// String hostname2 = hostname2; 
// String hostname3 = hostname3; 
// String hostname4 = hostname4; 
if(remoteFlag && secondaryFlag) { 
    ClientResponse response = call(hostname1); 
    // != null is one test. However you test the response is valid. 
    if (response != null) return response; 
    response = call(hostname2); 
    if (response != null) return response; 
    response = call(hostname3); 
    if (response != null) return response; 
    return call(hostname4); 
} 
+0

謝謝Elliott。對不起,如果我不清楚..上面的代碼是在實現CallableTask的類,所以調用方法來自那裏..我應該做的所有這些東西在該調用方法。我可以製作另一種方法來執行URL並做出響應,但是如何以遞歸方式調用該方法? – AKIWEB

+0

你不要遞歸地調用它,首先調用hostname1 ...是結果!= null,如果是的話返回它...下一次調用hostname2 ...是結果!= null;直到主機名4 ...返回結果。並且該方法可以調用其他方法!特別是靜態方法。 –

+0

你能提供一個我上面的場景的例子。我很困惑我們如何在不使用遞歸的情況下做到這一點。任何幫助將不勝感激..謝謝.. – AKIWEB

相關問題