1. HystrixCommand实战

1.1. 需求

  1. 由于前端公共调用入口接口代码,封装在单独的jar包,它不属于springCloud管理,所以不适合用注解的方式@HystrixCommand进行服务降级
  2. 这里直接通过HystrixCommand的原生实现方式,对服务进行服务降级限流

1.2. 代码

package com.zhiyis.common.command;

import com.alibaba.fastjson.JSON;
import com.netflix.hystrix.*;
import com.zhiyis.common.bean.bus.OtherFields;
import com.zhiyis.common.cache.HashMapCache;
import com.zhiyis.common.model.ErrorMsg;
import com.zhiyis.common.report.RequestReport;
import com.zhiyis.common.report.ResponseReport;
import com.zhiyis.common.service.TableService;
import com.zhiyis.common.service.TokenService;
import com.zhiyis.common.utils.ApplicationContextProvider;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.*; /**
* 断路器
*
* @author laoliangliang
* @date 2019/1/2 10:24
*/
public class RpcCommand extends HystrixCommand<ResponseReport> { private Logger logger = LoggerFactory.getLogger(this.getClass()); private TableService tableService; private ApplicationContextProvider applicationContextProvider; private TokenService tokenService; private String report;
private OtherFields fields;
private HttpServletRequest request; public RpcCommand(TableService tableService,
ApplicationContextProvider applicationContextProvider,
TokenService tokenService,
String report, OtherFields fields, HttpServletRequest request) {
super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("rpcGroup"))
.andCommandKey(HystrixCommandKey.Factory.asKey("rpcCommand"))
.andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("rpcThreadPool"))
.andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(3000)));
this.tableService = tableService;
this.applicationContextProvider = applicationContextProvider;
this.tokenService = tokenService;
this.report = report;
this.fields = fields;
this.request = request;
} @Override
protected ResponseReport run() throws Exception {
logger.info("The report received :" + report);
RequestReport requestReport = JSON.parseObject(report, RequestReport.class);
requestReport.setOtherFields(fields);
String name = Thread.currentThread().getName();
long start = System.currentTimeMillis();
String rand = start + String.valueOf((new Random()).nextInt(10));
logger.info("—————————————" + rand + "启动线程:" + name + "————————————————————");
ResponseReport responseReport = new ResponseReport();
logger.info("The requestReport is:" + report);
logger.debug("The body is:{}", requestReport.getBody());
logger.debug("The sign is:{}", requestReport.getHeader().getSign());
String traCode = requestReport.getHeader().getTra_code();
if (traCode.isEmpty()) {
responseReport = responseReport.returnError(ErrorMsg.TRADE_CODE_IS_EMPTY, requestReport);
} else {
Map<String, Object> rpcMap = HashMapCache.RPC_INFO.get(traCode);
if (rpcMap != null) {
//判断是否需要校验Token
if (rpcMap.get("is_token_check") != null && String.valueOf(rpcMap.get("is_token_check")).equals("1")) {
String token = requestReport.getHeader().getToken();
if (StringUtils.isEmpty(token)) {
responseReport = responseReport.returnError(ErrorMsg.TOKEN_IS_EMPTY, requestReport);
return responseReport;
} else {
switch (tokenService.checkToken(token)) {
case 0:
responseReport = responseReport.returnError(ErrorMsg.TOKEN_IS_INVALID, requestReport);
return responseReport;
case 2:
responseReport = responseReport.returnError(ErrorMsg.TOKEN_TRA_CODE_NOT_CONIG, requestReport);
return responseReport;
}
}
}
String tableName = (String) rpcMap.get("tb_name");
switch ((int) rpcMap.get("rpc_type")) {
// 增加单条记录
case 1:
responseReport = tableService.addRecord(rpcMap, tableName, requestReport);
break;
// 获取单条记录
case 2:
responseReport = tableService.getRecord(Arrays.asList(((String) rpcMap.get("query_fields")).split(",")), tableName, requestReport);
break;
// 获取多条记录
case 3:
responseReport = tableService.getRecords(Arrays.asList(((String) rpcMap.get("query_fields")).split(",")), tableName, requestReport);
break;
// 修改记录
case 4:
responseReport = tableService.updateRecord(tableName, ((String) rpcMap.get("query_fields")).split(","), requestReport);
break;
// 自定义接口
case 5:
Object clazz = applicationContextProvider.getBean((String) rpcMap.get("class_name"));
String methodName = (String) rpcMap.get("class_func_name");
Method method = ReflectionUtils.findMethod(clazz.getClass(), methodName, RequestReport.class);
responseReport = (ResponseReport) ReflectionUtils.invokeMethod(method, clazz, requestReport);
break;
// 获取单条记录自定义SQL
case 6:
responseReport = tableService.getSingleRecordBySQL((String) rpcMap.get("sql_text"), requestReport);
break;
// 获取多条记录自定义SQL
case 7:
responseReport = tableService.getMultipleRecordBySQL((String) rpcMap.get("sql_text"), requestReport);
break;
// 单文件上传的自定义接口
case 8:
MultipartFile file = null;
try {
Map<String, MultipartFile> fileMap = ((MultipartHttpServletRequest) request).getFileMap();
if (fileMap != null && fileMap.size() != 0) {
file = fileMap.values().iterator().next();
}
} catch (ClassCastException e) {
logger.info("未提供图片");
}
Object clazz2 = applicationContextProvider.getBean((String) rpcMap.get("class_name"));
String methodName2 = (String) rpcMap.get("class_func_name");
Method method2 = ReflectionUtils.findMethod(clazz2.getClass(), methodName2, RequestReport.class, MultipartFile.class);
responseReport = (ResponseReport) ReflectionUtils.invokeMethod(method2, clazz2, requestReport, file);
break;
// 单个或多文件上传的自定义接口
case 9:
List<MultipartFile> fileList = new LinkedList<>();
try {
MultiValueMap<String, MultipartFile> multiFileMap = ((MultipartHttpServletRequest) request).getMultiFileMap();
for (String key : multiFileMap.keySet()) {
for (int i = 0; i < multiFileMap.get(key).size(); i++) {
MultipartFile multipartFile = multiFileMap.get(key).get(i);
fileList.add(multipartFile);
}
}
} catch (ClassCastException e) {
logger.info("未提供图片");
}
Object clazz3 = applicationContextProvider.getBean((String) rpcMap.get("class_name"));
String methodName3 = (String) rpcMap.get("class_func_name");
Method method3 = ReflectionUtils.findMethod(clazz3.getClass(), methodName3, RequestReport.class, List.class);
responseReport = (ResponseReport) ReflectionUtils.invokeMethod(method3, clazz3, requestReport, fileList);
break;
default:
break;
}
logger.info("The responseResult is:" + JSON.toJSONString(responseReport));
}
}
long end = System.currentTimeMillis();
long term = end - start;
logger.info("—————————————" + rand + "结束线程:" + name + ",耗时:" + term + "ms——————————————");
return responseReport;
} @Override
protected ResponseReport getFallback() {
Throwable e = getExecutionException();
if (e != null) {
logger.error("rpc 异常",e);
}
RequestReport requestReport = JSON.parseObject(report, RequestReport.class);
ResponseReport responseReport = new ResponseReport();
return responseReport.returnError("9999", "服务器繁忙,请稍后再试", requestReport);
} }

