6

WebRoleが1つあるが、Cookieなしのセッションを使用するインスタンスが複数あるAzureプロジェクトに問題があります。アプリケーションはセッションストレージを必要としないため、セッションストレージプロバイダーを使用していませんが、SessionIDを追跡する必要があります。どうやら、SessionIDはWebRoleインスタンス全体で同じである必要がありますが、説明なしで突然変更されます。一部のデータを追跡するためにSessionIDを使用しているため、これは非常に重要です。

問題を再現するには:

  1. クラウドプロジェクトを作成します。

  2. ASP.NETWebロールを追加します。すでにその中にあるコードで十分です。

  3. 開けるDefault.aspx

  4. SessionID現在を表示するコントロールとポストバックを発生させるボタンを追加します

            <p><%= Session.SessionID %></p>
            <asp:Button ID="Button1" runat="server" Text="PostBack" onclick="Button1_Click" />
    
  5. 応答を少し遅らせるボタンのイベントハンドラーを追加します。

    protected void Button1_Click(object sender, EventArgs e)
    {
        System.Threading.Thread.Sleep(150);
    }
    
  6. 開けるWeb.Config

  7. Cookieなしのセッションを有効にします。

    <system.web>
            <sessionState cookieless="true" />
    </system.web>
    
  8. プロジェクトを実行し、アドレスバーのセッションIDに注意を向けながら、しばらくの間「PostBack」ボタンをすばやく繰り返し押します。何も起こりません。セッションIDは常に同じです:)。やめろ。

  9. 開けるServiceConfiguration.csfg

  10. 4つのインスタンスを有効にします。

    <Instances count="4" />
    
  11. Web.configに、VisualStudioによって自動的に追加されたマシンキーに関連する行があることを確認します。(system.webの最後にあります)。

  12. プロジェクトを再実行し、すばやく繰り返し「ポストバック」ボタンをしばらく押して、アドレスバーのセッションIDに注意してください。SessionIDしばらくすると、どのように変化するかがわかります。

なぜこうなった?私の知る限り、すべてのマシンがを共有しているmachineKey場合、セッションはそれらの間で同じである必要があります。Cookieの場合、問題はありません。問題は、Cookieなしのセッションが使用されている場合にのみ発生するようです。

SessionID私の推測では、複数のインスタンスがあり、あるインスタンスで生成されたものWebRoleが別のインスタンスに移動し、拒否されて再生成されたときに、何か問題が発生していると思います。WebRoleすべてのが同じであるため、これは意味がありませんmachineKey

問題を見つけて、それをより明確に見るために、私は自分自身を作成し​​ましたSessionIDManager

public class MySessionIDManager : SessionIDManager
{
    public override string CreateSessionID(HttpContext context)
    {
        if (context.Items.Contains("AspCookielessSession"))
        {
            String formerSessionID = context.Items["AspCookielessSession"].ToString();

           // if (!String.IsNullOrWhiteSpace(formerSessionID) && formerSessionID != base.CreateSessionID(context))
               // Debugger.Break();

            return formerSessionID;
        }
        else
        {
            return base.CreateSessionID(context);
        }
    }
}

そしてそれを使用するには、WebConfigでこの行を変更します。

    <sessionState cookieless="true" sessionIDManagerType="WebRole1.MySessionIDManager" />

これで、SessionIDどれだけ速く、どれだけ長く叩いても、が変わらないことがわかります。これらの2行のコメントを外すと、ASP.NETが新しいsessionIDを作成していることがわかります(すでに1つある場合でも)。

ASP.NETに新しいセッションを作成させるには、サイト内の絶対URLにリダイレクトするだけです。

 Response.Redirect(Request.Url.AbsoluteUri.Replace(Request.Url.AbsolutePath, String.Empty));

なぜこれがCookieなしのセッションで発生するのですか?

私のソリューションはどの程度信頼できMySessionIDManagerますか?

敬具。

更新

  • 私はこの回避策を試しました: サイトレベルの自動構成によって上書きされたユーザー指定のマシンキーですが、問題はまだ解決していません。

    public override bool OnStart()
    {
        // For information on handling configuration changes
        // see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.
    
        using (var server = new ServerManager())
        {
            try
            {
                // get the site's web configuration
                var siteNameFromServiceModel = "Web"; // update this site name for your site. 
                var siteName =
                    string.Format("{0}_{1}", RoleEnvironment.CurrentRoleInstance.Id, siteNameFromServiceModel);
                var siteConfig = server.Sites[siteName].GetWebConfiguration();
    
                // get the appSettings section
                var appSettings = siteConfig.GetSection("appSettings").GetCollection()
                    .ToDictionary(e => (string)e["key"], e => (string)e["value"]);
    
                // reconfigure the machine key
                var machineKeySection = siteConfig.GetSection("system.web/machineKey");
                machineKeySection.SetAttributeValue("validationKey", appSettings["validationKey"]);
                machineKeySection.SetAttributeValue("validation", appSettings["validation"]);
                machineKeySection.SetAttributeValue("decryptionKey", appSettings["decryptionKey"]);
                machineKeySection.SetAttributeValue("decryption", appSettings["decryption"]);
    
                server.CommitChanges();
                _init = true;
            }
            catch
            {
            }
        }
        return base.OnStart();
    }
    
  • また、セッション開始ハンドラーを配置してデータを追加することについても試しましたが、うまくいきませんでした。

    void Session_Start(object sender, EventArgs e)
    {
        Session.Add("dummyObject", "dummy");
    }
    

バウンティアップ!

4

3 に答える 3

1

私は同じ問題を経験し、多くの調査とデバッグの結果、Azure SDK の "仮想サーバー" が Web サイトを IIS メタベースの異なるパスにマップするために問題が発生していることがわかりました。(これは Request.ServerVariables["APPL_MD_PATH"] で確認できます。)

私は今これを発見しましたが、人々がテストに取り組めるようにこれを投稿したかったのです。私の理論では、この問題が Azure に適切に公開されると、この問題は解消される可能性があります。見つけた結果を更新します。

于 2011-03-10T18:10:32.270 に答える
1

トリッキーですね。

1 つの提案/質問があります。参考になるかどうかはわかりませんが、何かに挑戦する準備ができているようですね。

おそらく、新しいマシンのセッション マネージャーが中央のセッション ストレージ プロバイダーをチェックしており、セッション ストレージが空であることを検出すると、新しいセッション キーを発行しているようです。

解決策は次のようになると思います: - セッション ストレージに何かを挿入するために、上記のように Session_Start を使用する - さらに、何らかの説明の永続的なセッション ストレージ プロバイダーを web.config に挿入する - たとえば、最も古い Azure サンプルのいくつかはテーブルを提供しますベースのプロバイダー、または新しいサンプルの一部は、AppFabric キャッシュ ソリューションを提供します。

あなたのデザインがセッション ストレージを使用していないことは知っていますが、何か (Session_Start のようなもの) を入れる必要があるかもしれません。さらに、インプロセス セッション管理以外のものを定義する必要があります。

または、ASP.NET セッション以外のものを中心にアプリを再設計する必要があります。

お役に立てば幸いです-頑張ってください!

于 2011-02-28T19:25:10.623 に答える