Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import io.servicecomb.bizkeeper.BizkeeperExceptionUtils;
import io.servicecomb.core.exception.CseException;
import io.servicecomb.demo.CodeFirstRestTemplate;
import io.servicecomb.demo.TestMgr;
import io.servicecomb.provider.pojo.RpcReference;
Expand All @@ -44,8 +46,36 @@ protected void testExtend(RestTemplate template, String cseUrlPrefix) {

testResponseEntity("springmvc", template, cseUrlPrefix);
testIntf();
testFallback(template, cseUrlPrefix);
}

private void testFallback(RestTemplate template, String cseUrlPrefix) {
String result = template.getForObject(cseUrlPrefix + "/fallback/returnnull/hello", String.class);
TestMgr.check(result, "hello");
result = template.getForObject(cseUrlPrefix + "/fallback/returnnull/throwexception", String.class);
TestMgr.check(result, null);

result = template.getForObject(cseUrlPrefix + "/fallback/throwexception/hello", String.class);
TestMgr.check(result, "hello");
try {
result = template.getForObject(cseUrlPrefix + "/fallback/throwexception/throwexception", String.class);
TestMgr.check(false, true);
} catch (Exception e) {
TestMgr.check(((CseException) e.getCause().getCause().getCause()).getMessage(),
BizkeeperExceptionUtils.createBizkeeperException(BizkeeperExceptionUtils.CSE_HANDLER_BK_FALLBACK,
null,
"springmvc.codeFirst.fallbackThrowException").getMessage());
}

result = template.getForObject(cseUrlPrefix + "/fallback/fromcache/hello", String.class);
TestMgr.check(result, "hello");
result = template.getForObject(cseUrlPrefix + "/fallback/fromcache/throwexception", String.class);
TestMgr.check(result, "hello");

result = template.getForObject(cseUrlPrefix + "/fallback/force/hello", String.class);
TestMgr.check(result, "mockedreslut");
}

