博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
升级微服务架构4:断路器
阅读量:5273 次
发布时间:2019-06-14

本文共 5560 字,大约阅读时间需要 18 分钟。

   断路器是电路中的一个保护电路安全的开关,当电路出现短路时,断路器会自动跳闸,防止出现电路故障。

  一个微服务架构的系统中也需要这种保护装置,当消费者调用某一个服务的时候,如当前的服务有异常,譬如服务已经挂了,这时候就需要断路器来把当前调用的服务断开,Spring Cloud中集成的断路器组件为:Hystrix。如图所示,Hystrix在调用服务失败的情况下会进行回退或者降级处理,比如快速失败、无声失败、返回默认值、自己组装一个返回值、利用远程缓存、主次方式回退等回退类型。

  降级回退相关资料:

  

  以上一章的调用用户服务为例,先实现Java端的再移植到.net core

  1.服务调用设置断路器java版

  在Spring Cloud官方文档搜索断路器:Circuit Breaker

  参考:

  官方文档示例:

  

 

  1.1 添加断路器依赖

  断路器是在消费者调用时添加的,首先在orderservice上添加Hystrix依赖  

org.springframework.cloud
spring-cloud-starter-netflix-hystrix

  在启动类上添加@EnableCircuitBreaker注解来启用Hystrix

  1.2 指定调用失败退回方法

  在调用服务类UserService各个方法中添加回退错误的方法,并使用@HystrixCommand注解指定回退的方法 

@Servicepublic class UserService {    @Autowired    private RestTemplate restTemplate;    private String serviceUrl="http://userservice/user";    @HystrixCommand(fallbackMethod = "getAllError")    public List
getAll() { ParameterizedTypeReference
> responseType = new ParameterizedTypeReference
>(){}; ResponseEntity
> resp = restTemplate.exchange(serviceUrl+"/getall", HttpMethod.GET, null, responseType); List
list = resp.getBody(); return list; } @HystrixCommand(fallbackMethod = "getPortError") public String getPort(){ String msg = restTemplate.getForObject(serviceUrl+"/getport", String.class); return msg; } public User getByName(String name){ User user = restTemplate.getForObject(serviceUrl+"/getbyname?name="+name, User.class); return user; } //getAll回退方法 public List
getAllError() { return null; } //getPort回退方法 public String getPortError() { return "userservice服务断开,getPort方法调用错误!"; }}

  把userservice服务停掉,调用一下订单服务的获取端口方法,进入了错误方法了,说明已经成功设置回退方法。

  

  启动服务后,调用成功。

  

  

  1.3 设置超时时间

  如果调用一直进入回退方法,可能是Hystrix没设置超时时间,配置下超时时间即可。  

hystrix:  command:    default:      execution:        timeout:          enabled: true        isolation:          thread:            timeoutInMilliseconds: 10000 #设置超时时间 10秒

  

   2.服务调用设置断路器.net core版

   2.1 添加断路器引用

  首先在OrderService项目中添加Steeltoe.CircuitBreaker.HystrixCore引用

  

  2.2 创建Command类来指定退回方法

   在调用用户服务UserService类上继承HystrixCommand<string>

  官方文档:

  .net core版比较麻烦的是,不能直接在Service的方法上加特性来声明要回退的方法,而是每个方法要都用一个继承自HystrixCommand<>的泛型方法,泛型类型为方法返回的类型,然后再调用这个类的方法,Java版直接用注解还是方便很多。

  可以参考SteeltoeOSS的例子:

   

  两个Command类对应Service里面的两个方法。

  Command类我们按照服务名(去掉后面的Service)+方法名+Command来命名,方便确定是调用的那个方法,譬如获取所有用户的类:UsergetAllCommand。

  

using System.Collections.Generic;using System.Threading.Tasks;using Steeltoe.CircuitBreaker.Hystrix;namespace OrderService.Controllers{    public class UsergetAllCommand : HystrixCommand
> { private IUserService _userService; public UsergetAllCommand(IHystrixCommandOptions options,IUserService userService) : base(options) { _userService = userService; IsFallbackUserDefined = true; } public async Task
> getAll() { return await ExecuteAsync(); } protected override async Task
> RunAsync() { var result = await _userService.getAll(); return result; } ///
/// 回退方法 /// ///
protected override async Task
> RunFallbackAsync() { return null; } }}

  

  同样再创建一个getPort的命令类,然后在Startup类中的ConfigureServices配置HystrixCommand类的注入  

// 注册使用HystrixCommand类封装UserService方法做断路器的命令类    services.AddHystrixCommand
("userservice", Configuration); services.AddHystrixCommand
("userservice", Configuration);

  

  在OrderController中改为使用Command类来调用userservice的方法。  

[Route("[controller]")]    [ApiController]    public class OrderController : ControllerBase    {        private readonly IUserService _userService;        private readonly UsergetAllCommand _usergetAllCommand;        private readonly UsergetPortCommand _usergetPortCommand;        //构造方法来注入实例        public OrderController(IUserService userService            ,UsergetAllCommand usergetAllCommand            ,UsergetPortCommand usergetPortCommand)        {            _userService = userService;            _usergetAllCommand = usergetAllCommand;            _usergetPortCommand = usergetPortCommand;        }        [Route("getalluser")]        [HttpGet]        public async Task
> getAll() { //List
list = await _userService.getAll(); var list =await _usergetAllCommand.getAll(); return list; } [Route("getuserserviceport")] [HttpGet] public async Task
getUserServicePort() { //var port = await _userService.getPort(); var port = await _usergetPortCommand.getPort(); return port; } }

  停止userservice服务,成功调用回退方法。

  

  启动userservice服务后再刷新,成功获取到数据。

  

 

  2.3 设置超时时间  

{  "Logging": {    "LogLevel": {      "Default": "Warning"    }  },  "AllowedHosts": "*",  "spring": {    "application": {      "name": "orderservice"    }  },  "eureka": {    "client": {      "serviceUrl": "http://localhost:8881/eureka/",      "shouldRegisterWithEureka": true,      "shouldFetchRegistry": true    },    "instance": {      "port": 6660    }  },  "hystrix": {    "command": {      "default": {        "execution": {          "timeout": { "enabled": true },          "isolation": {            "thread": { "timeoutInMilliseconds" : 10000 }          }        }      }    }  }}

  至此断路器已添加完毕。  

转载于:https://www.cnblogs.com/townsend/p/9580371.html

你可能感兴趣的文章
Linux发行版的排行
查看>>
12010 解密QQ号(队列)
查看>>
2014年辛星完全解读Javascript第一节
查看>>
装配SpringBean(一)--依赖注入
查看>>
UESTC-我要长高 DP优化
查看>>
java选择文件时提供图像缩略图[转]
查看>>
方维分享系统二次开发, 给评论、主题、回复、活动 加审核的功能
查看>>
Matlab parfor-loop并行运算
查看>>
string与stringbuilder的区别
查看>>
2012-01-12 16:01 hibernate注解以及简单实例
查看>>
iOS8统一的系统提示控件——UIAlertController
查看>>
PAT甲级——1101 Quick Sort (快速排序)
查看>>
python创建进程的两种方式
查看>>
1.2 基础知识——关于猪皮(GP,Generic Practice)
查看>>
迭代器Iterator
查看>>
java易错题----静态方法的调用
查看>>
php建立MySQL数据表
查看>>
最简单的线程同步的例子
查看>>
旅途上看的电影和观后感
查看>>
qt实现类似QQ伸缩窗口--鼠标事件应用
查看>>