

> 環境・前提条件

  * 認証機能を実装している。(config : firewalls) 
  * バンドル FOSUserBundle を導入している。
  * 下記の処理はログイン状態で実行される。

* * *

単純にスリープするアクションがあります。

ルーティング：demo_home_index

[code]

    indexAction()
    {
        sleep(60);
    
        return // ...
    }
    
[/code]

ファイルを読み込むアクションがあります。

ルーティング：demo_home_read

[code]

    public function readAction()
    {
        $file       = "/path/to/file/read.txt";
        $contents   = false;
    
        if (file_exists($file)) {
            $fp = fopen($file, 'r');
            $contents = fgets($fp);
            fclose($fp);
        }
    
        return new Response(json_encode(array(
            'contents' => $contents,
        )));
    }
    
[/code]

まずUIから非同期で indexAction にアクセスします。  
と同時にインターバルでファイルを読み込む処理が走ります。

[code]

    $.ajax({
        url         : Routing.generate("demo_home_index"),
        type        : "GET",
        dataType    : 'json'
    })
    .done(function(response){
        // スリープのため60秒は返ってこない
        console.log(response);
    });
    
    var timer = setInterval(function(){
        $.ajax({
            url         : Routing.generate("demo_home_read"),
            type        : "GET",
            dataType    : 'json'
        })
        .done(function(response){
            console.log(response);
        });
    }, 3000);
    
[/code]

この時、3秒おきにアクセスするインターバルがファイアーウォールで足止めされるというか、スリープする処理、はじめのアクセス indexAction
が終了しないとインターバルでのアクセスも完了しません。

なので、インターバルで定期的にアクセスするが、60秒間全部のインターバルがローディングしている状態になり、はじめのアクセス＆処理（スリープ60秒間）が完了すると、すべてのインターバルのアクセスも順次完了する状態となっています。

これは非同期に関わらず、スリープで60秒間処理している間、別タブでページにアクセスする（otherActionなど）場合でも、ローディング状態となりアクセスが中断されてしまう。

Symfony2自体のファイアーウォールの設定などを変更することで、  
ファイアーウォールで中断されずに、同時処理することは可能なのでしょうか？

それともバンドルの方の問題で処理中の同時アクセスを制限しているのでしょうか？

今のところ原因のもとがわかっていない状態です。  
よろしくお願いします。


CC BY-SA 3.0
2015-03-05T12:43:45.183
7493
2015-04-05T17:49:05.363
8704
question
php symfony2
同時アクセスした場合ファイアーウォールで止まる：セキュリティ：Symfony2


目を付けられているように、セッションでのファイルロックが原因のようですね。

[`session_write_close()`](http://php.net/manual/ja/function.session-write-
close.php)のページを見ると、PHPデフォルトのファイルベースセッション管理を使っている場合、何もしなければスクリプト終了時までセッションファイルがロックされます。このため、次のリクエストでは、セッションファイルの書き込みオープンのためのロック解放を待つことになります。

これを回避するには、コントローラでセッションに関連する更新処理が完了したら、その時点で`session_write_close()`を呼び出すようにします。

Symfonyの場合、`session_write_close()`に相当するのは、コントローラでは次のコードになります。

[code]

    $this->get('session')->save();
    
[/code]

ですので、質問の検証コードならば、`indexAction()`で`sleep()`する前に上記コードを入れて試して頂く感じです。

また、別の対処法として、ファイルベースのセッション管理ではなく、PDO等を使うように変更することでセッションのブロッキングをなくすこともできます。[How
to Use PdoSessionHandler to Store Sessions in the
Database](http://symfony.com/doc/current/cookbook/configuration/pdo_session_storage.html)に解説があります。


CC BY-SA 3.0
2015-03-06T16:47:38.843
7563
2015-03-06T16:47:38.843
5444
7493
answer