質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
IIS 7

IIS(インターネットインフォメーションサービス) 7は、 Microsoftによって開発された、Windowsの標準ウェブサーバーです。Window Server 2008 と Windows Vista向けにリリースされました。

ASP.NET Web API

ASP.NET Web APIはブラウザやモバイル機器のようなクライアント向けのHTTPサービスを構築するフレームワークです。Microsoft .NET Frameworkがベースになっており、RESTfulサービスを構築するには理想的です。

Q&A

解決済

2回答

5549閲覧

.Net Web API シングルトンについて

ashinaga_onisan

総合スコア12

IIS 7

IIS(インターネットインフォメーションサービス) 7は、 Microsoftによって開発された、Windowsの標準ウェブサーバーです。Window Server 2008 と Windows Vista向けにリリースされました。

ASP.NET Web API

ASP.NET Web APIはブラウザやモバイル機器のようなクライアント向けのHTTPサービスを構築するフレームワークです。Microsoft .NET Frameworkがベースになっており、RESTfulサービスを構築するには理想的です。

0グッド

0クリップ

投稿2018/04/26 17:36

編集2018/04/27 01:12

皆様に質問なのですが、IISを用いた.Net Web APIにてシングルトン等使われていますか?

当方始めてAPIを作っておりますが、シングルトンにSortedListで変数を持っています。まれに同時アクセスする際、ContainsKeyがfalseだったのに同じキーのエントリが存在するとの例外が発生します。

マルチテナントアプリのため、呼び出し元クライアントからのリクエストヘッダー内の施設情報を元に、設定を取得する必要があります。その際、毎回リードから入るのはもったいないためシングルトンに確保して居ます。
IISのワーカー再起動にて再度取得できるよう、ContainsKeyがfalseなら読み込んだ情報をシングルトンのプロパティのSortedListにAddする単純な作りです。

C#

1// シングルトン中のプロパティ例 2public SortedList HogeList<string, Hoge> { get; set;} 3 4// Add部分メソッド例 5public Hoge GetHoge(string keyStr) 6{ 7 Hoge result = null; 8 if (AppSingleton.Instance.HogeList.ContainsKey(keyStr)) 9 { 10 result = AppSingleton.Instance.HogeList[keyStr]; 11 } 12 else 13 { 14 // オプジェクト作るメソッド呼ぶ 15 result = CreateHoge(keyStr); 16 AppSingleton.Instance.HogeList.Add(keyStr, result); 17 // ↑ここで同じキーのエントリ...例外出る 18 } 19 return result; 20}

この場合、CreateHoge後にもう一回Containsかけるくらいしか思いつかないのですが、根本解決とは思えません。
そもそもWeb APIでこのようなシングルトンで持つのは適していないのか?
みなさんはどうやってるのか知りたいですー!
ちなみに、プロパティの型はDictionaryでも良かったなーソートの必要性無いし...

2018/04/27 10:11追記
私の開発環境は以下です。
.Net 4(Coreでない)
IIS8.5
ですが、ある意味技法的な質問でもあるのでいろいろな回答をお待ちしております!

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/04/27 00:35

開発環境を書いてください。特に Core か否か。
ashinaga_onisan

2018/04/27 01:26 編集

すみません。追記いたしました。 また、Coreだとこういう技術がある、等でも構いませんので、ご意見お願いします!
guest

回答2

0

ベストアンサー

.Net 4(Coreでない)

Core でなければ、旧来の Web Forms や MVC と同様に、Web API も ASP.NET ランタイム上で動くので、「アプリケーション状態」が使えます。

AllKeys、Count プロパティ、Add、Clear、Get、GetKey、Remove、RemoveAt、Set メソッドを使用する際、ロックおよびロック解除を自動で行う点に注目です。

詳しくは以下の記事の「アプリケーション状態」のセクションおよびそこから張られたリンク先の記事を見てください。

ASP.NET の状態管理の概要
https://msdn.microsoft.com/ja-jp/library/75x4ha6s.aspx

具体的には、例えば Global.asax の Application_Start で以下のように key / value を追加すると、

namespace WebAPI { public class WebApiApplication : System.Web.HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas(); GlobalConfiguration.Configure(WebApiConfig.Register); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); // 上はテンプレートで自動生成された既存のコード // Key / Value を「アプリケーション状態」に追加 Application["test"] = "this is a HttpApplicationState test."; } } }

コントローラーでは以下のようにして取得できます。

