spring系列-动态注册bean

注册过程

1、注册定时任务,每隔60秒执行一次

@Component
@EnableScheduling
public class CacheTaskVersionMapScan implements SchedulingConfigurer {
	@Resource
	private CacheversionTask cacheVersionTask;
	@Resource
	private LogicCalcBeanLoadingTask logicCalcBeanLoadingTask;
	@Resource
	private LogicTaskTrigger logicTaskTrigger;
	@Resource
	private TaskTrigger taskTrigger;
	@Override
	public void configureTasks(ScheduledTaskRegistrar taskRegistrar){
		taskRegistrar.addTriggerTask(cacheVersionTask,taskTrigger);
		taskRegistrar.addTriggerTask(logicCalcBeanLoadingTask,logicTaskTrigger);
	}
}

public static String getLogicLoadingTaskCron(){
	String cronText "0 * * * * ?";
	//通过MCC修改cronText实现动态定时更新
	return cronText;
}

2、扫描DB中的配置信息

QOverride
public void run(){
	//是否更新开关
	if(!MccConfigutil.LoadLogicCalcThriftInterface()){
		return;
	}
	//从缓存中加载需要处理的Bean而非查询缓存,此步骤可以换成直接查缓存
	List<DynLogicBean>allUsingLogicBeans loadLogicService.getUsingBeans();
	//没有配置任何信息直接跳过
	if(CollectionUtils.isEmpty(allUsingLogicBeans)){
		return;
	}

	//得到ApplicationContext中的DefaultListableBeanFactory
	GenericApplicationContext context = (GenericApplicationContext)ApplicationContextServiceUtil.getContext();
	DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory)context.getBeanFactory();

	//admin端保证beanname在新建之后不能修改,否则会有很多垃圾bean清理不掉
	for(DynLogicBean dynLogicBean allUsingLogicBeans){
		//如果spring中注册过,并且版本spring==db,直接跳过
		//没有跳过的这些配置要么是新增加的要么是更新过的,直接重新注册即可
		defaultListableBeanFactory.registerBeanDefinition(dynLogicBean.getBeanName(), beanDefinitionBuilder.getRawBeanDefinition());
		//原来的做法是卸载:defaultListableBeanFactory.removeBeanDefinition(dynLogicBean.getBeanName());
	}
}

3、如何解析BD

// 通过BeanDefinitionBuilder创建bean定义
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(ThriftClientProxy.class);
beanDefinitionBuilder.setDestroyMethodName("destroy");
// 添加属性
// 添加必须属性
beanDefinitionBuilder.addPropertyValue("serviceInterface", CMigSupplyCalcThriftService.class);
beanDefinitionBuilder.addPropertyValue("timeout", dynLogicBean.getTimeout());
beanDefinitionBuilder.addPropertyValue("serverDynamicWeight", dynLogicBean.getServerDynamicWeight());
beanDefinitionBuilder.addPropertyValue("appKey", dynLogicBean.getAppkey());
beanDefinitionBuilder.addPropertyValue("remoteAppkey", dynLogicBean.getRemoteAppkey());
beanDefinitionBuilder.addPropertyValue("remoteServerPort", dynLogicBean.getRemoteServerPort());
// 链接属性设置,默认米格的thrift链接数设置
String configBeanName = "wmFilterThriftPoolConfig";
if(dynLogicBean.getUseConnConfig()) {//使用自定义的ThriftPoolConfig,并且如果启用了,admin端保证maxActive,maxIdle等不能为空
    configBeanName = dynLogicBean.getBeanName() + configBeanSuffix;
    if(context.containsBean(configBeanName)) {//有config,清理掉,重新加载,能走到这个逻辑里来,说明供给计算bean本身版本已经变化了
        defaultListableBeanFactory.removeBeanDefinition(configBeanName);
    }
    BeanDefinitionBuilder configBuilder = BeanDefinitionBuilder.genericBeanDefinition(MTThriftPoolConfig.class);
    configBuilder.addPropertyValue("maxActive", dynLogicBean.getMaxActive());
    configBuilder.addPropertyValue("maxIdle", dynLogicBean.getMaxIdle());
    configBuilder.addPropertyValue("minIdle", dynLogicBean.getMinIdle());
    configBuilder.addPropertyValue("maxWait", dynLogicBean.getMaxWait());
    configBuilder.addPropertyValue("testOnBorrow", dynLogicBean.getTestOnBorrow());
    configBuilder.addPropertyValue("testOnReturn", dynLogicBean.getTestOnReturn());
    configBuilder.addPropertyValue("testWhileIdle", dynLogicBean.getTestWhileIdle());
    //加载ThriftPoolConfig bean
    defaultListableBeanFactory.registerBeanDefinition(configBeanName, configBuilder.getRawBeanDefinition());
}
// 如果没开启,使用默认的名字是 wmFilterThriftPoolConfig 如果开启了,使用的名字是 dynLogicBean.getBeanName() + configBeanSuffix;
beanDefinitionBuilder.addPropertyReference("mtThriftPoolConfig", configBeanName);
//!!!预留了支持异步的参数,但建议暂时不启用,因为对方完全可能随时吧async属性从true改为false,在供给计算中先取配置,再判断是否是异步调用,很浪费时间,没必要
if (dynLogicBean.getSupportAsync()) {
    beanDefinitionBuilder.addPropertyValue("async", dynLogicBean.getAsync());
    beanDefinitionBuilder.addPropertyValue("nettyIO", dynLogicBean.getNettyIo());
}
//注册
defaultListableBeanFactory.registerBeanDefinition(dynLogicBean.getBeanName(), beanDefinitionBuilder.getRawBeanDefinition());

