Skip to content

Commit

Permalink
#232 基于Hystrix的系统保护,Day2. 演示
Browse files Browse the repository at this point in the history
  • Loading branch information
calvin1978 committed Jul 4, 2013
1 parent 1d85ed2 commit ef4e6bc
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import javax.validation.ConstraintViolationException;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
Expand All @@ -15,7 +17,9 @@ public class RestExceptionHandler extends ResponseEntityExceptionHandler {

@ExceptionHandler(value = { ConstraintViolationException.class })
public final ResponseEntity<?> handleException(ConstraintViolationException ex, WebRequest request) {
return new ResponseEntity(BeanValidators.extractPropertyAndMessage(ex.getConstraintViolations()),
HttpStatus.BAD_REQUEST);
String body = BeanValidators.extractPropertyAndMessage(ex.getConstraintViolations()).toString();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.TEXT_PLAIN);
return handleExceptionInternal(ex, body, null, HttpStatus.BAD_REQUEST, request);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.springside.examples.showcase.demos.hystrix.resource;

import org.hibernate.service.spi.ServiceException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
Expand All @@ -18,7 +19,7 @@
*/
@Controller
public class ResourceController {
public static final int TIMEOUT = 20000;
public static final int TIMEOUT = 10000;

@Autowired
private AccountEffectiveService accountService;
Expand All @@ -39,7 +40,7 @@ public UserDTO getUser(@PathVariable("id") Long id) {
}

if ("fail".equals(HystrixController.status)) {
throw new RuntimeException("Server Exception");
throw new ServiceException("Server Exception");
}

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandKey;
import com.netflix.hystrix.HystrixCommandProperties;

public class GetUserCommand extends HystrixCommand<UserDTO> {

Expand All @@ -13,7 +15,20 @@ public class GetUserCommand extends HystrixCommand<UserDTO> {
private RestTemplate restTemplate = new RestTemplate();

protected GetUserCommand(Long id) {
super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));

super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"))
.andCommandKey(HystrixCommandKey.Factory.asKey("GetUserCommand"))
.andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
// 线程超时,默认为1秒,设为3秒,
.withExecutionIsolationThreadTimeoutInMilliseconds(3000)
// 至少多少请求在rolling window内发生,开始触发短路的计算,默认为20, 设为3
.withCircuitBreakerRequestVolumeThreshold(3)
// 多少百分比的fail在rolling windows内发生,计算为短路。默认为50%
.withCircuitBreakerErrorThresholdPercentage(50)
// 被置成短路后,多久才会重新尝试访问资源。默认为5秒,设为10秒
.withCircuitBreakerSleepWindowInMilliseconds(10000)
// rolling windows 长度,默认为10秒,设为20秒。
.withMetricsRollingStatisticalWindowInMilliseconds(20000)));
this.id = id;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,33 @@
package org.springside.examples.showcase.demos.hystrix.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springside.examples.showcase.webservice.rest.RestException;
import org.springside.examples.showcase.webservice.rest.UserDTO;

/**
* 使用Hystrix访问资源的服务。
*/
@Controller
public class ServiceController {
private static Logger logger = LoggerFactory.getLogger(ServiceController.class);

@RequestMapping(value = "/hystrix/service/{id}", method = RequestMethod.GET)
@ResponseBody
public UserDTO getUser(@PathVariable("id") Long id) {
GetUserCommand command = new GetUserCommand(id);
return command.execute();

try {
return command.execute();
} catch (Exception e) {
logger.error(e.getMessage(), e);
throw new RestException(HttpStatus.SERVICE_UNAVAILABLE);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.springside.examples.showcase.webservice.rest;

import org.springframework.http.HttpStatus;

public class RestException extends RuntimeException {

public HttpStatus status;

public RestException() {
}

public RestException(HttpStatus status) {
this.status = status;
}

public RestException(HttpStatus status, String message) {
super(message);
this.status = status;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.springside.examples.showcase.webservice.rest;

import javax.validation.ConstraintViolationException;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import org.springside.modules.beanvalidator.BeanValidators;

@ControllerAdvice
public class RestExceptionHandler extends ResponseEntityExceptionHandler {

@ExceptionHandler(value = { ConstraintViolationException.class })
public final ResponseEntity<?> handleException(ConstraintViolationException ex, WebRequest request) {
String body = BeanValidators.extractPropertyAndMessage(ex.getConstraintViolations()).toString();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.TEXT_PLAIN);
return handleExceptionInternal(ex, body, headers, HttpStatus.BAD_REQUEST, request);
}

@ExceptionHandler(value = { RestException.class })
public final ResponseEntity<?> handleException(RestException ex, WebRequest request) {
String body = ex.getMessage();

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.TEXT_PLAIN);

HttpStatus status = (ex.status != null) ? ex.status : HttpStatus.INTERNAL_SERVER_ERROR;

return handleExceptionInternal(ex, body, headers, status, request);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,17 @@

<body>
<h1>Hystrix 演示</h1>

<p><a href="https://github.com/Netflix/Hystrix" target="_blank">Netflix Hystrix</a> 是一个延迟与容错类库,通过独立访问远程系统、服务和第三方库的节点,在复杂的分布式系统里停止雪崩及提供恢复能力。</p>

<h2>当前资源状态为<%= HystrixController.status %></h2>
<ul>
<li><a href="${ctx}/story/hystrix/timeout">切换为Timeout</a></li>
<li><a href="${ctx}/story/hystrix/fail">切换为Fail</a></li>
<li><a href="${ctx}/story/hystrix/normal">切换为Normal</a></li>
</ul>


<h2>访问Hystrix服务</h2>
<a href="${ctx}/hystrix/service/1" target="_blank"> ${ctx}/hystrix/service/1</a>
</body>
</html>

0 comments on commit ef4e6bc

Please sign in to comment.