2015-12-09 3 views
0

Вот задача - необходимо создать файл на основе некоторых данных со стороны интерфейса (JavaScript). Схема довольно проста:Как избежать липких сессий при загрузке файла?

  1. UI делает запрос HTTP асинхронной POST на сервер и предоставляет некоторые JSON данные:

    $.ajax({ 
         url: '/reports', 
         type: "POST", 
         data: JSON.stringify({...}), 
         success: function (uuid) {      
          window.location = "/reports/" + uuid; 
         }     
        }); 
    
  2. сервер получает запрос, создает файл, помещает его в файловой системе и возвращает уникальный идентификатор:

    @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; 
    } 
    
  3. стороны UI получает уникальный идентификатор файла, созданного и просит его:

    success: function (uuid) {      
        window.location = "/reports/" + uuid; 
    } 
    
  4. Сервер выводит запрашиваемый файл:

    @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

Существует несколько способов реализации решения вокруг этого. Хотя сеансовая липкость начинается и настраивается на балансировщике нагрузки.

Подход 1: - сделать доступным пространство NFS и установить его на всех серверах приложений и сгенерировать отчет в этом месте. После установки один и тот же файл может быть подан с любого сервера.

Подход 2: Реализация локального репозитория файлов на одном из серверов и при создании отчета подталкивает файл в репозиторий через протокол ftp, этот подход может оказать небольшое влияние на производительность, поскольку они будут накладными расходами на хранение и извлечение файл через FTP.

Подход 3: Храните отчеты в самой базе данных и извлекайте их через db с любого сервера.

Подход 4: Почему бы не отправить отчет клиенту во время генерации, почему бы не реализовать доставку файла вместе с первым вызовом. в любом случае в вашем javascript, кажется, что вы устанавливаете window.location при получении ответа после генерации файла.

+0

Подход 4: невозможно вызвать диалог сохранения в браузере с помощью ajax - http://stackoverflow.com/questions/12098178/prompt-user-to-save-file-through-ajax-call, поэтому есть два вызова ajax –

Смежные вопросы