如何在BD上绑定Hystrix的信息?

/更改Hystrix链接属性
//ConfigurationManager.getConfigInstance().setProperty方法中有synchronized,绝对不能在运行时线程中调用该方法
//HystrixServiceProxy(的构造器)中的commandkey就是以beanname命名的
if(HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE.equals(dynLogicBean.getExecutionIsolationStrategy()))
ConfigurationManager.getConfigInstance().setProperty("hystrix.command."dynLogicBean.getBeanName()+".execution.isolation.strategy",Hystr
ConfigurationManager.getConfigInstance().setProperty("hystrix.command."+dynLogicBean.getBeanName()+".execution.isolation.semaphore.maxCon
ConfigurationManager.getConfigInstance().setProperty("hystrix.command."+dynLogicBean.getBeanName()+".execution.isolation.thread.timeoutIn
ConfigurationManager.getConfigInstance().setProperty("hystrix.command."+dynLogicBean.getBeanName()+".circuitBreaker.errorThresholdPercent
}eLse{//线程池方式为默认方式
ConfigurationManager.getConfigInstance().setProperty("hystrix.command."dynLogicBean.getBeanName()+".execution.isolation.strategy",Hystr
ConfigurationManager.getConfigInstance().setProperty("hystrix.command."dynLogicBean.getBeanName()+".execution.isolation.thread.timeoutIn
ConfigurationManager.getConfigInstance().setProperty("hystrix.command."+dynLogicBean.getBeanName()+".circuitBreaker.errorThresholdPercent
}

调用关系

DynamicIOCCalculationEngine
1、获取动态bean的定义

@Override
public SupplyResult calculateSupply(RawData rawData){
	// 1、上下文中会包含逻辑类型
	ThirdPartyCalcConfig tpcc rawData.getTpcc();
	int logicTypeCode tpcc.getLogicTypeCode();
	DynLogicBean LogicBean = getCalcBeanByLogicCode(LogicTypeCode);
	if(logicBean!=nuLL){
		WmCMigSupplyCalcRequest request new WmCMigSupplyCalcRequest();
		request.setclient(tpcc.getclient());
		request.setVersion(tpcc.getVersionstr());
		request.setCityId(tpcc.getcityId());
		request.setDistrictId(tpcc.getDistrictId());
		request.setLat(tpcc.getLat());
		request.setLng(tpcc.getLng());
		request.setUserId(tpcc.getUserId());
		request.setUvid(tpcc.getUuid());
		reqvest.setPoiIdList(tpcc.getPoiIdList());
		//2、使用hystrix进行包装,供给计算
		HystrixServiceProxy hystrixServiceProxy = new HystrixServiceProxy(logicBean.getBeanName(),request);
		WmCMigSupplyCalcResponse response hystrixServiceProxy.execute();
	}
}

2、与Hystrix组合

class HystrixServiceProxy extends HystrixCommand<WmCMigSupplyCalcResponse>{
	public HystrixServiceProxy(String name,WmCMigSupplyCalcRequest request){
		super(
			Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(name:name "Group"))
				.andCommandKey(HystrixCommandKey.Factory.asKey(name))
		);
		this.request request;
	}
}


@Override
protected WmCMigSupplyCalcResponse getFallback(){
	WmCMigSupplyCalcResponse fallbackResponse = new WmCMigSupplyCalcResponse();
	fallbackResponse.setHasSupply(false);
	return fallbackResponse;
}
@Override
protected WmCMigSupplyCalcResponse run()throws Exception{
	WmCMigSuppLyCalcResponse response nuLL;
	try{
		//**通过beanName得到动态注册的bean**
		CMigSupplyCalcThriftService.Ifaceiface = ApplicationContextServiceutil.getSupplyCalcServiceByBeanName(this.name);
		if(iface !null){
		//供给计算
		response iface.calcSupply(this.request);
	} catch (Exception e){
		Logger.error(format:"HystrixServiceProxy run error",e);
		return response;
	}
}

调用梳理
1、api会传入聚类,聚类上会绑定logicType的值

	ThirdPartyCalcConfig tpcc rawData.getTpcc();
	int logicTypeCode tpcc.getLogicTypeCode();
	DynLogicBean LogicBean = getCalcBeanByLogicCode(LogicTypeCode);

2、用logicType在缓存中查找DB中的配置信息

private LoadingCache<string,Pair<List<DynLogicBean>,List<LogicType>>>calcUsingBeansCache = CacheBuilder.newBuilder()
	expireAfterWrite(duration:10,TimeUnit.MINUTES)
	refreshAfterWrite(MccConfigUtil.LogicLoadingCacheRefreshTime(TimeUnit.SECONDS)
	.maximumSize(10000build(new CacheLoader<String,Pair<List<DynLogicBean>,List<LogicType>>>(){
	aOverride
	public Pair<List<DynLogicBean>,List<LogicType>>Load(String key)throws Exception
	return Pair.of(LoadLogicDao.getUsingBeans(),LoadLogicDao.getALlLogicType());

3、创建HystrixServiceProxy,每次请求都会创建一个新的该对象是否影响性能,影响不大,因为Hystrix的底层就是https://www.cnblogs.com/frankcui/p/15249295.html 执行HystrixServiceProxy对象 HystrixCommand 的创建时机

HystrixServiceProxy hystrixServiceProxy = new HystrixServiceProxy(logicBean.getBeanName(),request);
WmCMigSupplyCalcResponse response = hystrixServiceProxy.execute();

4、在HystrixServiceProxy的run方法中通过beanName找到动态注册的服务对象

CMigSupplyCalcThriftService.Iface iface = ApplicationContextServiceutil.getSupplyCalcServiceByBeanName(this.name);
if(iface !null){
	response iface.calcSupply(this.request);
}

5、注解原理解析

    @HystrixCommand(groupKey = "CbaseFilterService",commandKey = "calcPolicySupply",fallbackMethod = "calcPolicySupplyFallback",
            commandProperties = {
                    @HystrixProperty(name = HystrixPropertiesManager.EXECUTION_ISOLATION_STRATEGY, value = "THREAD"),
                    @HystrixProperty(name = HystrixPropertiesManager.EXECUTION_ISOLATION_THREAD_TIMEOUT_IN_MILLISECONDS, value = "60"),
                    @HystrixProperty(name=HystrixPropertiesManager.CIRCUIT_BREAKER_ERROR_THRESHOLD_PERCENTAGE,value = "10")
            },
            threadPoolProperties = {
                    @HystrixProperty(name = HystrixPropertiesManager.CORE_SIZE, value = HystrixCons.CBaseFilterHystrixConfig.THREAD_POOL_CORE_SIZE)
            }
    )
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值