如何递归高效地调用服务器,直到得到正确的响应



我目前有两个标志。一个是CCD_ 1,另一个是CCD_。默认情况下,这两种情况都是真的,如果客户在呼叫我们的应用程序时想要更改,他们可以更改它们。所以可能发生的组合是-

remoteFlag       secondaryFlag
true             true
true             false
false            false
false            true

默认情况下,它总是真实的。

我应该给我们的服务器打一个HTTP呼叫(所有的服务器都是Ubunseu机器)。假设以下是我的服务器,其完全限定主机名对应于unix中的hostname -f

String hostname1 = hostname1;
String hostname2 = hostname2;
String hostname3 = hostname3;
String hostname4 = hostname4;

我有几个案例,我应该做如下所述-

  1. 假设remoteFlagsecondaryFlag都是true,则I我应该一个接一个地访问以上所有服务器,直到我们得到从服务器返回响应。意思是假设hostname1坏了所以我们不会从服务器得到任何响应,它会抛出异常,因此我们将转到hostname2以获取相同的数据,但假设hostname2也关闭,那么我们将继续remoteFlag0来获取数据,但是如果假定hostname3也是则我们将转到CCD_ 12以获取数据。但如果服务器能够返回响应,然后我们将返回通过做出适当的回应,说我们已经得到了数据。如果没有一个服务器能够返回响应,那么我们将做出错误响应,表示所有服务器都已关闭
  2. 现在,如果remoteFlagtrue,而secondaryFlagfalse,那么我们将仅转到CCD_ 17和CCD_。如果hostname1为向下,则我们将转到secondaryFlag0以获取响应。如果两者它们关闭了,那么我们将做出一个ERROR响应,说服务器下降
  3. 现在,如果remoteFlagfalse并且secondaryFlagfalse,那么我们只会去hostname1,仅此而已。如果CCD_ 26下降,那么我们将做出ERROR响应,表示服务器已关闭
  4. 现在,如果remoteFlagfalse并且secondaryFlagtrue,那么我们只会去hostname1hostname2,仅此而已。如果hostname1关闭,然后我们将转到hostname2获取回答如果它们都坏了,那么我们将产生一个错误响应称服务器已关闭

我所说的宕机是指服务器没有启动,所以这就是它们没有响应的原因。我在其中一台停机的服务器上进行了尝试,如果我尝试访问该服务器,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();
}
}

问题声明:-

在上面的代码中,我只是一直在重复一些东西,不知道如何递归地继续调用服务器,直到得到响应。以及我如何在上面的代码中适应其他用例。最初我想为其他用例添加相同的if块。然后我想我的整个代码都会被if块填满。

有什么想法吗?我该如何有效地解决这个问题?

您的代码中有很多锅炉板。只需在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
}
}

一种想法是将检索提取到另一种方法中(甚至可能是"静态"),就像一样

// 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);
}

然后你可以一个接一个地传入你的url,直到你得到一个好的响应。像这样,

// 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);
}

最新更新