最近正在维护以前别人遗留下的项目(04底的项目)
先介绍下项目大体情况,net1.1,C/S架构,使用remoting的http,(binary),IIS作为服务。
整个解决方案有200多个工程组成,实在是庞大。
代码部分就不说了(其代码和结构看了会让人疯了,代码质量差的没法说,命名空间非常混乱)。
据了解当时项目人员是3-4个左右,有M***公司开发,实在是跌眼镜。
问题:
客户希望优化性能,现在性能已经出现问题。
分析:
客户现在的生产环境有4台服务器负载均衡做为remoting服务端。从监控使用资源上看服务器几乎没压力。因此性能瓶颈不是服务器承受不了压力,基本是数据传输问题了,(网络vpn也是一部分原因,部分客户端速度比较低)
1.从服务端代码入手优化,这个几乎难以实现,时间紧,工程数量巨大,代码质量差。如要修改,改动量会很大。有人会问修改服务端即可,客户端影响不是很大。对于大多数remoting项目会采用接口方式,即在客户端部署接口,服务端部署接口实现,但此项目恰恰没这样做

2.优化remoting通讯方式。在net1.1下remoting最好的性能方式是tcp+binary。客户方不想修改现有的部署方式。虽然从http方式改成tcp方式不需做太大的改动,可客户不太赞成此方式。没办法了,只能最后一招了,压缩数据。net1.1下对dataset的传输可以说几乎没做压缩(net2.0已经改善),binary的序列方式和soap差别不是很大。
对dataset序列化方面优化可以参考 提高 DataSet 序列化和远程处理性能,和 优化.NET Remoting的传输的DataSet的序列化以提供性能
我没有采用此方式(偷懒了)而是直接采用压缩数据流方式。
实现:
remoting中压缩数据流不是很难,只需自定义sink即可。我使用的是7zip压缩组件,客户端实现IClientChannelSink,服务端实现IServerChannelSink即可。如果还不了解自定义sink可以详细阅读
等此sink完成后,客户端和服务端配置下即可。
客户端:

<clientProviders>

     <formatter ref="binary" />

     <provider type="CompressionSink.CompressionClientSinkProvider, CompressionSink" />

</clientProviders>

服务端:

<serverProviders>
     <provider type="CompressionSink.CompressionServerSinkProvider, CompressionSink" />

     <formatter ref="binary" />

</serverProviders>
NOTE:如果你详细阅读上面介绍的文章,就会了解客户端和服务端配置是有些小区别的,自定义的sink次序是不一样的。
经过测试效率还是比较好的,基本上能提高2.5倍的传输效率。测试数据这里就不放上来了。如果想具体了解的可以参考 性能比较:.NET Remoting 与 ASP.NET Web 服务
解决了?没有,客户在做测试的时候,又提出问题了,当服务器端部署压缩sink后,希望客户端无论部署和不部署sink,都能使用(因为如果服务端部署sink后,客户端如不部署就会造成数据流不一致,一端是压缩的数据,一段是没有压缩的)。
怎么解决?只能是有客户端标志下此客户端是否配置了sink,服务端接收后判断是否启用解压。
1.CallContext.SetData?在server端sink中是无法通过CallContext.GetData得到此消息的,因为CallContext的数据还没被还远,还是stream阶段(如果有误请指正)。通过测试,的确得不到CallContext.SetData设置的数据。
2.自定义MessageSink。使用自定义的messagesink来传输数据,经过测试也不行。如果客户端使用自定义的messagesink后,服务端虽然可以收到message,但是数据传输到客户端的时候会出错,本来想客户端先使用messagesink然后在使用compresssink处理,最后服务器又不行了,最后只能放弃(如有解决方案请告知)自定义message可以参考下面2篇文章,写的比较详细:
Using MSMQ for Custom Remoting Channel.
Remoting基本原理及其扩展机制(中)

似乎没办法了。
再看下

        public ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders,Stream requestStream, out IMessage responseMsg, out ITransportHeaders responseHeaders,out Stream responseStream) 

requestmsg是不能用了,requestheaders呢,这个还没试呢。
客户端:

    public void ProcessMessage(IMessage msg, ITransportHeaders requestHeaders,     Stream requestStream,out ITransportHeaders responseHeaders,out Stream responseStream) 
        {
            requestHeaders[
"Compress"= "True";
}

服务端:

public ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders,Stream requestStream, out IMessage responseMsg, out ITransportHeaders responseHeaders,out Stream responseStream) 
        
{
            
object compress = requestHeaders["Compress"];
if(compress != null && compress.ToString() == "True")
            
{
//使用7zip压缩
}

else
{
//不压缩
}

测试通过。如果服务端不配置sink,和配置sink完全能和服务端正常通讯。

代码下载
posted on 2007-02-09 22:21  try  阅读(3061)  评论(4编辑  收藏  举报