返回介绍

快速入门

发布于 2024-08-18 11:12:34 字数 5188 浏览 0 评论 0 收藏 0

在开始使用Spring Cloud Hystrix实现断路器之前,我们先用之前实现的一些内容作为基础,构建一个如下图架构所示的服务调用关系。

我们在这里需要启动的工程有如下一些。

- eureka-server工程:服务注册中心,端口为1111。

- hello-service工程:HELLO-SERVICE的服务单元,两个实例启动端口分别为8081和8082。

- ribbon-consume工程:使用Ribbon实现的服务消费者,端口为9000。

在未加入断路器之前,关闭8081的实例,发送 GET 请求到http://localhost:9000/ribbon-consumer,可以获得下面的输出:

{

"timestamp": 1473992080343,

"status": 500,

"error": "Internal Server Error",

"exception": "org.springframework.web.client.ResourceAccessException",

"message": "I/O error on GET request for \"http://HELLO-SERVICE/hello\":Connection refused: connect; nested exception is java.net.ConnectException: Connection refused: connect",

"path": "/ribbon-consumer"

}

下面我们开始引入Spring Cloud Hystrix。

- 在 ribbon-consumer 工程的 pom.xml 的 dependency 节点中引入 springcloud-starter-hystrix依赖:

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-starter-hystrix</artifactId>

</dependency>

- 在 ribbon-consumer 工程的主类 ConsumerApplication 中使用@EnableCircuitBreaker注解开启断路器功能:

@EnableCircuitBreaker

@EnableDiscoveryClient

@SpringBootApplication

public class ConsumerApplication {

@Bean

@LoadBalanced

RestTemplate restTemplate(){

return new RestTemplate();

}

public static void main(String[]args){

SpringApplication.run(ConsumerApplication.class,args);

}

}

注意:这里还可以使用Spring Cloud应用中的@SpringCloudApplication注解来修饰应用主类,该注解的具体定义如下所示。可以看到,该注解中包含了上述我们所引用的三个注解,这也意味着一个Spring Cloud标准应用应包含服务发现以及断路器。

@Target({ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Inherited

@SpringBootApplication

@EnableDiscoveryClient

@EnableCircuitBreaker

public @interface SpringCloudApplication {

}

- 改造服务消费方式,新增HelloService类,注入RestTemplate实例。然后,将在ConsumerController中对RestTemplate的使用迁移到helloService函数中,最后,在helloService函数上增加@HystrixCommand注解来指定回调方法:

@Service

public class HelloService {

@Autowired

RestTemplate restTemplate;

@HystrixCommand(fallbackMethod="helloFallback")

public String helloService(){

return restTemplate.getForEntity("http://HELLO-SERVICE/hello",

String.class).getBody();

}

public String helloFallback(){

return "error";

}

}

- 修改 ConsumerController 类,注入上面实现的 HelloService 实例,并在helloConsumer中进行调用:

@RestController

public class ConsumerController {

@Autowired

HelloService helloService;

@RequestMapping(value="/ribbon-consumer",method=RequestMethod.GET)

public String helloConsumer(){

return helloService.helloService();

}

}

下面,我们来验证一下通过断路器实现的服务回调逻辑,重新启动之前关闭的8081端口的Hello-Service,确保此时服务注册中心、两个Hello-Service以及RIBBONCONSUMER均已启动,访问http://localhost:9000/ribbon-consumer可以轮询两个HELLO-SERVICE并返回一些文字信息。此时我们继续断开8081的HELLO-SERVICE,然后访问http://localhost:9000/ribbon-consumer,当轮询到8081服务端时,输出内容为error,不再是之前的错误内容,Hystrix的服务回调生效。除了通过断开具体的服务实例来模拟某个节点无法访问的情况之外,我们还可以模拟一下服务阻塞(长时间未响应)的情况。我们对HELLO-SERVICE的/hello接口做一些修改,具体如下:

@RequestMapping(value="/hello",method=RequestMethod.GET)

public String hello()throws Exception {

ServiceInstance instance=client.getLocalServiceInstance();

//让处理线程等待几秒钟

int sleepTime=new Random().nextInt(3000);

logger.info("sleepTime:"+sleepTime);

Thread.sleep(sleepTime);

logger.info("/hello,host:"+instance.getHost()+",service_id:"+instance.getServiceId());

return "Hello World";

}

通过Thread.sleep()函数可让/hello接口的处理线程不是马上返回内容,而是在阻塞几秒之后才返回内容。由于Hystrix默认超时时间为2000毫秒,所以这里采用了0至3000的随机数以让处理过程有一定概率发生超时来触发断路器。为了更精准地观察断路器的触发,在消费者调用函数中做一些时间记录,具体如下:

@HystrixCommand(fallbackMethod="helloFallback",commandKey="helloKey")

public String hello(){

long start=System.currentTimeMillis();

//消费服务的逻辑

...

long end=System.currentTimeMillis();

logger.info("Spend time : "+(end-start));

return result.toString();

}

重新启动 HELLO-SERVICE 和 RIBBON-CONSUMER 的实例,连续访问http://localhost:9000/ribbon-consumer几次,我们可以观察到,当RIBBON-CONSUMER的控制台中输出的Spend time大于2000的时候,就会返回error,即服务消费者因调用的服务超时从而触发熔断请求,并调用回调逻辑返回结果。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文