这里做个参考,该代码包含了基本配置和异常处理(这里只是打印了下日志)

1.3. 使用


@ResponseBody
@RequestMapping(value = "/rpc.api")
public ResponseReport doRemoteCall(@RequestParam(required = false) String report, OtherFields fields, HttpServletRequest request) {
RpcCommand rpcCommand = new RpcCommand(tableService, applicationContextProvider, tokenService,
report,fields,request);
return rpcCommand.execute();
}

HystrixCommand实战的更多相关文章

  1. Hystrix请求命令 HystrixCommand、HystrixObservableCommand

    Hystrix有两个请求命令 HystrixCommand.HystrixObservableCommand. HystrixCommand用在依赖服务返回单个操作结果的时候.又两种执行方式  -ex ...

  2. SpringCloud实战-Hystrix请求熔断与服务降级

    我们知道大量请求会阻塞在Tomcat服务器上,影响其它整个服务.在复杂的分布式架构的应用程序有很多的依赖,都会不可避免地在某些时候失败.高并发的依赖失败时如果没有隔离措施,当前应用服务就有被拖垮的风险 ...

  3. SpringCloud(6)---熔断降级理解、Hystrix实战

    SpringCloud(6)---熔断降级理解.Hystrix实战 一.概念 1.为什么需要熔断降级 (1)需求背景 它是系统负载过高,突发流量或者网络等各种异常情况介绍,常用的解决方案. 在一个分布 ...

  4. springcloud微服务实战:Eureka+Zuul+Feign/Ribbon+Hystrix Turbine+SpringConfig+sleuth+zipkin

    相信现在已经有很多小伙伴已经或者准备使用springcloud微服务了,接下来为大家搭建一个微服务框架,后期可以自己进行扩展.会提供一个小案例: 服务提供者和服务消费者 ,消费者会调用提供者的服务,新 ...

  5. SpringCloud实战3-Hystrix请求熔断与服务降级

    我们知道大量请求会阻塞在Tomcat服务器上,影响其它整个服务.在复杂的分布式架构的应用程序有很多的依赖,都会不可避免地在某些时候失败.高并发的依赖失败时如果没有隔离措施,当前应用服务就有被拖垮的风险 ...

  6. 微服务SpringCloud+Docker入门到高级实战(教程详情)

    第一章 课程介绍和学习路线 1.微服务架构SpringCloud课程介绍 简介:课程介绍和课程大纲讲解,讲课风格和重点内容理解技巧 2.技术选型和学后水平 简介:课程所需基础和技术选型讲解,学完课程可 ...

  7. spring-cloud-kubernetes的服务发现和轮询实战(含熔断)

    本文是<spring-cloud-kubernetes实战系列>的第四篇,主要内容是在kubernetes上部署两个应用:Web-Service和Account-Service,通过spr ...

  8. springcloud微服务实战:Eureka+Zuul+Ribbon+Hystrix+SpringConfig

    原文地址:http://blog.csdn.net/yp090416/article/details/78017552 springcloud微服务实战:Eureka+Zuul+Ribbon+Hyst ...

  9. Hystrix原理与实战

    Hystrix原理与实战 背景 分布式系统环境下,服务间类似依赖非常常见,一个业务调用通常依赖多个基础服务. 比如:订单服务调用商品服务,商品服务调用库存服务. 对于同步调用,当库存服务不可用时,商品 ...

