首页 | 编程语言 | 网站建设 | 游戏天堂 | 冲浪宝典 | 网络安全 | 操作系统 | 软件时空 | 硬件指南 | 病毒相关 | IT 认证
软讯网络 > 编程语言 > .NET > VB.NET > More on connection pooling in a web application
【标  题】:More on connection pooling in a web application
【关键字】:More,on,connection,pooling,in,web,application
【来  源】:http://blog.joycode.com/demonfox/archive/2006/11/29/88250.aspx

More on connection pooling in a web application

Thread pooling for web connections中我曾经提到Shared Source CLI,这次再借用另一个场合宣传一下这个"Open Source .NET Framework"吧。

Topic还是web connection pooling:可以很自然地想到我们可以设计这么一个class:

class WebConnector

{

    WebRequest CreateRequest(string targetUrl)

    {

        return WebRequest.Create(targetUrl);

    }

    ...

}

这个class现在什么都没有做,因为我们的希望是.NET提供的WebRequest可以提供一定的pooling mechanism,如果真是那样,那生活真是很美好,我们什么都不要做就可以下班了。而其实这也不是什么太wild的dream,毕竟是.NET,连个pooling都不提供,也不要混了。

在深入研究一下WebRequest class之前,我们还需要考虑一个问题:web application很常见的会用到其他的web service,也就是用SOAP像其他web service请求服务。在Visual Studio中如何生成web service的proxy class等等我就不用重复重复了吧(wsdl.exe等等的)?关键在于:这个由wsdl自动生成proxy class用的是什么connection mechanism呢?虽然基本可以想到应该也是somewhere, somehow用的WebRequest,但还是让我们double check一下。找任意一份wsdl生成的proxy class的代码看看:

public partial class WSProxcyClass : System.Web.Services.Protocols.SoapHttpClientProtocol

嗯,看来基本功能都在SoapHttpClientProtocol这个类里面。

再研究一下MSDN里SoapHttpClientProtocol的API,aha,有这么一个member function:

protected override WebRequest GetWebRequest(Uri uri)

看来所有SoapHttpClientProtocol里面用到的WebRequest都是通过这个函数来取得的。注意一下前缀的override关键字,很好很好,这说明如果我们对WebRequest现有的pooling mechanism不满意的话(或者WebRequest根本没有提供pooling机制),我们可以从SoapHttpClientProtocol派生一个类,然后改写掉GetWebRequest来实现我们满意的pooling机制。其他的接口都还是用SoapHttpClientProtocol,而WSProxyClass只要继承新的派生类就可以了。

 

嗯,很好,至少我们有了backup plan,虽然麻烦了一点点,但也算不错,感谢SoapHttpClientProtocol良好的界面。

现在该进一步了,我们来研究一下WebRequest到底有没有提供pooling吧。

