微服务项目中增加多数据源功能出现与Hystrix冲突的问题
**下图 1图是正常访问从库数据,2图是查询从库数据失败查询成主库了 请问大家怎么样让多数据源兼容Hystrix
**
先看一下问题图片
1、能够正常访问从库的操作 查询从库数据
2、错误查询从库Hystrix的注释没去掉 查询出来的数据是主库数据
代码部分
@DataSource("slave") // 指定从库
@GetMapping("/OperatePopularDoListx")
@HystrixCommand(fallbackMethod = "OperatePopularDoList")
public List<OperatePopularDo> OperatePopularDoListx() {
QueryWrapper wrapper = new QueryWrapper();
wrapper.eq("STATUS", 0);
wrapper.orderByDesc("order_num");
List<OperatePopularDo> list = operatePopularService.list(wrapper);
return list;
}
多数据源切换用的是aop去环绕切的代码如下
package com.chinalife.gstc.commons.aop;
import com.alibaba.druid.pool.DruidDataSource;
import com.chinalife.gstc.commons.config.DruidConfig;
import com.chinalife.gstc.commons.datasource.CommonConstant;
import com.chinalife.gstc.commons.datasource.DynamicDataSourceHolder;
import com.chinalife.gstc.commons.utils.SpringUtil;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.*;
@Aspect
@Component
@Slf4j
public class DataSourceAspect {
// 设置DataSource注解的切点表达式
@Pointcut("execution(public * com.chinalife.gstc.controller..*.*(..))")
public void dynamicDataSourcePointCut(){
}
//环绕通知
@Around("dynamicDataSourcePointCut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
DataSource defineAnnotation = getDefineAnnotation(joinPoint);
HystrixRequestContext context = HystrixRequestContext.initializeContext();
String key = "";
//判断方法上是否有注解,没有注解则默认是走的是主服务器
if (defineAnnotation == null) {
key = CommonConstant.MASTER;
}else {
key = defineAnnotation.value();
}
//判断数据库是否断开连接
key = getConnection(key);
System.err.println(" 当前使用: "+key);
DynamicDataSourceHolder.setDynamicDataSourceKey(key);
Object proceed = null;
try {
proceed = joinPoint.proceed();
} finally {
context.shutdown();
DynamicDataSourceHolder.removeDynamicDataSourceKey();
}
return proceed;
}
/**
* 先判断方法的注解,后判断类的注解,以方法的注解为准
* @param joinPoint
* @return
*/
private DataSource getDefineAnnotation(ProceedingJoinPoint joinPoint){
// 获取访问信息
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
// 获取方法上的注解
DataSource dataSourceAnnotation = methodSignature.getMethod().getAnnotation(DataSource.class);
// 方法上无注解则抛空指针 nonNull
if (Objects.nonNull(dataSourceAnnotation)) {
return dataSourceAnnotation;
} else {
// 获取类上的注解 返回类
Class<?> dsClass = joinPoint.getTarget().getClass();
return dsClass.getAnnotation(DataSource.class);
}
}
/**
* 判断数据库是否连接成功
* @return
*/
private String getConnection(String target) throws SQLException {
//将数据源名称添加到list集合,方便后续操作
List<String> dataSources = new ArrayList<>();
dataSources.add(CommonConstant.SLAVE);
dataSources.add(CommonConstant.MASTER);
//获取装配好的bean对象
DruidConfig druidConfig = (DruidConfig) SpringUtil.getBean("druidConfig");
DruidDataSource druidDataSource = new DruidDataSource();
if (target.equals(CommonConstant.SLAVE)) {
druidDataSource = (DruidDataSource) druidConfig.slaveDataSource();
}
if (target.equals(CommonConstant.MASTER)) {
druidDataSource = (DruidDataSource) druidConfig.masterDataSource();
}
System.err.println("配置:"+target);
try {
Connection connection = DriverManager.getConnection(druidDataSource.getUrl(), druidDataSource.getUsername(), druidDataSource.getPassword());
if (connection != null && !connection.isClosed()) {
System.out.println("数据库连接成功!");
} else {
System.out.println("数据库连接异常!");
}
} catch (SQLException e) {
System.out.println("数据库连接失败-"+target+":" + e.getMessage());
dataSources.remove(target);
// shuffle 打乱顺序
Collections.shuffle(dataSources);
// 再选择一个新的数据源
String changeTarget = dataSources.get(0);
// 再次尝试连接数据源
getConnection(changeTarget);
log.info("========================数据源:{}连接异常,切换数据源为:{}===========================",target,changeTarget);
return changeTarget;
}
log.info("数据源结束");
return target;
}
}