private void testIntf() {
Date date = new Date();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright 2017 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.servicecomb.demo.springmvc.client;

import org.springframework.stereotype.Component;

import io.servicecomb.bizkeeper.FallbackPolicy;
import io.servicecomb.core.Invocation;
import io.servicecomb.swagger.invocation.Response;

@Component
public class MockedFallbackExample implements FallbackPolicy {

@Override
public String name() {
return "mycustom";
}

@Override
public Response getFallbackResponse(Invocation invocation) {
return Response.succResp("mockedreslut");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@
~ limitations under the License.
-->

<beans xmlns="http://www.springframework.org/schema/beans"
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util" xmlns:cse="http://www.huawei.com/schema/paas/cse/rpc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans classpath:org/springframework/beans/factory/xml/spring-beans-3.0.xsd
http://www.huawei.com/schema/paas/cse/rpc classpath:META-INF/spring/spring-paas-cse-rpc.xsd">
http://www.huawei.com/schema/paas/cse/rpc classpath:META-INF/spring/spring-paas-cse-rpc.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<context:component-scan base-package="io.servicecomb.demo.springmvc.client" />
<cse:rpc-reference id="controller" microservice-name="springmvc"
schema-id="controller" interface="io.servicecomb.demo.controller.Controller"></cse:rpc-reference>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,24 @@ cse:
serverListFilter:
zoneaware:
className: io.servicecomb.loadbalance.filter.ZoneAwareServerListFilterExt
fallbackpolicy:
Consumer:
springmvc:
codeFirst:
fallbackFromCache:
policy: fromCache
fallbackReturnNull:
policy: returnNull
fallbackThrowException:
policy: throwException
fallbackForce:
policy: mycustom
fallback:
Consumer:
springmvc:
codeFirst:
fallbackForce:
force: true
datacenter:
name: myDC
region: my-Region
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,12 @@
import io.servicecomb.swagger.invocation.Response;
import io.servicecomb.swagger.invocation.context.ContextUtils;
import io.servicecomb.swagger.invocation.context.InvocationContext;
import io.servicecomb.swagger.invocation.exception.InvocationException;
import io.servicecomb.swagger.invocation.response.Headers;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.ResponseHeader;

@RestSchema(schemaId = "codeFirst")
Expand Down Expand Up @@ -176,4 +178,44 @@ public String addString(@RequestParam(name = "s") List<String> s) {
}
return result;
}

@RequestMapping(path = "/fallback/returnnull/{name}", method = RequestMethod.GET)
@ApiResponses(value = {@ApiResponse(code = 200, response = String.class, message = "xxx"),
@ApiResponse(code = 490, response = String.class, message = "xxx")})
public String fallbackReturnNull(@PathVariable(name = "name") String name) {
if ("throwexception".equals(name)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's better to use the constant string.

throw new InvocationException(490, "490", "xxx");
}
return name;
}

@RequestMapping(path = "/fallback/throwexception/{name}", method = RequestMethod.GET)
@ApiResponses(value = {@ApiResponse(code = 200, response = String.class, message = "xxx"),
@ApiResponse(code = 490, response = String.class, message = "xxx")})
public String fallbackThrowException(@PathVariable(name = "name") String name) {
if ("throwexception".equals(name)) {
throw new InvocationException(490, "490", "xxx");
}
return name;
}

@RequestMapping(path = "/fallback/fromcache/{name}", method = RequestMethod.GET)
@ApiResponses(value = {@ApiResponse(code = 200, response = String.class, message = "xxx"),
@ApiResponse(code = 490, response = String.class, message = "xxx")})
public String fallbackFromCache(@PathVariable(name = "name") String name) {
if ("throwexception".equals(name)) {
throw new InvocationException(490, "490", "xxx");
}
return name;
}

@RequestMapping(path = "/fallback/force/{name}", method = RequestMethod.GET)
@ApiResponses(value = {@ApiResponse(code = 200, response = String.class, message = "xxx"),
@ApiResponse(code = 490, response = String.class, message = "xxx")})
public String fallbackForce(@PathVariable(name = "name") String name) {
if ("throwexception".equals(name)) {
throw new InvocationException(490, "490", "xxx");
}
return name;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright 2017 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.servicecomb.bizkeeper;

import java.util.List;

import javax.inject.Inject;

public class BeansHolder {
@Inject
private List<FallbackPolicy> policies;

public void init() {
for (FallbackPolicy policy : this.policies) {
FallbackPolicyManager.addPolicy(policy);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,18 +61,7 @@ protected Observable<Response> resumeWithFallback() {
Observable<Response> observable = Observable.create(f -> {
LOG.info("fallback called.");
try {
if (Configuration.FALLBACKPOLICY_POLICY_RETURN
.equals(Configuration.INSTANCE.getFallbackPolicyPolicy(type,
invocation.getMicroserviceName(),
invocation.getOperationMeta().getMicroserviceQualifiedName()))) {
f.onNext(Response.succResp(null));
} else {
f.onNext(Response.failResp(invocation.getInvocationType(),
BizkeeperExceptionUtils
.createBizkeeperException(BizkeeperExceptionUtils.CSE_HANDLER_BK_FALLBACK,
null,
invocation.getOperationMeta().getMicroserviceQualifiedName())));
}
f.onNext(FallbackPolicyManager.getFallbackResponse(type, invocation));
f.onCompleted();
} catch (Exception e) {
LOG.warn("fallback failed due to:" + e.getMessage());
Expand All @@ -91,9 +80,11 @@ protected Observable<Response> construct() {
// e should implements toString
LOG.warn("bizkeeper command failed due to:" + resp.getResult());
f.onError(resp.getResult());
FallbackPolicyManager.record(type, invocation, resp, false);
} else {
f.onNext(resp);
f.onCompleted();
FallbackPolicyManager.record(type, invocation, resp, true);
}
});
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,18 +60,7 @@ public void call() {
public Observable<Response> toObservable() {
return Observable.create(f -> {
try {
if (Configuration.FALLBACKPOLICY_POLICY_RETURN
.equals(Configuration.INSTANCE.getFallbackPolicyPolicy(handler.groupname,
invocation.getMicroserviceName(),
invocation.getOperationMeta().getMicroserviceQualifiedName()))) {
f.onNext(Response.succResp(null));
} else {
f.onNext(Response.failResp(invocation.getInvocationType(),
BizkeeperExceptionUtils
.createBizkeeperException(BizkeeperExceptionUtils.CSE_HANDLER_BK_FALLBACK,
null,
invocation.getOperationMeta().getMicroserviceQualifiedName())));
}
f.onNext(FallbackPolicyManager.getFallbackResponse(handler.groupname, invocation));
} catch (Exception e) {
f.onError(e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,15 +224,10 @@ public int getFallbackMaxConcurrentRequests(String type, String microserviceName
}

public String getFallbackPolicyPolicy(String type, String microserviceName, String qualifiedOperationName) {
String p = getProperty(null,
return getProperty(null,
FALLBACKPOLICY + type + "." + qualifiedOperationName + "." + FALLBACKPOLICY_POLICY,
FALLBACKPOLICY + type + "." + microserviceName + "." + FALLBACKPOLICY_POLICY,
FALLBACKPOLICY + type + "." + FALLBACKPOLICY_POLICY);
if (FALLBACKPOLICY_POLICY_RETURN.equals(p)) {
return FALLBACKPOLICY_POLICY_RETURN;
} else {
return FALLBACKPOLICY_POLICY_THROW;
}
}

private String getProperty(String defaultValue, String... keys) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2017 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.servicecomb.bizkeeper;

import io.servicecomb.core.Invocation;
import io.servicecomb.swagger.invocation.Response;

public interface FallbackPolicy {
String name();

Response getFallbackResponse(Invocation invocation);

default void record(Invocation invocation, Response response, boolean isSuccess) {

};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright 2017 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.servicecomb.bizkeeper;

import java.util.HashMap;
import java.util.Map;

import io.servicecomb.core.Invocation;
import io.servicecomb.swagger.invocation.Response;

public class FallbackPolicyManager {
private static final Map<String, FallbackPolicy> POLICIES = new HashMap<>();

public static void addPolicy(FallbackPolicy policy) {
POLICIES.put(policy.name().toLowerCase(), policy);
}

public static void record(String type, Invocation invocation, Response response, boolean isSuccess) {
FallbackPolicy policy = getPolicy(type, invocation);
if (policy != null) {
policy.record(invocation, response, isSuccess);
}
}

public static Response getFallbackResponse(String type, Invocation invocation) {
FallbackPolicy policy = getPolicy(type, invocation);
if (policy != null) {
return policy.getFallbackResponse(invocation);
} else {
return Response.failResp(invocation.getInvocationType(),
BizkeeperExceptionUtils
.createBizkeeperException(BizkeeperExceptionUtils.CSE_HANDLER_BK_FALLBACK,
null,
invocation.getOperationMeta().getMicroserviceQualifiedName()));
}
}

private static FallbackPolicy getPolicy(String type, Invocation invocation) {
String policyKey = Configuration.INSTANCE.getFallbackPolicyPolicy(type,
invocation.getMicroserviceName(),
invocation.getOperationMeta().getMicroserviceQualifiedName());
FallbackPolicy policy = null;
if (policyKey != null) {
policy = POLICIES.get(policyKey.toLowerCase());
}
return policy;
}
}
Loading