(题外话:可以看到.NET源代码的朋友可以研究一下SoapHttpClientProtocol的实现,这里是一个class hierarchy:

WebClientProtocol

-> HttpWebClientProtocol

    -> SoapHttpClientProtocol :
你会发现,GetWebRequest其实一直延伸到最基类的WebClientProtocol里,有不少messy stuff to deal with,所以真的要改写GetWebRequest并非那么容易。不过,anyway, that's a side note to this article, we are heading for better stuff, baby.

这下该用到,搜一下webrequest.cs,嗯嗯,time to read the source code:

private static WebRequest Create(Uri requestUri, bool useUriBase) {

    string LookupUri;
    WebRequestPrefixElement Current = null;
    bool Found = false;

    if (!useUriBase) {
        LookupUri = requestUri.AbsoluteUri;
    }
    else { 
        // schemes are registered as <schemeName>":", so add the separator
        // to the string returned from the Uri object

        LookupUri = requestUri.Scheme + ':';
    }

    int LookupLength = LookupUri.Length;

    // Copy the prefix list so that if it is updated it will
    // not affect us on this thread.

    ArrayList prefixList = PrefixList;

    // Look for the longest matching prefix.

    // Walk down the list of prefixes. The prefixes are kept longest
    // first. When we find a prefix that is shorter or the same size
    // as this Uri, we'll do a compare to see if they match. If they
    // do we'll break out of the loop and call the creator.

    for (int i = 0; i < prefixList.Count; i++) {
        Current = (WebRequestPrefixElement)prefixList[i]; 


        // See if this prefix is short enough.
        if (LookupLength >= Current.Prefix.Length) { 
            // It is. See if these match.
            if (String.Compare(Current.Prefix, 0, LookupUri, 0, Current.Prefix.Length, StringComparison.OrdinalIgnoreCase ) == 0) {

                // These match. Remember that we found it and break
                // out.
                Found = true;
                break;
            }
        }
    }

    WebRequest webRequest = null;

    if (Found) {

        // We found a match, so just call the creator and return what it
        // does.

        webRequest = Current.Creator.Create(requestUri);
        return webRequest;
    } 


    // Otherwise no match, throw an exception.
    throw new NotSupportedException(SR.GetString(SR.net_unknown_prefix));
}

 

WebRequest.Create就是最后的生成一个个实际的request object的地方。如果有pooling mechanism,在这里也该看出些端倪来了。

嗯,这段代码实在太有意思了。看懂了么?WebRequest有一个url prefixlist这样的列表,对于每个注册过的url prefix,都有一个对应的Creator来create相应的webrequest。可以想象的,一定还有一个" * "这样的prefix来匹配所有没有注册的prefix。

而匹配prefix的过程更是有趣,如果你仔细研究并理解我用红色highlight的comment的话,一定可以看出为什么了。不过这个不是我的focus,我就不分析了。

重要的是,我们知道有Creator这么一个东西,而且用户可以注册不同的url用不同的Creator,比如对于连接到www.microsoft.com的webrequest有一种要求,对于连接到www.amazon.com的webrequest有另一种要求,这些要求都可以customize。

^_^ 很好很好,我们已经很接近了。现在只有最后两个问题了,怎么customize webrequest? 以及,可以customize到什么程度?

嗯,第二个问题很好,我猜,答案是。没准,嗯,没准可以customize的程度很高?高到可以让我们指定pooling的功能!!

现在所有的线索都串起来了,我们知道有那么一个Creator,特别是那个匹配" * " (即所有)url的Creator,它应该可以是customize的,而且很可能允许我们指定pooling的一些参数。

那好,现在只有最后一个问题了:怎么customize?

难不成要我们自己派生几个Creator的子类,然后改写一下Create函数??

太复杂了吧。藏的这么深,谁知道这一把怎么玩的。。。

嗯,找找线索。

而线索也只有一条了:Creator的type!

Current = (WebRequestPrefixElement)prefixList[i];

webRequest = Current.Creator.Create(requestUri);

Bingo! WebRequestPrefixElement!

Hmm, element, element, element... 想到了什么?web.config里的configuration element么!

web.config -- we are almost done, baby.

让我们查一下msdn里system.net configuration element的文档(因为webrequest类在system.net里),有4个child element:

<authenticationModules> Specifies the modules used to authenticate Internet requests.
<connectionManagement> Specifies the maximum number of connections to Internet hosts.
<defaultProxy> Specifies the proxy server used for HTTP requests to the Internet.
<webRequestModules> Specifies the modules used to request information from Internet hosts.

找到了,从connectionManagement里你可以看到如何设置maxConnection #,然后最低下有指向ServicePoint和ServicePointManager的连接,那里,有如何设置pooling的介绍。

 

Well, quite an adventure, isn't it?  I mean, it really doesn't have to take that much if you know system.net.connectionManagement element from the every beginning. I just found this process of following the cues, digging around, pondering about things, etc is quite some fun and definitely worth the time, : )

At least, for me, it is.

Hope you enjoyed it.

========================================================

升级后没有了code highlighter真不方便啊,code snippet在我的主页上看好好的,在博客堂的主页上看就很乱。

博客堂新版本功能集:【上一篇】
技巧和诀窍:使用ASP.NET 2.0 输出缓存替换的功能实现“甜圈缓存(Donut Caching)”:【下一篇】
【相关文章】
  • 11月30日:2007 Microsoft Office system、Windows Vista、Exchange Server 2007 产品发布会
  • javascript在href和在onclick中的区别
  • weblogic各版本下载地址大全
  • linux不同字符集之间转换
  • [proof-of-concept]cisc0-brute
  • Linux+FTP
  • 实用的css option
  • linux下安装sqldeveloper将
  • [免费培训]12月2日免费嵌入式Linux预科班
  • 嵌入式linux下常见的文件系统
  • 【随机文章】
  • 智能小区全套解决方案(2)
  • 建立数据库连接
  • [原创]添加连续规则子域的DNS管理脚本1
  • How to create a MEX file using the Microsoft Dev
  • 用VB实现图像切换效果
  • 网络安全中防火墙和IDS的作用
  • Free translation software for Linux
  • 免费新书推荐: Mastering EJB 3.0
  • 光纤、光缆介绍(2)
  • 基于LINUX的高可用性集群技术分析
  • 【相关评论】
    没有相关评论
    【发表评论】
    姓名:
    邮件:
    随机码*
    评论*
          
    |  首 页  |  版权声明  |  联系我们   |  网站地图  |
    CopyRight © 2004-2007 软讯网络 All Rigths Reserved.