加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

为什么第一次调用WebService慢呢?

发布时间:2020-12-16 22:56:50 所属栏目:安全 来源:网络整理
导读:添加Web引用的时候,WebService在客户端有一个代理,如下: ??? [System.CodeDom.Compiler. GeneratedCodeAttribute ( "System.Web.Services" ,? "2.0.50727.42" )] ??? [System.Diagnostics. DebuggerStepThroughAttribute ()] ??? [System.ComponentModel.
添加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://tempuri.org/")
? ?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;
????????????????try
??????????????? {
??????????????????? 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,?out?implementation1);
加载没有就去产生(会生成临时文件并编译,很慢):
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>
?
临时文件在C:Documents and Settings 抹布Local SettingsTemp下,注意,因为名称是随机的,序列化的dll文件,并不能重用,重开进程会重新生成。
3)??? 如果自定义序列化类,可以跳过产生临时序列化的步骤,大大提高第一次加载的速度,也就是说,只要有一个
程序集名称 + .XmlSerializers ”的序列化类存在,就不会动态生成序列化程序集了。
?
4)??? 在代理类上可以加
[System.Xml.Serialization.XmlSerializerAssemblyAttribute(AssemblyName =?"TestPerformance.XmlSerializers")]
指定Xml序列化的类,这个序列化的类可以通过一个工具产生,
但是根据研究TempAssemlby的LoadGeneratedAssemlby代码发现,这个Attribute可以不加的,只要你有一个GetTempAssemblyName返回值一样的名称的序列化类即可。
?
5)??? 根据加载失败会触发 AppDomain .CurrentDomain.AssemblyResolve 事件,可以在加载失败后动态产生序列化类,如下。
????????http://support.microsoft.com/kb/872800/zh-cn,请参考这个kb
??? ??private?void?Form1_Load(object?sender,?EventArgs?e)
??????? {
????????????AppDomain.CurrentDomain.AssemblyResolve +=
????????????????new?ResolveEventHandler(MyResolveEventHandler);
??????? }
?
????????static?Assembly?MyResolveEventHandler(object?sender,?ResolveEventArgs?args)
??????? {
????????????Assembly?a =?null;
????????????string[] arr = args.Name.Split(new?string[] {?"."?},?StringSplitOptions.None);
????????????if?(args.Name.IndexOf("XmlSerializers") >= 0)
??????????? {
????????????????if?(!System.IO.File.Exists(args.Name +?".dll"))
??????????????????? PreGenNS.Pregen.Generate(new?string[] { arr[0] });
????????????????string?sSerializersDLL = args.Name +?".dll";
????????????????string?smartDeploymentHostLocation =?"";
??????????????? a =?Assembly.LoadFrom(smartDeploymentHostLocation + sSerializersDLL);
??????????? }
????????????return?a;
??????? }
6)VS2005利用Release编译,会产生AssemblyName+"XmlSerializer.dll"的序列化文件,可以随着客户端一起部署,跟5这种方式不太一样,可以根据实际情况来选择。
利用5这种方式,是第一次调用WebService时,动态生成序列化类;而6是在软件发布时,生成这个类,并部署到客户端。

转载:http://www.cppblog.com/eday/articles/36045.html

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读