Spring Cloud eureka注册中心实例不可用,ribbon配置请求重试

 今天 在开发的时候,开发环境都 注册到服务中心,但是有些开发同事服务是不可用的,但是又设置了服务保护机制,实例仍然是up 的,在本地进行开发的时候,可以使用eureka.server.enable-self-preservation=false参数来关闭保护机制,以确保注册中心可以将不可用的实例正确剔除,因为有同事不关心这个,直接默认配置都是true,导致线上问题,就需要改变一下,如果发现服务实例不可用,或者异常自动转发其它实例上再执行,

  首生要加包   springooot 依赖的其它包就不贴出来了,主要容断器的包要添加上去

		<dependency>
		   <groupId>org.springframework.cloud</groupId>
		   <artifactId>spring-cloud-starter-hystrix</artifactId>
		</dependency>

在启动服务类里面,需要加些参数   SpringApplication.run(YitaiTMSApplication.class, args); 

@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
@Import(FdfsClientConfig.class)//可以拥有带有连接池的FastDFS Java客户端
@EnableTransactionManagement
@ServletComponentScan
@MapperScan("com.yitai.tms.*.dao")
@SpringBootApplication
@EnableEurekaClient
@EnableScheduling
@EnableDiscoveryClient
@EnableHystrix
public class YitaiTMSApplication {
	
    public static void main(String[] args) {
        SpringApplication.run(YitaiTMSApplication.class, args);
    }
    
//@EnableHystrix 这个是必须的, 开户容断器
 // @Primary  这个不是必须的,这个注入是如果注入相同实例,有这个关键字就优先注入
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
    	HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
		  httpRequestFactory.setReadTimeout(4000);
		  httpRequestFactory.setConnectTimeout(4000);
		return new RestTemplate(httpRequestFactory);
    }
// 设置访问时间和连接超时时间,默认的时间太长,配置后可以有效时间内转发服务注册实例请求

接下来是配置文件 application.yml 

#开启hystrix功能   这个功能是 feign方式调用秘,ribbon的配置与feign整合后配置设置参数一样
feign:
  hystrix:
    enabled: true
 
#tms-mrg:  如果加上这个配置,说明指定的微服务开启重试功能,不是自己的微服务名称,相当如局部服务重试
ribbon:
 # 同一实例最大重试次数,不包括首次调用,配置后本实例至少会执行两次
  MaxAutoRetries: 1
 # 重试其他实例的最大重试次数,不包括首次所选的server,配置后本实例和其它服务注册实例至少会执行两次
  MaxAutoRetriesNextServer: 2
 # 是否所有操作都进行重试
  OkToRetryOnAllOperations: false  #默认为false,则只允许GET请求被重试
 #如果此设置关闭, 所有重试机制都失效,注意:全局重试如局部重试开启,是本服务调用的所有微服务都开启重试,配置局部微服务名称才启作用此称为局部重试机制
 #下面两个时间我是指定在服务启动时设置的,如果不指定就在这里设置
  ReadTimeout: 5000   #请求时间,这个配置容断器的时间,必须小于容断器设置的时间才能触发重试
  ConnectTimeout: 2000  # 服务连接时间


对时间有特殊要求可以配置下面两个,
#开户服务重试机制,默认是关闭,但是,开启OkToRetryOnAllOperations后,不配也行
  cloud:
    loadbalancer:
      retry:
        enabled: true
#这是容断器的时间 必须大于请求时间才能触发重试,容断器没有超时肯定不会去重试
hystrix:
  command:
    default:
      execution:
#        timeout:
#          enabled:true
        isolation:
          thread:
            timeoutInMilliseconds:1000
			
配置超时时间,默认是开启超时时间,这里有设置超时时间是1秒触发容断,默认是5秒 

下面是配置的代码

/**
	 * 
	 * @param post请求方式,  直接封装json传递参数
	 * @return   特别说明 ,容断器的回调函数必须与注入的容断函数保持一致,返回参数必须一致
	 */
	@HystrixCommand(fallbackMethod="postDataFallback")
	private JSONObject postData(JSONObject jsonObj,String urls){
			if (StringUtils.isBlank(urls)) {
				return null;
			}
		   HttpHeaders headers = new HttpHeaders();
	        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
	        headers.setContentType(type);
	        headers.add("Accept", MediaType.APPLICATION_JSON.toString());
	        
	        HttpEntity<String> formEntity = new HttpEntity<String>(jsonObj.toString(), headers);
	        String result =  restTemplate.postForObject(urls, formEntity, String.class);
	        JSONObject results = JSONObject.parseObject(result);
	    	/*if (results.getIntValue("code") == 0){
	    		results.getString("data");
			}else{
				results.put("code", 1);
			}*/
		   return results;
	}
//调用超时和不可用的时候执行的方法,返回参数与 提交参数一致尽可,无参数也可行
//返回参数必须和注入的方法一致   所以下面方法这样写是不会回调的
	public void postDataFallback(JSONObject jsonObj,String url) {
		logger.debug("服务注册中心返回失败"+url.toString());
        //return "fallback";
	}
