微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

第一次调用WebService慢的原因和解决办法

我们经常抱怨首次调用WebService比较慢,通常的做法是在程序启动的时候,后台逐一调用一遍所有的WebService,还有人利用多线程来解决这个问题。其实,大家只是看到了问题的现象以及“工程”的解决办法,而没有接触到问题的本质。经过本人反编译.Net类库,逐步查找,应该说找到了解决这个问题的根本办法。我们都知道,WebService是通过Soap协议来传递消息的,所有的消息都是XML,而在客户端和服务器端,都是使用的对象,这其中必然有一个XML和对象之间的转换,这个转换就是慢的罪魁祸首。下面,我就逐步分析,希望对你能有帮助,请耐心看完。

1.       添加Web引用的时候,WebService在客户端有一个代理,如下:

   

复制代码

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services","2.0.50727.42")]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Web.Services.WebServiceBindingAttribute(Name="WebService1Soap",Namespace="http://te@R_502[email protected]/")
   public partial class WebService1 : System.Web.Services.Protocols.soapHttpClientProtocol

 
 
客户端调用WebServivce就是通过这个代理类来调用的。
2.        调用WebService方法,客户端和服务器端通信是Xml,所以代理类跟Xml之间就有序列化和反序列化的过程
3.        客户端调用WebService的过程如下
a)          客户端调用代理类Hello world方法
string  str = (new Service2.WebService1()).HelloWorld ();
b)          代理类调用基类SoapHttpClientProtocal的Invoke方法
        [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/HelloWorld0766",RequestNamespace="http://tempuri.org/",ResponseNamespace="SoapBindingUse.Literal,ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
        public string HelloWorld() {
            object[] results = this.Invoke("HelloWorld"new object[0]);
            return ((string)(results[0]));
        }
c)          SoapHttpClientProtocal进行Soap序列化Soap头和方法,都是这个类自己做的,但是输入参数和返回值,是利用的XmlSerializer,输入参数要序列化,返回值要反序列化。
        protected object[] Invoke(string methodName, object[] parameters)
        {
                
                try
                {
                    message1.SetStream(stream1);
                    this.Serialize(message1);// 注1
                }
               
                response1 = this.GetWebResponse(request1);
                Stream stream2 = null;
                    stream2 = response1.GetResponseStream();
                    objArray1 = this.ReadResponse(message1,response1,stream2, false);// 注2
          }
         
           注1:this.Serialize中有一句参数序列化的代码如下
          method1.parameterSerializer.Serialize(writer1,message.GetParameterValues(), null,flag1 ? text2 : null);
           注2:this.ReadResponse中有一句返回值的反序列化的代码如下
          message.SetParameterValues((object[]) method1.returnSerializer.Deserialize(reader1,flag1 ? text1 : null));
d)          XmlSerializer会缓存临时程序集,这个程序集作用是序列化和反序列化,如果缓存中没有会调用TempAssembly产生一个
 
Static 的缓存(就是我们每次调用慢的罪魁祸首): private  static TempAssemblyCache cache;
获取缓存中的程序集:this.tempAssembly = XmlSerializer.cache[defaultNamespace,type];
缓存中没有就去加载: Assembly  assembly1 = TempAssembly.LoadGeneratedAssembly(type,defaultNamespace, outimplementation1);
加载没有就去产生(会生成临时文件并编译,很慢):
this .tempAssembly = new TempAssembly(new XmlMapping[] { this.mapping },assembly1,implementation1);
e)          TempAssemlby这个类负责加载以及产生临时程序集
LoadGeneratedAssemlby 方法中,有一段逻辑,就是默认去加载序列化类,这个类的命名是规则如下
        internal static string GetTempAssemblyName(AssemblyName parent, string ns)
        {
            return (parent.Name + ".XmlSerializers" + (((ns == null) || (ns.Length == 0)) ? "" : ("." + ns.GetHashCode())));
        }
        同时,如果加载失败会触发 AppDomain .CurrentDomain.AssemblyResolve 事件
        
4.        结论
1)    WebService 的序列化是调用 XmlSerializer
 
2)    WebService 慢,是因为产生序列化类慢,所谓的临时文件都是 XmlSerializer 的中间代码。可以在config文件中加入如下的配置,临时序列化的文件就不会被删除了,WinForm程序是*.exe.config,asp.net是web.config。
        <configuration>  <system.diagnostics>    <switches>      <add name="XmlSerialization.Compilation" value="4"/>    </switches>  </system.diagnostics></configuration>
推荐的解决方法:

在应用程序的config文件中加入以下配置节:

   <system.net>
    <defaultProxy enabled="false" useDefaultCredentials="false">
      proxy/>
      bypasslistmodule/>
    </defaultProxy>
  >

复制代码

          或者在程序入口加入以下代码

      HttpWebRequest.DefaultWebProxy = null;

 


猜你在找
查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