Spring Boot 微服務之間通過FeignClient進行大檔案下載:
阿新 • • 發佈:2019-01-02
使用FeignClient作為中介軟體進行一個微服務之間的呼叫的時候,一般的服務請求是沒有什麼問題,但是,當下載大檔案,會出現:java heap space
也就是堆溢位問題。
具體解決方案如下:
1、首先是service層返回ResponseEntity<Resource>
2、@FeignClient的remote介面返回Response物件(FeignClient提供的Response物件)
3、前端層獲取Response物件之後,可以獲取headers和body資訊.程式碼如下:
Response response = exploreServiceRemote.downPackSensorDataFile(recordCode, uniqueCode); Map<String, Collection<String>> headers = response.headers(); HttpHeaders httpHeaders = new HttpHeaders(); headers.forEach((key, values) -> { List<String> headerValues = new LinkedList<>(); headerValues.addAll(values); httpHeaders.put(key, headerValues); }); Response.Body body = response.body(); try { InputStream inputStream = body.asInputStream();//HttpURLInputStream InputStreamResource resource = new InputStreamResource(inputStream); return ResponseEntity .ok() .contentType(MediaType.APPLICATION_OCTET_STREAM) .headers(httpHeaders) .body(resource); } catch (IOException e) { throw new SdsResourceFileNotFoundException( MessageFormat.format("Can not download resource recordCode [{0}] and uniqueCode [{1}]", recordCode, uniqueCode)); }
具體跟蹤的原始碼:
看這個原始碼可以知道:只要當我們的FeignClient的介面返回的是feign.Response型別的時候,才有可能扔過去response。而且,他還有驗證,就是你的body為null,或者你的body的長度大於這個MAX_RESPONSE_BUFFER_SIZE的時候,這個值是8192L,也就是8KB的大小,所以,在這個範圍內,不用擔心堆溢位問題,如果都不符合,那就直接讀取流轉成byte陣列。
如果:你的FeginClient的註解的介面的方法返回的不是feign.Response型別,那麼肯定就是走decode(response)這個方法了,這個方法的原始碼如下:
@Override public Object decode(Response response, Type type) throws IOException { if (response.status() == 404) return Util.emptyValueOf(type); if (response.body() == null) return null; if (byte[].class.equals(type)) { return Util.toByteArray(response.body().asInputStream()); } return super.decode(response, type); }
看這個方法原始碼也是讀取所有內容到一個byte陣列當中去,所以下載大檔案的時候,一定要設定返回feign.Response型別