正确方法应该如下
	public JSONObject postDataFallback(JSONObject jsonObj, String url) {
		logger.debug("服务注册中心返回失败" + url.toString());
		System.out.println("**************************** "+url.toString());
		return new JSONObject();
	}

GET请求方式的熔断返回

@HystrixCommand(fallbackMethod = "getDataFallback")
	private JSONObject getData(String url) {

		// String url = "http://tms-mgr-ssss/jhb/waybill/updateStatus?vin=" + urls+
		// "&fromTime=" + urls;
		if (StringUtils.isBlank(url)) {
			return null;
		}
		JSONObject result = JSONObject.parseObject(restTemplate.getForObject(url, String.class));
		if (result.getIntValue("code") == 0) {
			result.getString("data");
		} else {
			result = new JSONObject();
			result.put("code", 1);
		}
		return result;
	}
正确方法应该如下
     JSONObject getDataFallback(String urls) {
			 System.out.println("____________________________________");
			logger.debug("服务注册中心返回失败"+url.toString());
	        return new JSONObject();
		}

服务请求这里后面再研究了下,配置有很大关系  重点 OkToRetryOnAllOperations   开启所有请求重试

基于HTTP响应码重试

clientName:
 ribbon:
  retryableStatusCodes: 404,502

注意点:

一般来说,不建议将ribbon.OkToRetryOnAllOperations 设为true。
因为一旦启用该配置,则表示重试任何操作,包括POST请求,而由于缓存了请求体,此时可能会影响服务器的资源。
此结论有待验证,之前结论里是说重试 GET请求

方法参数可以知道调用哪个服务不可用,会打印出IP地址,进行排查,当然不会抛出异常,相当能 try catch处理过,显示不可用的服务实例IP 如 192.168.11.88:3020 等详细信息。

那么断路器是在什么情况下开始起作用呢?这里涉及到断路器的三个重要参数:快照时间窗、请求总数下限、错误百分比下限。这个参数的作用分别是:

  • 快照时间窗:断路器确定是否打开需要统计一些请求和错误数据,而统计的时间范围就是快照时间窗,默认为最近的10秒。
  • 请求总数下限:在快照时间窗内,必须满足请求总数下限才有资格根据熔断。默认为20,意味着在10秒内,如果该hystrix命令的调用此时不足20次,即时所有的请求都超时或其他原因失败,断路器都不会打开。
  • 错误百分比下限:当请求总数在快照时间窗内超过了下限,比如发生了30次调用,如果在这30次调用中,有16次发生了超时异常,也就是超过50%的错误百分比,在默认设定50%下限情况下,这时候就会将断路器打开。

下面容断的返回值必须一致 其它配置都默认就可以,只需要改变一下配置容断超时时间就OK,被坑过

     @GetMapping("/getelf")
        @HystrixCommand(fallbackMethod="fallbackTest")
        public JSONObject elfste(String urls){
            urls="http://microservice-elefdata-service/getelefdata/test";
            JSONObject result = JSONObject.parseObject(restTemplate.getForObject(url, String.class));
               return result;
        }
         JSONObject fallbackTest(String urls) {
             System.out.println("____________________________________");
            logger.debug("服务注册中心返回失败"+url.toString());
            return new JSONObject();
        }

服务注册中心的服务实例转发,并不能保证全部都会转发到正常服务实例中去,偶尔会去不可用的服务实例,可能这是为了容错性的而做的策略,尝试去执行一次,如果服务可用下次请求就可能会自动落到此实例,

那么当断路器打开之后会发生什么呢?我们先来说说断路器未打开之前,对于之前那个示例的情况就是每个请求都会在当hystrix超时之后返回fallback,每个请求时间延迟就是近似hystrix的超时时间,如果设置为5秒,那么每个请求就都要延迟5秒才会返回。当熔断器在10秒内发现请求总数超过20,并且错误百分比超过50%,这个时候熔断器打开。打开之后,再有请求调用的时候,将不会调用主逻辑,而是直接调用降级逻辑,这个时候就不会等待5秒之后才返回fallback。通过断路器,实现了自动地发现错误并将降级逻辑切换为主逻辑,减少响应延迟的效果。

 

今天重试和容断器总结

启动微服务时 注入的方法 

1  @EnableHystrix  与  @EnableCircuitBreaker   效果一样, 前者包含后者

2  @HystrixCommand(fallbackMethod="fallbackTest")   里面的方法返回类型必须一致,  代码如上

3 配置重试机制   关键点   OkToRetryOnAllOperations: false  默认关闭,true开启就会自动重试,参数配置如上,下面是再次强调

tms-mgr:
  ribbon:
   # 同一实例最大重试次数,不包括首次调用,配置后本实例至少会执行两次
    MaxAutoRetries: 1
开启局部微服务重试机制 必须加上指定的微服务

 

 还有更多功能没有挖掘,学习的道路还有很长

参考 资料 https://www.jb51.net/article/129336.htm 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值