using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Web.Http; using WebAPI.Models; using System.Web.Http.ModelBinding; namespace WebAPI.Controllers.BizB { public class ListAuthorsWebApiController : ApiController { [HttpGet] [Route("BizB/ListAuthors/GetAllAuthors")] public List<AuthorDTO> GetAllAuthors() { System.Web.HttpContext context = System.Web.HttpContext.Current; System.Web.HttpApplicationState applicationState = context.Application; string testValue = (string)applicationState["test"]; //・・・中略・・・ } } }

投稿2018/04/27 05:49

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ashinaga_onisan

2018/04/27 07:55 編集

なるほど!Win Formsの業務ばかりだったので初めて知りました。Application スコープに置いておけばシングルトンなんか要らないですね。頂いたサンプルやネット上の文献は全てstring型を値としていましたが、上述のSortedListそのまま突っ込むことも可能でした(^^)ただし、あまり大きなデータ入れるなとは書いてあるものの、明示的な線引きが無く扱いが難しそうです...せめて物理メモリの○%みたいな閾値があれば(´・ω・`) ところで、ロックが自動で行われる件についてまだ文献が見つけられていません。逆に動的にコールすると言った情報や、読んでる間はアプリケーション全体が止まるなどと言う本当かわからない情報もありました。この辺りは実際の動作確認もしてみますが、なにか詳しいサイト等ご存知ありませんでしょうか。
退会済みユーザー

退会済みユーザー

2018/04/27 10:08 編集

> せめて物理メモリの○%みたいな閾値があれば メモリを圧迫するのは質問者さんの案シングルトンでも同じこと思うのですが・・・ 何にせよ、そういう指標はないと思います。少なくとも自分は聞いたことがないです。(そもそも質問者さんの運用環境で Web アプリにどのぐらいのメモリが割り当てられて・・・というのは質問者さんにしか分かりません) > ロックが自動で行われる件についてまだ文献が見つけられていません。 自分の持っている本「プログラミング Microsoft ASP.NET 4」に書いてあったことですが「アクセスをシリアル(直列)化するために必要なロックメカニズム」は間違いなく実装されているようです。 ただ、Item プロパティの get アクセサは Lock メソッドと組み合わせて使用しなければクロススレッドの読み取り書き込みを阻止しないという記述もありました。検証したわけではないので保証の限りではないですが。質問者さんの方で検証してみてください。 なお、Application オブジェクトへの書き込みは推奨されなくなってるそうです。Cache を使えということのようです。 なので、私が上のレスで書いたような使い方に限った方がよさそうです。
ashinaga_onisan

2018/04/27 13:45

>シングルトンでも同じ シングルトンはあくまでワーカープロセスのリサイクル時に破棄されますが、Applicationスコープはアプリが動き続ける限り保持して、自アプリだけでなく他のIIS上のアプリにもパフォーマンスの影響を与えるようでした。 調べた限りではCacheの方が適当のようですね!Applicationのロックのテストは、どうも自分だけがいじれるようにするため、スタンドアロンでのデバッグは失敗に終わりました...ログ吐くかなんかしてIIS Expressじゃないリアルなサーバーに配置してテストするほかなさそうです。 この’自分しか’の捉え方もセッションでは無い何かで制御されているのか、フロントからの正規アクセスでロックして、その後テストクライアントから別セッションで問い合わせても特に怒られず... フロントの要求はレスポンス返すまで終わってるのですが、この時自動的にアンロックされているのでしょうかね?Application.IsLocked等ロック中か調べるすべがなくて(´・ω・`) なんにせよもう少し調べて見ます!ASP初心者に色々ありがとうございました!
退会済みユーザー

退会済みユーザー

2018/04/27 15:32

一つだけ・・・ > Applicationスコープはアプリが動き続ける限り保持して、 ワーカープロセスのリサイクルで消えるのは同じです。それを考えて先の私のレスで Global.asax の Application_Start で設定するサンプルを書いてます。
ashinaga_onisan

2018/04/27 15:47

ぁ、そうなのですね。すみません。何か変なページ読んだかもしれません(ノД`) ともするとシングルトンだろうが、Application だろうが、Global.aspxのパブリック変数だろうがメモリの食い方は一緒ですね。唯一Cacheだけが有効期限とともに解放されると。 ご指摘ありがとうございました!
guest

0

おそらく、その不具合というのは同時アクセスした時に双方のアクセスがかぶってしまうために、読み出してる最中に書き込みが起こって変なデータが読み出されてしまったり、複数の書き込みがかぶって、変なデータが書き込まれたりするんじゃないでしょうか。
そうならないように、いわゆる排他制御というのを行わなければなりません

シングルトンというのはインスタンスが一つ、というのを保証するもので、同時アクセスする時に排他制御してくれるってものではないですねー

投稿2018/04/27 05:59

y_waiwai

総合スコア87749

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ashinaga_onisan

2018/04/27 07:57

ご意見ありがとうございます。今回はシングルトンに置いたプロパティの更新に対する競合対策(排他制御)の仕方そのものの質問でした。タイトルが悪くて申し訳ありません。
y_waiwai

2018/04/27 09:26

そういうことなら、「ASP.NET 排他制御」でぐぐるとかすればいろいろでてきますねー
ashinaga_onisan

2018/04/27 13:48

ありがとうございました! 調べ方を聞いたわけではなかったのでSurferOnWwwさんをベストアンサーとさせていただきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問