くりーむわーかー

プログラムとか。作ってて ・試しててハマった事など。誰かのお役に立てば幸いかと。 その他、いろいろエトセトラ。。。

mvc

.net core mvc で Redis使用でSession共有

比較的大きめ(10万行くらい?)のWebアプリを作るのに、アプリケーションを分けて構成したくなったりする。そういう時に問題になるのが、アプリ間でのセッション共有。いちをSQLServerで出来るんだけど、やっぱDBをストアにすると多少遅くなる。

.net core でのセッションの実装はなんだかんだでココが一番わかりやすい。

.net core では 昔の「Session」みたいなのはいきなりは使えないのね。キャッシュを使う模様。

で、.net core でもサイト間でセッション共有するやり方は提供されてて、SQLServerとRedisが使えるみたい。今回はRedisを使ったんだけど、すごくはまった。

Redisを使ったセッションの共有はここに書いてある。

まず、Redisのインストール。上記に書いてある通りでいけるんだけど、プロキシ使ってる環境だと上手くいかない。その場合はココが一番参考になる。

Redisがインストール出来たら、コマンドプロンプトで「redis-server」って打って実行しておく。

そしたらNugetで「Microsoft.AspNetCore.Session」と「Microsoft.AspNetCore.DataProtection.Redis」をプロジェクトにインストールする。

そしたら.net core mvc の StartUpのコンフィグを下の感じにする。

using Microsoft.AspNetCore.DataProtection;
using StackExchange.Redis;

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    //キャッシュにRedisを使う場合
    services.AddDistributedRedisCache(options =>
    {
        options.Configuration = "localhost";
        options.InstanceName = "SampleInstance";
    });
    
    //プロテクションの設定をする(セッション共有する場合はここが必須。
    var redis = ConnectionMultiplexer.Connect("localhost:6379");
    services.AddDataProtection()
        .SetApplicationName("HogeApp")//これが必要!!!!!
        .PersistKeysToRedis(redis, "DataProtection-Keys");
    
    services.AddSession(options =>
    {
        options.IdleTimeout = TimeSpan.FromSeconds(600);
        options.Cookie.HttpOnly = true;
        options.Cookie.Name = "NetCoreWebAppSessionKey";//これは適当に(なくてもいい)
    });
}

SetApplicationNameでそれぞれのサイトで名称一緒にしないと共有できなかった。

あー、これは同一ホスト上で複数のWebアプリを動かして、アプリ間でセッション共有したい場合の話。ホストが別の場合はまた色々考えないといけない模様。つかホスト跨いでセッション共有とかすることあるのかな?

ロードバランサで分けると思うんだとも、その場合ってIPかセッションクッキーでのバランシングするよね?そうするとユーザは1サーバにしか基本いかないからホスト跨ぐことないような気がするけど、どうなんでしょね。リクエスト毎にサーバを回されることってあるんかな?まぁアプリの作り次第か。。。

あと、Redisにどんなクエリが来てるのか見たい場合は、コマンドプロンプトで「redis-cli」を実行して、「moniter」って入れるとredisに来たリクエストが見れる。

.net mvc レスポンスヘッダつける

別ドメインのURLにAjaxでリクエスト送りたかったんだけど、↓のアクセスエラーが返ってくる。

XMLHttpRequest cannot load http://***. Origin http://*** is not allowed by Access-Control-Allow-Origin.

やる前からだいたい予想してたけど、やっぱ別ドメインにAjaxで飛ばすのは大変だ。

Jsonpにすればいけるかと思ったけどなんかダメ。なので結果を返す側でレスポンスヘッダつけた。返す側は.netMVCで作ってるサイト。コントローラーで以下をつけてあげる。

Response.Headers.Add("Access-Control-Allow-Origin", "*");//呼び出せるようにクロスドメインをOKにしておく。

まーだめな対応の仕方だとは思う。自分が作ってるサイト間でのやり取りだからこその話。それでもだめだと思うけど。。。

.netMVCでアクセスログはどこに書くか

.net MVCで独自にアクセスログを取りたくなった。どこに入れるのが正解なのかよくわからない。 何となくGlobal.asaxにリクエスト来たときに書けばいいのかと思い、↓でとってみる。

public class MvcApplication : System.Web.HttpApplication
{
	protected void Application_Start()
	{
	    //アプリの起動時の処理
	}
        //↓これで書く
	protected void Application_OnBeginRequest(object sender, EventArgs e)
	{
	    // HTTP リクエスト処理開始時の処理
	    WriteLog();//ログをはく
	}
}

「Application_OnBeginRequest()」だとリクエスト来た時に全部拾えるからここがいいかなーと思ったけど、 User.Identityとゆーか認証の状態がとれかった。まぁ当たり前ですか。。。

認証後の状態はいつかなーで見てたら⇒でした。「Application_OnAuthenticateRequest()」これの中に書けばUser.Identityとかちゃんと取れる。ログイン前はNullってるけども。

リクエストのライフサイクル的な話はココで見れる。いろんなブログとかもあるけど、やっぱまず、MSDN見たほうがいいと思う。

で、とりあえず、アクセスログっぽいものはこれで作れたんだけど、なんとなく、ほんとにココでいいのか自信が持てない。動作上は特に問題無いよう思えるんだけど。。。

あと、ログ取ってみて思ったけど、やっぱSignalRはすげーコネクション使うのね。なんかこんなに接続しちゃってよいのだろーかと不安になるくらいつなぐ。最近のWebはこんなもんなのだろうか。。。

問合せ