Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is using X509 for WCF security inherently slow with a new channel per-request?

Is there anything I can do to make X509 perform better and follow the new-channel-each-request best practice, or is this slow negotiation an inherent drawback of using X509 for WCF security?

For tl;dr skip to Update 3 at the end for the source of this.

Best practice with WCF channels seems to be "reuse the ChannelFactory, but create a new channel for each request", and I've always done it this way. E.g. Single WCF channel performance vs multiple channels

I am currently experimenting with using X509 certificates as the security credentials and CreateChannel takes ages each time (15 secs+). Reusing the channel subsequently yields good performance (if I understand correctly because symmetric keys are used following the initial public/private key authentication that occurs when calling CreateChannel), but this is bad practice.

On the server side:

var managerCertificate = new X509Certificate2(@"Manager.pfx", "");
var host = new ServiceHost(typeof(ManagerService));
host.Credentials.ClientCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
host.Credentials.ClientCertificate.Authentication.RevocationMode = X509RevocationMode.NoCheck;
host.Credentials.ServiceCertificate.Certificate = managerCertificate;
host.Open();
Console.ReadLine();

On the worker side (slow each request):

var workerCertificate = new X509Certificate2(@"Worker.pfx", "");
var cfact = new ChannelFactory<IManagerService>("client");
cfact.Credentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
cfact.Credentials.ServiceCertificate.Authentication.RevocationMode = X509RevocationMode.NoCheck;
cfact.Credentials.ClientCertificate.Certificate = workerCertificate;
for (int i = 0; i < 10; i++)
{
    using (IManagerService channel = cfact.CreateChannel()
    {
         Console.WriteLine(channel.GetMyData("test data" + i));
    }
}

And if I move the CreateChannel call outside of the for loop to reuse it only the first request takes any substantial time.

Also, I'm using NetTcpBinding.

Update 1: A short sample of the results:

0: 546.875ms
1: 281.25ms
2: 281.25ms
3: 17484.375ms
4: 250ms
5: 234.375ms
6: 250ms
7: 250ms
8: 265.625ms
9: 250ms

250ms is not too horrendous an overhead per call (though enormous compared to reusing the channel), but is seems to go in fits and spurts (see the 17secs) that varies in frequency, sometimes 1-in-3. If the server stays up between runs of the client exe then the initial negotiation cost disappears on subsequent runs, so that's good.

Update 2: Presumably not firewall/antivirus related as I tried this inside a VM with stock XP and firewall disabled and got wildly inconsistent results. One time predictable (400ms per call), another these crazy pauses.

Update 3: After wading through the trace logs, it seems the time consuming server activity when creating a new channel each time (and the activity that is the cause of the occasional pause) is this:

<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">
  <System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system">
    <EventID>0</EventID>
    <Type>3</Type>
    <SubType Name="Transfer">0</SubType>
    <Level>255</Level>
    <TimeCreated SystemTime="2012-03-10T15:02:27.2968750Z" />
    <Source Name="System.ServiceModel" />
    <Correlation ActivityID="{9e5e819b-e837-40b8-81b1-9f3c18e54595}" RelatedActivityID="{2faaac57-4e24-41ad-a3e5-85d81bddfa3b}" />
    <Execution ProcessName="WcfCertExample" ProcessID="420" ThreadID="4" />
    <Channel />
    <Computer>MYCOMPUTER</Computer>
  </System>
  <ApplicationData></ApplicationData>
</E2ETraceEvent>

The log also says: Related Activity Name: Process action 'http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue'.

So if anyone has any ideas on why this might pause consistently for 17.5 secs and whether it's always going to cost 250ms normally then you'll be answering my question!

like image 479
Xiaofu Avatar asked Mar 09 '12 15:03

Xiaofu


1 Answers

Based on the comments you are using self signed certificates.

There is a known performance issue with WCF and self signed certificates, see: Terrible Performance with WCF and certificates (mutual authentication)

This is not a problem when you use certificates from a certificate authority.

like image 169
Shiraz Bhaiji Avatar answered Oct 22 '22 15:10

Shiraz Bhaiji