`

springcloud feign监听启动调用服务熔断问题处理

阅读更多
spring cloud 版本:Edgware.SR2 

问题: 使用feign注册eurka服务在监听器中调用

package com.listener;

import java.util.concurrent.Executors;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.xx.charge.facade.client.BusinessClient;
import com.xx.framework.util.SnowflakeIdWorkerUtils;
import com.xx.framework.util.StringUtils;
import com.xx.getway.app.common.Global;

import lombok.extern.slf4j.Slf4j;

@Component
@Slf4j
public class LoadDataListener implements ServletContextListener {
	@Autowired
	private BusinessClient businessClient;
	@Override
	public void contextInitialized(ServletContextEvent sce) {
		businessClient.loadData();	}
	@Override
	public void contextDestroyed(ServletContextEvent sce) {
	}
}
=================================================================
@FeignClient(value = "app",fallback=AppStartClientFallback.class)
public interface AppStartClient {
	 @RequestMapping(value = "/app/loadData")
	 ResponseInfo loadData();
}
@Slf4j
@Component
class AppStartClientFallback implements AppStartClient{
        @Override
 	public ResponseInfo loadData() {
  	   log.error("数据进入服务消费者降级处理");
	   return ResponseInfo.error("数据进入服务消费者降级处理");
        }
}

=====================================================

@EnableDiscoveryClient
@SpringBootApplication(exclude = { MongoAutoConfiguration.class,
  MongoDataAutoConfiguration.class }, scanBasePackages = { "com.xx.bsp.getway.app","com.xx.bsp.charge.facade.client" })
@EnableFeignClients // 启用feign
@ImportResource(locations = { "classpath:/applicationContext.xml" })
@ServletComponentScan(basePackageClasses = { LoadDataListener.class })
public class Application {
}
==================================================
问题:项目启动 始终是会进入熔断,然后在调用目标方法。

原因:监听器在springcloud加载配置文件HystrixCommandProperties之前就调用目标方法,
     监听器的方法调用默认为1秒 超过这个时间自定会进入熔断fallback方法。 真正的Hystrix还未起作用
这个时候还是会调用目标方法。

解决办法:不用servlet监听。

需要在容器启动的时候执行一些内容。比如读取配置文件,数据库连接之类的。
SpringBoot给我们提供了两个接口来帮助我们实现这种需求。
这两个接口分别为CommandLineRunnerApplicationRunner。
他们的执行时机为容器启动完成的时候。

@Component
@Slf4j
public class InitDataApplicationRunner implements ApplicationRunner {
 @Autowired
 private AppStartClient appStartClient;
 @Override
 public void run(ApplicationArguments args) throws Exception {
   long startTime = System.currentTimeMillis();// 开始时间
   log.info("getway redis开始初始化!");
   
   ResponseInfo response=appStartClient.loadData();
   
   long endTime = System.currentTimeMillis();// 结束时间
   float excTime = (float) (endTime - startTime) / 1000;
   if(response.isSuccess()){
    log.info("getway redis初始化完成!,执行时间: {}s", excTime);
   }else{
    log.error("getway redis初始化失败!,执行时间: {}s", excTime,response.getMessage());
   }
 }

package com.jb.mpc.equipmemnt.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import com.jb.mpc.controller.EquipmentController;
/**
 * @see @Order注解的执行优先级是按value值从小到大顺序。
 * @author pangps
 * @version v1.0
 * @date 2017年7月24日
 * 
 */
@Component
@Order(value=1)
public class MyApplicationRunner implements ApplicationRunner{
 
 private static final Logger logger = LoggerFactory.getLogger(MyApplicationRunner.class);
 
 @Override
 public void run(ApplicationArguments args) throws Exception {
  logger.info("==服务启动后,初始化数据操作==");
 }
}


package com.jb.mpc.equipmemnt.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
 * @see @Order注解的执行优先级是按value值从小到大顺序。
 * @author pangps
 * @version v1.0
 * @date 2017年7月24日
 * 
 */
@Component
@Order(value=2)
public class MyCommandLineRunner implements CommandLineRunner{
 
 private static final Logger logger = LoggerFactory.getLogger(MyCommandLineRunner.class);
    @Override
    public void run(String... args) throws Exception {
     logger.info("==服务启动执行,执行加载数据等操作==");
    }
}

说明:

1、@Order注解
如果有多个实现类,而你需要他们按一定顺序执行的话,可以在实现类上加上@Order注解。@Order(value=整数值)。SpringBoot会按照@Order中的value值从小到大依次执行。
2、如果你发现你的实现类没有按照你的需求执行,请看一下实现类上是否添加了Spring管理的注解(@Component)。

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics