- PR -

Webサービスでのcookieless="true"設定時のセッション管理

1
投稿者投稿内容
KeiOS
会議室デビュー日: 2007/09/21
投稿数: 4
投稿日時: 2007-09-21 20:12
初めて投稿させていただきます。

以下の環境で開発を行なっています。
Webサーバー :.NET 1.1(WinXP_SP2+IIS5.0)
クライアント:.NET 1.1(WinXP_SP2)

現時点ではWebサーバーとクライアントは同一です(開発前の技術検証中なので)。

Webサーバー側でWebサービスを構築し、セッション管理を行なおうと考えています。
セッション管理を行なう理由は、このWebサービスではデータベースアクセスが発生する
のですが、都度コネクションを作成するとパフォーマンスが悪い為、初回ログイン時にコ
ネクションを作成してセッションに登録しておき、後の処理ではこれを使いまわすと言っ
た事を行なう為です(サーバー側のセッション変数として、対象ユーザーのコネクション
を格納しておき、クライアントにはセッションキーのみを送付すればよいと考えています
)。

プロトタイプ作成時はApplication変数としてコネクション管理をしていたのですが、当
然この方法ではまずい為、次の段階としてコネクション管理をセッション変数で実施しよ
うと考えました(セッション切断時のイベントでコネクションの開放が可能と思われるか
らです)。

但し、ユーザー都合によりクッキーの利用が出来ない為、Web.configでcookieless=
"true"としてクッキーレスなセッション管理を実施しようとしましたが、Webサービスメ
ソッド呼び出し時に以下のエラーが発生して実行が不能な状況になっています。

-------------------------------------------------------------------------------
'System.Net.WebException' のハンドルされていない例外が system.web.services.dll
で発生しました。

追加情報 : 要求は以下のエラーにより失敗しました。
--
<html><head><title>Object moved</title></head><body>
<h2>Object moved to
<a href='/SessionSample/(ubgdcj45uodupm45qhchhw45)/Service1.asmx'>here</a>
.</h2>
</body></html>

--.
-------------------------------------------------------------------------------

なお、cookieless="false"にすると正常に動作する事は確認しています。
また、Webサービス側でデバッグ実行して起動されたIEから、セッション管理対象のメソ
ッドを呼び出してもやはり同様の現象(cookieless="false"だと正常に動作するが、
"true"の場合はエラー(メッセージは異なる→InvalidOperationException: 要求形式が認
識されません))が発生します。

ご質問になりますが、
・Webサービスでは、cookieless="true"でのセッション管理は実行できないのでしょう
か?
・なにか必要な手順を踏んでいない(クッキーを使用する場合とは異なる処理を行わな
ければならない)のでしょうか?
・それとも、何かの設定がまずい(IIS?、ASP.NET?)のでしょうか?

以前似たような質問が投稿されていたようですが、未解決のままだったようなのでご質問
させていただきました。

ご存知の方がいらっしゃいましたらご教授下さい。
参考までに当方でエラーが発生しているソースを以下に添付します(大変長くなってしま
い、申し訳ありません)。
よろしくお願いします。


■Webサービス側■
Imports System.Web.Services

<System.Web.Services.WebService(Namespace := "http://tempuri.org/SessionSample/Service1")> _
Public Class Service1
Inherits System.Web.Services.WebService

#Region " Web サービス デザイナで生成されたコード "

Public Sub New()
MyBase.New()

'この呼び出しは Web サービス デザイナで必要です。
InitializeComponent()

' InitializeComponent() 呼び出しの後に独自の初期化コードを追加してください。

End Sub

'Web サービス デザイナで必要です。
Private components As System.ComponentModel.IContainer

'メモ : 以下のプロシージャは、Web サービス デザイナで必要です。
'Web サービス デザイナを使って変更することができます。
'コード エディタによる変更は行わないでください。
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
components = New System.ComponentModel.Container()
End Sub

Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
'CODEGEN: このプロシージャは Web サービス デザイナで必要です。
'コード エディタによる変更は行わないでください。
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

#End Region

<WebMethod(EnableSession:=True)> _
Public Function HelloWorld() As String
Return "Hello World"
End Function

<WebMethod(EnableSession:=True)> _
Public Function Addition(ByVal i As Integer) As Integer
Dim value As Integer
If IsNothing(Me.Session("value")) Then
value = 0
Else
value = CType(Me.Session("value"), Integer)
End If

value += i

Me.Session("value") = value

Return value
End Function

