我目前有两个标志。一个是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;
我有几个案例,我应该做如下所述-
- 假设
remoteFlag
和secondaryFlag
都是true
,则I我应该一个接一个地访问以上所有服务器,直到我们得到从服务器返回响应。意思是假设hostname1
坏了所以我们不会从服务器得到任何响应,它会抛出异常,因此我们将转到hostname2
以获取相同的数据,但假设hostname2
也关闭,那么我们将继续remoteFlag
0来获取数据,但是如果假定hostname3
也是则我们将转到CCD_ 12以获取数据。但如果服务器能够返回响应,然后我们将返回通过做出适当的回应,说我们已经得到了数据。如果没有一个服务器能够返回响应,那么我们将做出错误响应,表示所有服务器都已关闭 - 现在,如果
remoteFlag
是true
,而secondaryFlag
是false
,那么我们将仅转到CCD_ 17和CCD_。如果hostname1
为向下,则我们将转到secondaryFlag
0以获取响应。如果两者它们关闭了,那么我们将做出一个ERROR响应,说服务器下降 - 现在,如果
remoteFlag
是false
并且secondaryFlag
是false
,那么我们只会去hostname1
,仅此而已。如果CCD_ 26下降,那么我们将做出ERROR响应,表示服务器已关闭 - 现在,如果
remoteFlag
是false
并且secondaryFlag
是true
,那么我们只会去hostname1
和hostname2
,仅此而已。如果hostname1
关闭,然后我们将转到hostname2
获取回答如果它们都坏了,那么我们将产生一个错误响应称服务器已关闭
我所说的宕机是指服务器没有启动,所以这就是它们没有响应的原因。我在其中一台停机的服务器上进行了尝试,如果我尝试访问该服务器,RestTemplate
会抛出异常。
以下是我到目前为止的代码,仅适用于remoteFlag
和secondaryFlag
都为真的情况,但在我看来,这不是一个好代码,因为我只是重复下面代码中的内容。我不知道如果其中任何一个服务器出现故障,我该如何继续递归调用服务器。但是,如果其中任何一个启动并得到了正确的响应,那么通过使用我得到的实际数据做出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);
}