随机推荐

  1. window下maven的环境搭建

    一.下载 官网下载地址 二.maven的安装配置 1.环境变量的配置 1)新建环境变量MAVEN_HOME,值如下: D:\install\develop\apache-maven- 2)修改环境变量 ...

  2. vscode和gitee的使用

    1.安装git 2.生成公钥 $ ssh-keygen -t rsa -C "youremail@youremail.com" # Generating public/privat ...

  3. 人脸检测(1)——HOG特征

    一.概述 前面一个系列,我们对车牌识别的相关技术进行了研究,但是车牌识别相对来说还是比较简单的,后续本人会对人脸检测.人脸识别,人脸姿态估计和人眼识别做一定的学习和研究.其中人脸检测相对来说比较简单, ...

  4. Java 字符编码(二)Java 中的编解码

    Java 字符编码(二)Java 中的编解码 java.nio.charset 包中提供了一套处理字符编码的工具类,主要有 Charset.CharsetDecoder.CharsetEncoder. ...

  5. Sum of Subsequence Widths LT891

    Given an array of integers A, consider all non-empty subsequences of A. For any sequence S, let the  ...

  6. C# BitArray 二进制处理

    int k = 6; byte[] bytearr = BitConverter.GetBytes(k); BitArray myBA = new BitArray(bytearr); for (in ...

  7. mysql 字段指定值靠前排序方法,多字段排序排序方法

    背景:SEO下选择某查询条件 查询展示信息为装修设计师以及设计师作品.设计师原型设计为:选择某风格 例如:简约,则列表出现拥有简约风格的设计师信息以及该设计师类型为简约的作品(3条靠前记录) 浏览原型 ...

  8. O365 Manager Plus帮助台委派功能一览表

    O365 Manager Plus帮助台委派介绍 虽然Office 365允许您在全球任何地方工作,但它提供的管理功能十分不足.当一个组织分布在多个国家/地区时,一个管理员很难单独管理所有用户和邮箱. ...

  9. C#中一些关联名词的含义归纳

    形参/实参:定义一个方法,方法中需要传输的参数为形参,实际调用方法时候传入的参数为实参. 方法/函数:两个没有本质上的区别,都是指类中的一些操作. 委托/事件:委托(delegate)是存有对某个方法 ...

  10. temp--贵州银行

    -------住宿----泊乐酒店----8905----与朱聿一起住 2018年  1月3日晚 1月4日晚  1月5日晚 1月6日晚  1月7日晚 1月8日晚  1月9日晚 已结清! ======= ...