<WebMethod()> _
Public Function GetSessionID() As String
Return "hoge"
End Function

End Class

■クライアント側■
Module Module1
Public Sub main()
Dim proxy As SessionSample.Service1 = New SessionSample.Service1
proxy.CookieContainer = New System.Net.CookieContainer

System.Console.WriteLine("PG Start.")
System.Console.WriteLine(proxy.HelloWorld())
System.Console.ReadLine()
End Sub
End Module
todo
ぬし
会議室デビュー日: 2003/07/23
投稿数: 682
投稿日時: 2007-09-21 22:05
構想だけ。

サーバ側
ダミーなページ dummy.aspx を用意する。

クライアント側
dummy.aspx を HTTP GET して、レスポンスのヘッダからセッションID付きのURLを取得する。
WebサービスプロキシのUrlプロパティにそのURLを設定する。
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2007-09-22 00:40
引用:

セッション管理を行なう理由は、このWebサービスではデータベースアクセスが発生する
のですが、都度コネクションを作成するとパフォーマンスが悪い為、


本当に悪かったですか?
リソースの利用効率から言っても、通常は普通のコネクションプールを使用する方が望ましいと思いますが…

引用:

但し、ユーザー都合によりクッキーの利用が出来ない為、


本当に使えないのでしょうか?
ユーザの都合とは何でしょう?
Webサービスのクッキーを禁止するというのはちょっと理由が思いつきません。
※.NET内での話としてみてますが。

そもそもセッションなど使わない前提でならあるのかもしれませんが、
URL使ってでもセッションを使いたい、という場面でクッキーを禁止する理由は無いと思います。


で、根本的には最初に書いたようにそんなことにセッションを使うのがそもそも間違いでしょう。
KeiOS
会議室デビュー日: 2007/09/21
投稿数: 4
投稿日時: 2007-09-23 00:30
引用:

todoさんの書き込み (2007-09-21 22:05) より:
構想だけ。

サーバ側
ダミーなページ dummy.aspx を用意する。

クライアント側
dummy.aspx を HTTP GET して、レスポンスのヘッダからセッションID付きのURLを取得する。
WebサービスプロキシのUrlプロパティにそのURLを設定する。




todoさん、ご返答ありがとうございました。
プロキシのUrlプロパティと、リダイレクトした先のアドレスが違っているのが問題だと
いうことですね。参考になります。
なちゃさんのご指摘とあわせて検証してみたいと思います。
KeiOS
会議室デビュー日: 2007/09/21
投稿数: 4
投稿日時: 2007-09-23 01:04
なちゃさん、ご返答ありがとうございます。

引用:

なちゃさんの書き込み (2007-09-22 00:40) より:
引用:

セッション管理を行なう理由は、このWebサービスではデータベースアクセスが発生する
のですが、都度コネクションを作成するとパフォーマンスが悪い為、


本当に悪かったですか?
リソースの利用効率から言っても、通常は普通のコネクションプールを使用する方が望ましいと思いますが…



本当に悪かったです。残念ながら「このぐらい悪いです」というのは記録していなかった
ので提示できませんが。
利用効率とパフォーマンスは別の話ではないでしょうか??

ただし、ご指摘を受けてちょっと自信がなかったのは、最初にWebメソッド実行都度コネ
クションを作成/開放していた際に、コネクションプールがちゃんと使われているかどう
かは検証できていなかったので、もう一度確認してみたいと思います。

なお、接続データベースはOracle10g(Rlease2)、データプロバイダは.NET Provider for
Oracle(Oracle製のものではなく、Microsoftで配布しているもの。最終的にはODP.NETを
使用する予定です)を使ってプロトタイプを作成しています。

#
# ほうっておけば通常コネクションプールが使われるものだと思っていましたが。
# データプロバイダや、接続文字列設定値の指定等の問題で正常に機能していなかった
# のかもしれません。
#

引用:

なちゃさんの書き込み (2007-09-22 00:40) より:
引用:

但し、ユーザー都合によりクッキーの利用が出来ない為、


本当に使えないのでしょうか?
ユーザの都合とは何でしょう?
Webサービスのクッキーを禁止するというのはちょっと理由が思いつきません。
※.NET内での話としてみてますが。

そもそもセッションなど使わない前提でならあるのかもしれませんが、
URL使ってでもセッションを使いたい、という場面でクッキーを禁止する理由は無いと思います。


で、根本的には最初に書いたようにそんなことにセッションを使うのがそもそも間違いでしょう。




