Thread pooling for web connections

4410 ワード

[Main Reference:http://msdn.microsoft.com/msdnmag/issues/04/12/NETMatters/」
今回は、clientアプリでHttpWebRequestを使ってserverにサービスを要請するということです。NET 1.xの中で、もしあなたが併発したHttpWebRequestの数が多すぎると、あなたは発見します。NETはこのようなexceptionを投げ始めました。The were not enough freads in the ThreadPool oject to compect the operation。これはどんな原因ですか?
答えはいつもソースコードで探します。Shared Source CLIの実現を見たら(ちなみに、SSCLIをダウンロードすることをお勧めします。NETはオープンソースではありませんが、SSCLIの多くの実現は忠実に表現されています。NETでは多くのデザインの概念と方法があります。)、実は1.xのNET frame ebookの中で、HttpWebRequestはAsynchnousです。
 
public override WebResonse Get Resonse()
{  ....  IAsyncResult asynccResult=BeginnGet Resonse(null,null)  ....  return EndGetResonse(async Resoult);
 
BeginnGet Resonseは実はThread poolの中でqueueの一つのwork itemに行っています。(thread poolを使った友達はQue UserWorkItemというAPIをよく知っているはずです。)これはなぜ異常を引き起こすのですか?
デッドロック。
私たちはThread Poolの中に一つだけのthreadがあると仮定して、初めてGetResonseを呼び出した時に、Thread poolの中で唯一のthreadを使いました。GetResonseはBeging GetResonse queueを呼び出してください。しかし、残念ながら、BeginnGet Resonseは永遠に実行されました。唯一のthreadはGet Resonseによって使用されました。
現実的には、thread poolは一つのthreadしかないはずがない。しかし、このような情況はやはり発生して、例えばthread poolは10つのthreadがあって、あなたが連続してqueue 10つのwork itemに入る時、同様に生死の鍵を出します。
1.xの中で、NETの方便は例外を投げます。BeginnGet Resonseの最後に、queue user work itemの前に、プログラムはSystem.Net.Connection.Is ThreadPoollowをチェックします。trueであれば、InvalidOpeartional Exceptionの異常を突破します。
しかし、上のSSCLIのこの部分の実現を見てみると、GentResonseにはBeginnGet Resonse/EndGet Resonseはまったく使われていないことが分かります。(ほほほ、実は最初から見ていました。NETのsource codeは、BeginnGet Resonse/EndGetResonseがまったくないことを発見しました。だから、元の著作者は乱雑に引っ張っていますか?後に文章を見てから分かります。NET 2.0では、GetResonseは本当にsynchronous callを使っています。だから、デッドロックの問題もありません。
では、1.xのNETでは、どのように人間が干渉して、デッドロックの発生を防ぐのですか?
一番明らかな答えはもちろんsemaphoreを使っています。
もっとかわいそうなのは.NET 1.xはsemaphoreもないということです。
じゃ自分でwrapしてwin 32のAPIを作らなければなりません。
 
public sealed class Semaphore : WaitHandle
{
    public Semaphore() : this(1, 1) {}

    public Semaphore(int initialCount, int maximumCount)
    {
        if (initialCount < 0 || initialCount > maximumCount)
            throw new ArgumentOutOfRangeException("initialCount");
        if (maximumCount < 1)
            throw new ArgumentOutOfRangeException("maximumCount");
        IntPtr h = CreateSemaphore(
            IntPtr.Zero, initialCount, maximumCount, null);
        if (h == WaitHandle.InvalidHandle || h == IntPtr.Zero)
            throw new Win32Exception();
        Handle = h;
    }

    public void ReleaseOne()
    {
        int previousCount;
        if (!ReleaseSemaphore(Handle, 1, out previousCount))
            throw new Win32Exception();
    }

    [DllImport("kernel32.dll", SetLastError=true)]
    private static extern IntPtr CreateSemaphore(
        IntPtr lpSemaphoreAttributes, int lInitialCount,
        int lMaximumCount, string lpName);

    [DllImport("kernel32.dll", SetLastError=true)]
    private static extern bool ReleaseSemaphore(
        IntPtr hSemaphore, int lReleaseCount, out int lpPreviousCount);
}
 
Semaphoreでスレッド数を併発するコードを制御するにはどうすればいいですか?経典のproducer/consumerの問題、あるいは原文のcode snippetを参考にしてもいいです。
==================================================================================================================
いくつかのcomments:
web connection poolingは、どのような大きなwebアプリに対してもほとんど必要であるが、2.0では、NETは同期スレッド数をどのように制御しているのか?web connectionに対して、他の構成可能な変数がありますか?
答えはあります。興味がある友達は見てもいいです。ServicePoint、ServicePointManager、system.net configration element。今度はこの内容について紹介します。
 
ハイグレードsecurity-concern、ハイflexibilityを要求するwebアプリケーションの中で、以下のいくつかは私がずっと覚えています。
1.Sacrifice performance for design simplity.
2.Sacrifice functionlity for performace.
3. If a functionlity is really desired and a must-have、at least provide a fallback so that user can get their relt in a not intutive but fast fashion.
複雑なdesignはミスしやすく、セキュリティ・ホールがありやすく、自分のsecurity mechange ismが壊れにくいと思っている時に、無数のハッカーが動き始めています。一番いいsecurityは何ですか?public key crytographyだけで、すべての敏感データを暗号化することができたら一番安全です。。
Performanceについては、everextra second your service tars、you lose 10% more users.私はまず簡単なシステムがほしいです。そして、alpha、betaテストを出して、caching mechanismをいっぱい設計します。xslant trnslation、throttling、blah blah、見たところとても綺麗です。本当に遅くて耐えられません。後で太ったシステムを直します。価格はとても大きいです。