有业务的同事反馈,图片上传之后,加载不出来。登录系统后台查看相关记录,图片附件确实未显示。在新标签打开图片链接,图片只显示出来上面一小截,然后就没有然后了。多次刷新也不好使。这个问题之前出现过,之前是调高图片服务器的一个访问配置缓存大小:

location / {
    client_body_buffer_size 256k;
    ...
    proxy_buffer_size 256k;
    proxy_buffers 4 256k;
    ...
}

运维做了代理缓存限制,调高一点就可以让更大的图片通过。但是在调整到 1024k 之后,图片还是有访问不到的情况。这时候就不能盲目地调高配置了,因为明显是上传图片过大了。这边就反馈让她做图片压缩处理之后再上传,并确认图片不涉密,所以推荐了一个在线的压缩工具:tinypng.com

过了两天,她又反馈压缩后的图片上传不了,截图说明报错信息:

运行时异常:Read timed out executing GET xxx/uploadImage

因为刚接触这个 feign 服务,对于这种调用错误所知甚少。就想确认是否是图片本身的问题,还是接口的问题(其实只要报错了,就不应该纠结,肯定是要去调试找问题的)。

先是在测试站上传正常的图片,发现没有问题。然后跟她要了压缩后的图片上传,确实报错了:

运行时异常:xxxFeign#xxx timed-out and no fallback available.

从上传使用的时间来看,1s 左右就返回了,怎么会 time-out 超时呢?百度这个报错信息,得到了一篇解读:springcloud异常:timed-out and no fallback available,failed and no fallback available的问题解决 - CSDN

这个错误基本是出现在 Hystrix 熔断器,熔断器的作用是判断该服务能不能通,如果通了就不管了,调用在指定时间内超时时,就会通过熔断器进行错误返回。

其中提到了三个配置项:feignhystrixribbon。 其中 feign 是在使用的,其主要是替换 restTemplate 做远程调用,其 interface 接口形式的定义,可以比较方便定义使用。hystrix 文中提到是熔断器,Ribbon 是一个基于HTTP 和 TCP的客户端负载均衡工具(百度)。

测试站配置文件里带的是 feign.hystrix.enabled=true。测试将其改成 false,并重新部署,测试报错:运行时异常:Read timed out executing GET xxx/uploadImage。与正式站后台报错一致,都是 Read timed out。查看正式站服务器配置,确实是关闭了 feign.hystrix.enabled=false

尝试修改增加 ribbon 配置:

ribbon.ReadTimeout=60000
ribbon.ConnectTimeout=60000

此时不再报错,图片也成功上传。看时间用了 6.65s,这惊到我了,正常图片(1.7M)上传也只用了 1.6s。她的图片压缩过后只有几百K,怎么会这么长时间呢?跟她要到源文件(都是几M的),然后找了另外一个压缩工具 Caesium Image Compressor,限制说明里有一条 图片永远不会离开您的设备,从控制台看确实没有上传二进制文件到其他服务器的请求。所以大概率是前端版本的压缩,且压缩率不低(3.48 MB -> 780 kB (-78%))。测试新压缩后的图片上传(去掉 riboon 配置),报错 Read timed out。所以确认是图片存在问题,导致文件上传服务处理缓慢,进而导致系统这边的超时报错。

但文中也提到了,如果关闭 feign 熔断器并不能解决根本问题。然后就想再试试 feign 熔断器开启状态下如何设置超时时间参数,使其不再报错。

一开始 feign + hystrix 组合,超时一开始设置成 5000 报错,设置成 15000 还是报错:运行时异常:xxxFeign#xxx failed and no fallback available.。也测试过 feign + ribbon 依然报错。

最后直接把提到的几个参数都设置了重新部署:

feign:
  hystrix:
    enabled: true
hystrix:
  command:
    default:
      execution:
        timeout:
          enabled: true
        isolation:
          thread:
            timeoutInMilliseconds: 15000
ribbon:
  ReadTimeout: 60000
  ConnectTimeout: 60000

成功了!另外百度到的一篇 微服务 feign远程调用yml配置,并解决显示服务不可用 timed-out and no fallback 里面整体配置:

# pzy最新升级版 feign配置远程调用超时时间
# 细节请看csdn博客
feign:
  hystrix:
    enabled: true
  client:
    config:
      default:
        connectTimeout: 40000
        readTimeout: 40000
#pzy最新升级版  hystrix的超时时间
hystrix:
  command:
    default:
      execution:
        timeout:
          enabled: true
        isolation:
          thread:
            timeoutInMilliseconds: 15000
      circuitBreaker:
        requestVolumeThreshold: 200
        sleepWindowInMilliseconds: 5000
        errorThresholdPercentage: 50
  threadpool:
    default:
      coreSize: 200
      maxQueueSize: 200
      queueSizeRejectionThreshold: 160
# pzy最新升级版 feign配置远程调用超时时间
ribbon:
  ReadTimeout: 12000
  ConnectTimeout: 3000
  MaxAutoRetries: 1
  MaxAutoRetriesNextServer: 1
  OkToRetryOnAllOperations: false

主要还是针对 feignhystrixribbon 进行配置,只是多了很多的配置项,测试也是可以的。如果上面的那个简版配置测试还报错,可以试试下面这个。