Skip to content

Commit

Permalink
[#508] add fault injection features (#815)
Browse files Browse the repository at this point in the history
  • Loading branch information
liubao68 authored Aug 2, 2022
1 parent ba18b08 commit 351dffd
Show file tree
Hide file tree
Showing 16 changed files with 423 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,40 @@ public void gatewayIsolationForceOpenFeign() {
Assertions.assertThrows(HttpServerErrorException.class,
() -> template.getForObject(url + "/order/govern/gatewayIsolationForceOpenFeign", String.class));
}

@Test
public void testFaultInjectionGateway() {
long begin = System.currentTimeMillis();
String result = template.getForObject(url + "/price/faultInjection", String.class);
Assertions.assertEquals("success", result);
Assertions.assertTrue((System.currentTimeMillis() - begin) >= 1000);
}

@Test
public void testFaultInjectionConsumerRestTemplate() {
// spring decoder not properly decode json null and here will get string `null`
Assertions.assertEquals("null",
template.getForObject(url + "/order/govern/faultInjectionRestTemplate", String.class));
}

@Test
public void testFaultInjectionConsumerFeign() {
// spring decoder not properly decode json null and here will get string `null`
Assertions.assertEquals("null",
template.getForObject(url + "/order/govern/faultInjectionFeign", String.class));
}

@Test
public void testFaultInjectionConsumerRestTemplateModel() {
// spring decoder not properly decode json null and here will get string `null`
Assertions.assertEquals(null,
template.getForObject(url + "/order/govern/faultInjectionRestTemplateModel", PojoModel.class));
}

@Test
public void testFaultInjectionConsumerFeignModel() {
// spring decoder not properly decode json null and here will get string `null`
Assertions.assertEquals(null,
template.getForObject(url + "/order/govern/faultInjectionFeignModel", PojoModel.class));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright (C) 2020-2022 Huawei Technologies Co., Ltd. All rights reserved.
* 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 com.huaweicloud.sample;

public class PojoModel {
private int num;

private String name;

public PojoModel() {

}

public PojoModel(int num, String name) {
this.num = num;
this.name = name;
}

public int getNum() {
return num;
}

public void setNum(int num) {
this.num = num;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ servicecomb:
matches:
- apiPath:
prefix: "/govern/gatewayIsolationForceOpenFeign"
faultInjection: |
matches:
- apiPath:
prefix: "/price/faultInjection"
instanceIsolation:
allOperation: |
minimumNumberOfCalls: 10
Expand All @@ -58,6 +62,11 @@ servicecomb:
gatewayIsolationForceOpenFeign: |
forceOpen: true
order: 1
faultInjection:
faultInjection: |
type: delay
delayTime: 1000
percentage: 100
management:
endpoint:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@FeignClient(name = "price")
public interface FeignService {
Expand All @@ -29,6 +30,14 @@ public interface FeignService {
@RequestMapping("/retry")
String retry(@RequestParam(name = "invocationID") String invocationID);

@RequestMapping(value = "/faultInjection", produces = "application/json")
@ResponseBody
String faultInjection();

@RequestMapping(value = "/faultInjectionModel", produces = "application/json")
@ResponseBody
PojoModel faultInjectionModel();

@RequestMapping("/invocationContext")
String invocationContext();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,26 @@ public String hello() {
return restTemplate.getForObject("http://price/hello", String.class);
}

@RequestMapping("/faultInjectionRestTemplate")
public String faultInjectionRestTemplate() {
return restTemplate.getForObject("http://price/faultInjection", String.class);
}

@RequestMapping("/faultInjectionFeign")
public String faultInjectionFeign() {
return feignService.faultInjection();
}

@RequestMapping("/faultInjectionRestTemplateModel")
public PojoModel faultInjectionRestTemplateModel() {
return restTemplate.getForObject("http://price/faultInjectionModel", PojoModel.class);
}

@RequestMapping("/faultInjectionFeignModel")
public PojoModel faultInjectionFeignModel() {
return feignService.faultInjectionModel();
}

@RequestMapping("/retry")
public String retry(@RequestParam(name = "invocationID") String invocationID) {
return restTemplate.getForObject("http://price/retry?invocationID={1}", String.class, invocationID);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright (C) 2020-2022 Huawei Technologies Co., Ltd. All rights reserved.
* 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 com.huaweicloud.sample;

public class PojoModel {
private int num;

private String name;

public PojoModel() {

}

public PojoModel(int num, String name) {
this.num = num;
this.name = name;
}

public int getNum() {
return num;
}

public void setNum(int num) {
this.num = num;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ servicecomb:
matches:
- apiPath:
prefix: "/isolationForceOpen"
faultInjection: |
matches:
- apiPath:
prefix: "/faultInjection"
demo-rateLimiting: |
matches:
- apiPath:
Expand Down Expand Up @@ -99,3 +103,8 @@ servicecomb:
# failureRateThreshold: 20
isolationForceOpen: |
forceOpen: true
faultInjection:
faultInjection: |
fallbackType: ReturnNull
type: abort
percentage: 100
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@ public String sayHello() {
return "Hello world!";
}

@RequestMapping("/faultInjection")
public String faultInjection() {
return "success";
}

@RequestMapping("/faultInjectionModel")
public PojoModel faultInjectionModel() {
return new PojoModel(2, "hello");
}

@RequestMapping("/retry")
public String retry(HttpServletResponse response, @RequestParam(name = "invocationID") String invocationID) {
retryTimes.putIfAbsent(invocationID, 0);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright (C) 2020-2022 Huawei Technologies Co., Ltd. All rights reserved.
* 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 com.huaweicloud.sample;

public class PojoModel {
private int num;

private String name;

public PojoModel() {

}

public PojoModel(int num, String name) {
this.num = num;
this.name = name;
}

public int getNum() {
return num;
}

public void setNum(int num) {
this.num = num;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,18 @@ public class FallbackClientHttpResponse extends AbstractClientHttpResponse {

private final String message;

private final String contentType;

public FallbackClientHttpResponse(int code, String message) {
this.code = code;
this.message = message;
this.contentType = "application/text";
}

public FallbackClientHttpResponse(int code, String message, String contentType) {
this.code = code;
this.message = message;
this.contentType = contentType;
}

@Override
Expand All @@ -57,7 +66,7 @@ public InputStream getBody() {
@Override
public HttpHeaders getHeaders() {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add(HttpHeaders.CONTENT_TYPE, "application/text");
httpHeaders.add(HttpHeaders.CONTENT_TYPE, contentType);
return httpHeaders;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package com.huaweicloud.governance.adapters.feign;

import org.apache.servicecomb.governance.handler.FaultInjectionHandler;
import org.apache.servicecomb.governance.handler.InstanceIsolationHandler;
import org.apache.servicecomb.governance.handler.RetryHandler;
import org.apache.servicecomb.governance.handler.ext.ClientRecoverPolicy;
Expand All @@ -38,12 +39,13 @@ public class FeignConfiguration {
@ConditionalOnProperty(value = "spring.cloud.servicecomb.feign.governance.enabled",
havingValue = "true", matchIfMissing = true)
public Client feignClient(RetryHandler retryHandler,
FaultInjectionHandler faultInjectionHandler,
InstanceIsolationHandler instanceIsolationHandler,
@Autowired(required = false) ClientRecoverPolicy<Response> clientRecoverPolicy,
LoadBalancerClient loadBalancerClient,
LoadBalancerClientFactory loadBalancerClientFactory) {
return new RetryableFeignBlockingLoadBalancerClient(
retryHandler, instanceIsolationHandler, clientRecoverPolicy,
return new GovernanceFeignBlockingLoadBalancerClient(
retryHandler, faultInjectionHandler, instanceIsolationHandler, clientRecoverPolicy,
new Client.Default(null, null), loadBalancerClient,
loadBalancerClientFactory);
}
Expand Down
Loading

0 comments on commit 351dffd

Please sign in to comment.