私がひとつ思い違いをしているのかも知れませんが、Webサービスで使用するクッキーは
結局のところ該当クライアントのWebブラウザのクッキーとして処理されるのではないの
ですか?
だとすれば、「本当に使えない」し、使えない理由は「ユーザーの都合」です。

# ユーザーが、ユーザー運用環境においてクッキーの使用を禁止しているためです。

私のお客さんではあまり珍しい事例ではないのですが、世間一般ではめずらしいのでしょ
うか??

↑が思い違いなのであればユーザーにWebサービスアプリケーションに関してのみクッキ
ーの使用を許可してもらうというのもひとつの手ではありますね。
ユーザーが社内で運用している別のシステムでは.NETのWebアプリケーションとして作成
されているものがあり、こちらはクッキーレスのセッション管理を行っているため、この
方法でという要望があったことが背景としてあります(個人的にこの手法をどう思ってい
るのかは別の問題です:仕事ですので)。

Webサービスが原則ステートレスである点については承知していますが、今回の作業では
基幹業務っぽいドメインに属するシステムを扱うため、結構パフォーマンスを気にされて
います(割にはクライアントサーバ型はいやだとのたまわれていますが)。
私としても当初は接続プールが何とかしてくれるだろうぐらいの勢いで考えていたのです
が、やってみたら案外遅かった事、接続を使いまわしてみたら逆に案外速かった事もあり
、苦肉の策としてFirst CGIライクな本対応を検討しました。

おっしゃるとおり、接続プールでの対応で不都合がなければセッションを使う必要はない
と思います。当方で検証して、再度この場でご報告させていただきます。
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2007-09-23 03:15
引用:

本当に悪かったです。残念ながら「このぐらい悪いです」というのは記録していなかった
ので提示できませんが。
利用効率とパフォーマンスは別の話ではないでしょうか??


なので、リソースの利用効率から言って「も」というような書き方をしたんですが、まあそれはそれとして…

コネクションプールを使った場合でももちろんプールの管理の手間は入りますから、まったく処理を行わないのに比べたら負荷はかかりますが…
どのくらいというのを記録してないということは、結構体感でわかるくらいに悪かったってことですかね?
通常はパフォーマンスの理由で使えないほど悪いってことは無いと思うんですけどね〜
まあもう一度検証してみたほうがいいのではないかと思います。

引用:

私がひとつ思い違いをしているのかも知れませんが、Webサービスで使用するクッキーは
結局のところ該当クライアントのWebブラウザのクッキーとして処理されるのではないの
ですか?
だとすれば、「本当に使えない」し、使えない理由は「ユーザーの都合」です。

# ユーザーが、ユーザー運用環境においてクッキーの使用を禁止しているためです。


微妙にどっちの意味で書かれてるのかわかりづらいんですが、Webサービスを.NETのプロキシから呼び出す場合、クッキーはコードで直接CookieContainerを設定する使い方になります。
これは純粋に単なる.NET上でのデータ構造であり、ブラウザのクッキーとは関係ありません。
なので、少なくとも.NET上で呼び出しを実行する場合にこれを禁止しなければならない意味が思いつかないということです。

引用:

↑が思い違いなのであればユーザーにWebサービスアプリケーションに関してのみクッキ
ーの使用を許可してもらうというのもひとつの手ではありますね。
ユーザーが社内で運用している別のシステムでは.NETのWebアプリケーションとして作成
されているものがあり、こちらはクッキーレスのセッション管理を行っているため、この
方法でという要望があったことが背景としてあります(個人的にこの手法をどう思ってい
るのかは別の問題です:仕事ですので)。


なんでお客さんがその要望をしているのか理由を明確にしてもらって、問題ないのであれば使わせてもらう、あるいは目的上より望ましい方法を提案するなどは、仕事だからこそ重要だと思います。

ってまあ現実にはいろいろ事情があるのもわかりますけどね。
Webアプリでクッキーを禁止してURLでセッション使ってるってのは(携帯用サイトなどやむをえない理由がある場合を除くと)結構重症な気がするので、話が通じないかもしれませんが。

Webサービスのクッキーに関してはブラウザが絡むWebアプリのクッキーとは別として捕らえたほうがいいと思いますし、無理やりURLでセッションを使うこともいらん苦労を呼び込むだけだと思いますよ。
その辺りを全部説明してそれでも駄目だといわれるならもう仕方ないですが…

引用:

Webサービスが原則ステートレスである点については承知していますが、今回の作業では
基幹業務っぽいドメインに属するシステムを扱うため、結構パフォーマンスを気にされて
います(割にはクライアントサーバ型はいやだとのたまわれていますが)。


まず、接続を使いまわすためだけにセッションを使うこと自体が、パフォーマンス的に見ても望ましい方法では無いでしょうってまあこれは使い方にもよりますが。
例えば同一クライアントから複数接続すると同時に処理されないなんて問題にも遭遇するかもしれませんし、同時接続があるならもう単純な使いまわしはできないですよね?

仮に同時接続は絶対無いと仮定しても、そもそもセッションで接続を保持しなくとも、何かのコレクションに覚えといてひとつずつ取り出せばすむのではありませんか?
※ユーザごとに接続文字列が違うとかならそこまで単純にはいきませんが。

まあそんなことやりだす前にまずは接続プールのパフォーマンスをきっちり検証するほうが先だと思います。
悪い場合はそのときのCPU負荷等がどの程度なのかとかも含めて(もし悪い理由が純粋にCPU負荷ではないのなら、レスポンスは多少悪くなってもスループットにはほとんど影響しない、などの可能性もあるかも知れませんし)。
パフォーマンスの検証は、実際に想定されるようなユーザ数などで負荷をかけてスループットとレスポンスを両方検証しないと、後で痛い目に会う危険もあります。

どの程度のユーザ数なのかわかりませんが、セッションで常時接続をユーザ数分維持するのは、リソース的には相当無駄が多いでしょう。
パフォーマンスに直結ずるとは限りませんが、通常無駄なリソースを維持することはパフォーマンス上望ましく無い場合が多いと思います。特に昨今のように、CPU処理能力が高い環境では。
KeiOS
会議室デビュー日: 2007/09/21
投稿数: 4
投稿日時: 2007-09-25 09:08
なちゃさん、ご返答ありがとうございます。

引用:

なちゃさんの書き込み (2007-09-23 03:15) より:
コネクションプールを使った場合でももちろんプールの管理の手間は入りますから、まったく処理を行わないのに比べたら負荷はかかりますが…
どのくらいというのを記録してないということは、結構体感でわかるくらいに悪かったってことですかね?
通常はパフォーマンスの理由で使えないほど悪いってことは無いと思うんですけどね〜
まあもう一度検証してみたほうがいいのではないかと思います。


はい。明らかに悪かったです。
正直「多少」なんてものでなかったのです。
なので、なちゃさんのご指摘を受けた際に接続プールが正常に動作していなかったのか
なと感じた次第です。

引用:

微妙にどっちの意味で書かれてるのかわかりづらいんですが、Webサービスを.NETのプロキシから呼び出す場合、クッキーはコードで直接CookieContainerを設定する使い方になります。
これは純粋に単なる.NET上でのデータ構造であり、ブラウザのクッキーとは関係ありません。



ブラウザでクッキーを禁止していてもクライアント側でCookieContainerの設定を行なっ
ていれば問題なく利用可能ということですね。
ちょっと思い違いをしていたようです。ありがとうございます。

引用:

仮に同時接続は絶対無いと仮定しても、そもそもセッションで接続を保持しなくとも、何かのコレクションに覚えといてひとつずつ取り出せばすむのではありませんか?



初めに単一ユーザーの同時接続はクライアントプログラム側で多重起動を許可させないよ
うにして対応可能だと言う前提でお話をします(別のプログラムでWebサービスを使われ
たらなんて考えると破綻しますが、こんな事はイントラネット環境で利用している場合は
事実上ほとんどないと想定できるからです)。

「コレクションに覚えといて」と言う方法は私の方でも考えました。
ほとんどの場合は確かに問題ないと思いますが、クライアント側で実行時エラーが発生し
た場合なんかを考慮すると、どうしてもタイムアウトをサーバー側で捕捉してあげなきゃ
いけなくなる(クライアントから明示的に開放処理が実施されない場合にリソースを開放
する手段がなくなる為)かなと考え、そんなことするの面倒でかなわないと思って断念し
ました。

引用:

まあそんなことやりだす前にまずは接続プールのパフォーマンスをきっちり検証するほうが先だと思います。



仰るとおりだと思います。
トリッキーな手段は極力利用しないに越した事はないですからね。

接続プールを使った場合と、接続を使いまわす場合の性能差については後日この場で報告
させていただきます。

ありがとうございました。
1

スキルアップ/キャリアアップ(JOB@IT)