这是一项任务 - 必须根据UI端的一些数据(JavaScript)生成文件。架构非常简单:
UI向服务器发出异步POST HTTP请求并提供一些JSON数据:
$.ajax({
url: '/reports',
type: "POST",
data: JSON.stringify({...}),
success: function (uuid) {
window.location = "/reports/" + uuid;
}
});
服务器接收请求,生成文件,将其放在文件系统上并返回唯一ID:
@RequestMapping(value = "/reports", method = RequestMethod.POST)
public String generateReport(ReqData data) throws IOException {
final String fileUuid = UUID.randomUUID();
...
//generate a report and return filename
...
return fileUuid;
}
UI方获取生成文件的唯一ID并请求它:
success: function (uuid) {
window.location = "/reports/" + uuid;
}
服务器输出所请求的文件:
@RequestMapping(value = "/reports/{uuid}", method = RequestMethod.GET)
public ResponseEntity<InputStreamResource> downloadReport(@PathVariable("uuid") String fileUuid) throws IOException {
final String resultFileName = fileUuid + ".txt";
final Path resultFile = Paths.get(resultFileName);
return ResponseEntity
.ok()
.header("Content-Disposition", "attachment; filename=\"" + resultFileName + "\"")
.contentLength(Files.size(resultFile))
.contentType(MediaType.parseMediaType("text/plain"))
.body(new InputStreamResource(Files.newInputStream(resultFile)));
}
当我们考虑使用多个服务器的此架构时,问题就开始了。如果我们有两个实例 Server_A 和 Server_B ,并且前面有一个负载均衡器,那么我们需要确保上述两个请求都转到同一台服务器。因此需要粘性会话。提供与http://server_a/reports/123指定的服务器的绝对路径不是一个好的选择,因为我们希望使所有服务器无法从外部世界访问。
那么有哪些选项可用于实现下载生成的文件以及避免粘性会话?
答案 0 :(得分:0)
有几种方法可以围绕此实现解决方案..虽然会话粘性开始并在负载均衡器上配置。
方法1: - 使NFS空间可用并将其安装在所有应用程序服务器上,并在该位置生成报告。安装后,可以从任何服务器提供相同的文件。
方法2:在其中一个服务器上实现本地文件存储库,并在生成报告时通过ftp协议将文件推送到存储库,这种方法可能会对性能产生一点影响,这将是存储和检索文件的开销。通过FTP文件。
方法3:将报告存储在数据库本身中,并通过数据库从任何服务器检索它。
方法4:为什么不在生成本身时将报告发送给客户端,为什么不实现文件的传递以及第一次调用本身。无论如何,在您的javascript中,您似乎在生成文件后收到响应时设置了window.location。