0

ここにタスクがあります - UI 側 (JavaScript) からのデータに基づいてファイルを生成する必要があります。スキーマは非常に単純です。

  1. UI はサーバーに対して非同期の POST HTTP 要求を作成し、いくつかの JSON データを提供します。

        $.ajax({
            url: '/reports',
            type: "POST",
            data: JSON.stringify({...}),
            success: function (uuid) {                    
                window.location = "/reports/" + uuid;
            }                
        });
    
  2. サーバーはリクエストを受け取り、ファイルを生成し、それをファイルシステムに置き、一意の 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;
    }
    
  3. UI 側は、生成されたファイルの一意の ID を取得し、それを要求します。

    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_AServer_Bの2 つのインスタンスがあり、それらの前にロード バランサーがある場合、上記の両方の要求が同じサーバーに送信されるようにする必要があります。したがって、スティッキー セッションが必要です。http://server_a/reports/123のように指定されたサーバーに絶対パスを提供することは、すべてのサーバーを外界から到達できないようにするため、適切なオプションではありません。

では、生成されたファイルのダウンロードを実装し、スティッキー セッションを回避するには、どのようなオプションを利用できるのでしょうか?

4

1 に答える 1

0

これを回避するソリューションを実装するには、いくつかの方法があります。ただし、セッション スティッキーはロード バランサで開始および設定されます。

アプローチ 1: -- NFS スペースを使用可能にして、それをすべてのアプリケーション サーバーにマウントし、その場所でレポートを生成します。マウントすると、同じファイルを任意のサーバーから提供できます。

アプローチ 2: サーバーの 1 つにローカル ファイル リポジトリを実装し、レポートの生成時に ftp プロトコル経由でファイルをリポジトリにプッシュします。このアプローチは、FTP 経由でファイルを保存および取得するオーバーヘッドになるため、パフォーマンスに少し影響を与える可能性があります。 .

アプローチ 3: レポートを db 自体に保存し、任意のサーバーから db を介して取得します。

アプローチ 4: 生成時にクライアントにレポートを送信しない理由、最初の呼び出し自体と共にファイルの配信を実装しない理由。とにかくあなたのjavascriptでは、ファイルを生成した後に応答を受け取るときにwindow.locationを設定しているようです。

于 2015-12-09T01:31:58.877 に答える