新しいシステムで使用する通信技術を評価しようとしていますが、WCFのパフォーマンスがひどいため、Remotingが唯一の選択肢であるように見えます。Remotingと比べてWCFのパフォーマンスが遅いのはなぜですか?
私は、nettcpを使用してIIS7でホストされているWCFサービスの呼び出しをベンチマークしました。これは、コンソールアプリケーションでホストされているリモーティングインターフェイスを呼び出すことと比較しています。 WCFサービスは、エンドポイントで1000個の要求を実行するのに約4.5秒かかります(単純にオブジェクトの新しいインスタンスを返す)。リモートクライアントは、同じタスクを実行するために、0.5秒間で<を取得します。ここで
は、WCFクライアントのコードです:
public class TcpNewsService : INewsService
{
private INewsService _service = null;
Lazy<ChannelFactory<INewsService>> _newsFactory = new Lazy<ChannelFactory<INewsService>>(() =>
{
var tcpBinding = new NetTcpBinding
{
//MaxBufferPoolSize = int.MaxValue,
//MaxBufferSize = int.MaxValue,
//MaxConnections = int.MaxValue,
//MaxReceivedMessageSize = int.MaxValue,
PortSharingEnabled=false,
TransactionFlow = false,
ListenBacklog = int.MaxValue,
Security = new NetTcpSecurity
{
Mode = SecurityMode.None,
Transport = new TcpTransportSecurity
{
ProtectionLevel = System.Net.Security.ProtectionLevel.None,
ClientCredentialType = TcpClientCredentialType.None
},
Message = new MessageSecurityOverTcp
{
ClientCredentialType = MessageCredentialType.None }
},
ReliableSession = new OptionalReliableSession { Enabled = false }
};
EndpointAddress endpointAddress = new EndpointAddress("net.tcp://localhost:8089/NewsService.svc");
return new ChannelFactory<INewsService>(tcpBinding, endpointAddress);
});
public TcpNewsService()
{
_service = _newsFactory.Value.CreateChannel();
((ICommunicationObject)_service).Open();
}
public List<NewsItem> GetNews()
{
return _service.GetNews();
}
}
とクライアントコードを呼び出すための単純なコンソールアプリケーション:IISホストの
var client = new TcpNewsService();
Console.WriteLine("Getting all news");
var sw = new System.Diagnostics.Stopwatch();
sw.Start();
for (int i = 0; i < 1000; i++)
{
var news = client.GetNews();
}
sw.Stop();
Console.WriteLine("Finished in " + sw.Elapsed.TotalSeconds);
Console.ReadLine();
web.configファイルは次のようになります。
<system.serviceModel>
<services>
<service behaviorConfiguration="NewsServiceBehavior" name="RiaSpike.News.Service.NewsService">
<endpoint address=""
binding="netTcpBinding"
bindingConfiguration="tcpBinding"
contract="RiaSpike.News.Types.INewsService">
</endpoint>
<endpoint address="http://localhost:8094/NewsService.svc"
binding="basicHttpBinding"
bindingConfiguration="httpBinding"
contract="RiaSpike.News.Types.INewsService">
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="NewsServiceBehavior">
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="httpBinding">
<security mode="None">
<transport clientCredentialType="None" />
</security>
</binding>
</basicHttpBinding>
<netTcpBinding>
<binding name="tcpBinding" portSharingEnabled="false">
<security mode="None">
<transport clientCredentialType="None" />
<message clientCredentialType="None" />
</security>
<reliableSession enabled="false" />
</binding>
</netTcpBinding>
</bindings>
そして、IISでホストされているサービスクラス:私はWCFの活動をトレースしているプロセスを見てきました
[ServiceBehavior(
ConcurrencyMode = ConcurrencyMode.Multiple,
InstanceContextMode = InstanceContextMode.Single,
AddressFilterMode = AddressFilterMode.Any
)]
public class NewsService : MarshalByRefObject, INewsService
{
public List<NewsItem> GetNews()
{
return new List<NewsItem>
{
new NewsItem { Descripion = "The Description", Id = 1, Title = "The Title"}
};
}
}
が完了するまでに約5 milliscondsを取る(私はアニメージュをアップロードすることができませんでした、ここではログから1つのacivityトレースです)
送信元:処理メッセージ5.転送3/12/2010 15:35:58.861
アクティビティの境界。開始2010/03/12 15:35:58.861
チャンネル経由でメッセージを受信しました。情報3/12/2010 15:35:58.861
To: 'Ria.Spike.News.INewsService.GetNews'を転送する。3/12/2010 15:35:58.864
アクティビティの境界。サスペンド3/12/2010 15:35:58.864
送信元: 'Ria.Spike.News.INewsService.GetNews'転送転送3/12/2010 15:35:58.864
アクティビティの境界。履歴書2010年3月12日15:35:58.864
チャネルを介してメッセージを送信しました。情報3/12/2010 15:35:58.866
アクティビティの境界。 35::2010年3月12日15を停止58.866
は恋愛小説家このされます。■
は、ここでは、この例で使用するリモートコードです。
var iserver = (INewsService)Activator.GetObject(typeof(INewsService), "tcp://127.0.0.1:9000/news");
var sw = new System.Diagnostics.Stopwatch();
sw.Start();
for (int i = 0; i < 1000; i++)
{
var news = iserver.GetNews();
}
sw.Stop();
Console.WriteLine("Finished in " + sw.Elapsed.TotalSeconds);
Console.ReadLine();
そしてIISでホスティングこのリモートチャネルのためのTCPエンドポイント:
public class Global : System.Web.HttpApplication
{
private TcpServerChannel _quote;
protected void Application_Start(object sender, EventArgs e)
{
_quote = new TcpServerChannel(9000);
if (ChannelServices.RegisteredChannels.Length ==0)
{
ChannelServices.RegisterChannel(_quote, false);
}
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(NewsService),
"news",
WellKnownObjectMode.SingleCall);
_quote.StartListening(null);
}
}
WCFバージョンのスタートアップペナルティがあるかどうかを確認することは重要です。呼び出しが少なくとも1回行われて結果が送信されるまで、swが起動していない実行を試すことができますか? –
こんにちはPeter、私は実際にstarupコストを解消するために1000回の呼び出しを2回呼び出しました。第1と第2の時差はごくわずかであった。 – gav
リモート設定は何ですか? –