WCF service run very slow with reliable session - c#

The server is hosted on a WPF application and use net.tcp binding for duplex channel. We have the client (.NET 4.0) to send a burst of async request to the server. After reliable session is on, the service become really slow (approx. 50-100 call/s) and callback messages aren't sent to the client.
The issue happens in two cases.
We send approx. 1000 messages per seconds to the server. If we send 300-500 messages is all OK.
We send a single message to the server with size 10-20 MB. And in this case messages from the server callbacks wait until the big message is sending.
Below are the codes for the server and client.
Server's binding:
(Also we tried to use standart net.tcp binding istead of custom one but it didn't help)
var customBinding= new CustomBinding()
{
CloseTimeout = new TimeSpan(0, 1, 10),
OpenTimeout = new TimeSpan(0, 1, 10),
ReceiveTimeout = new TimeSpan(0, 5, 30),
SendTimeout = new TimeSpan(0, 2, 0)
};
customBinding.Elements.Add(new BinaryMessageEncodingBindingElement()
{
MessageVersion = MessageVersion.Default,
ReaderQuotas =
{
MaxBytesPerRead = int.MaxValue,
MaxDepth = int.MaxValue,
MaxNameTableCharCount = int.MaxValue,
MaxStringContentLength = int.MaxValue,
MaxArrayLength = int.MaxValue
}
});
customBinding.Elements.Add(new ReliableSessionBindingElement()
{
AcknowledgementInterval = TimeSpan.FromMilliseconds(1),
FlowControlEnabled = true,
InactivityTimeout = new TimeSpan(0, 30, 0),
MaxPendingChannels = 1000,
MaxRetryCount = 10,
MaxTransferWindowSize = 4096,
Ordered = true,
ReliableMessagingVersion = ReliableMessagingVersion.Default
});
var tcpTransport = new TcpTransportBindingElement()
{
ChannelInitializationTimeout = TimeSpan.FromSeconds(30),
ConnectionBufferSize =8192,
ListenBacklog = 10000000,
MaxBufferPoolSize = int.MaxValue,
MaxBufferSize = int.MaxValue,
MaxOutputDelay= TimeSpan.FromMilliseconds(1000),
MaxPendingAccepts = int.MaxValue,
MaxPendingConnections = 40000,
MaxReceivedMessageSize = int.MaxValue,
PortSharingEnabled = true,
TransferMode = TransferMode.Buffered,
};
tcpTransport.ConnectionPoolSettings.GroupName = "OnlineList";
tcpTransport.ConnectionPoolSettings.IdleTimeout = TimeSpan.FromMinutes(5);
tcpTransport.ConnectionPoolSettings.LeaseTimeout = TimeSpan.FromMinutes(5);
tcpTransport.ConnectionPoolSettings.MaxOutboundConnectionsPerEndpoint = 40000;
customBinding.Elements.Add(tcpTransport);
Client side configuration:
BaseTimeout = 7000;
int.MaxValue = 2147483647;
///Common
CloseTimeout = new TimeSpan(0, 0, BaseTimeout),
OpenTimeout = new TimeSpan(0, 0, BaseTimeout),
ReceiveTimeout = new TimeSpan(0, 0, BaseTimeout*4),
SendTimeout = new TimeSpan(0, 0, BaseTimeout),
///Security
Security = { Mode = SecurityMode.None },
///Session
ReliableSession =
{
Enabled = true,
InactivityTimeout = new TimeSpan(1, 10, 0),
Ordered = true
},
///Buffer and message
MaxBufferPoolSize = int.MaxValue,
MaxBufferSize = int.MaxValue,
MaxReceivedMessageSize = int.MaxValue,
///ReaderQuotas
ReaderQuotas =
{
MaxBytesPerRead = int.MaxValue,
MaxDepth = int.MaxValue,
MaxNameTableCharCount = int.MaxValue,
MaxStringContentLength = int.MaxValue,
MaxArrayLength = int.MaxValue
},
//Other
PortSharingEnabled = true,
MaxConnections = 1000,
TransactionFlow = true,
TransferMode = TransferMode.Buffered,

Related

Set the MaxClockSkew when using NetTcpBinding with TransportWithMessageCredential

I'm using WCF with the NetTcpBinding and I'm unable to set the MaxClockSkew as the SymmetricSecurityBindingElement is null when using SecurityMode of TransportWithMessageCrediential. Does anyone know how this is done when using TransportWithMessageCrediential SecurityMode?
private Binding GetNetTcpBinding()
{
long MaxReceivedMessageSize = 2147483647;
int MaxStringContentLength = 2147483647;
int MaxBytesPerRead = 2147483647;
int MaxNameTableCharCount = 100000;
var timeout = 5;
var maxClockSkew = new TimeSpan(0, 30, 0);
var binding = new NetTcpBinding
{
OpenTimeout = new TimeSpan(0, 0, timeout),
SendTimeout = new TimeSpan(0, 0, timeout),
ReceiveTimeout = new TimeSpan(0, 0, timeout),
MaxReceivedMessageSize = MaxReceivedMessageSize,
ReaderQuotas = new XmlDictionaryReaderQuotas
{
MaxArrayLength = MaxBytesPerRead,
MaxBytesPerRead = MaxBytesPerRead,
MaxNameTableCharCount = MaxNameTableCharCount,
MaxStringContentLength = MaxStringContentLength,
MaxDepth = MaxBytesPerRead
}
};
binding.ReliableSession = new OptionalReliableSession
{
Enabled = true,
InactivityTimeout = new TimeSpan(0, 0, timeout),
Ordered = true
};
binding.Security = new NetTcpSecurity
{
Mode = SecurityMode.TransportWithMessageCredential,
Message = new MessageSecurityOverTcp
{
ClientCredentialType = MessageCredentialType.Certificate,
AlgorithmSuite = SecurityAlgorithmSuite.Basic256
},
Transport = new TcpTransportSecurity
{
ClientCredentialType = TcpClientCredentialType.Certificate,
SslProtocols = SslProtocols.Tls12
}
};
var customBinding = new CustomBinding(binding);
var security =
customBinding.Elements.Find<SymmetricSecurityBindingElement>();
// NOTE: This Always Returns NULL
if (security != null)
{
security.LocalClientSettings.MaxClockSkew = maxClockSkew;
security.LocalServiceSettings.MaxClockSkew = maxClockSkew;
// Get the System.ServiceModel.Security.Tokens.SecureConversationSecurityTokenParameters
var secureTokenParams =
(SecureConversationSecurityTokenParameters)security.ProtectionTokenParameters;
// From the collection, get the bootstrap element.
var bootstrap = secureTokenParams.BootstrapSecurityBindingElement;
// Set the MaxClockSkew on the bootstrap element.
bootstrap.LocalClientSettings.MaxClockSkew = maxClockSkew;
bootstrap.LocalServiceSettings.MaxClockSkew = maxClockSkew;
return customBinding;
}
return binding;
}
I'm unable to find any solutions for this and the documentation seems to be out of date. This only works if you use SecurityMode.Message.

WCF Timeouts larger than configured

I have configured my wcf with these timeouts:
public static NetTcpBinding MakeTcpBinding(bool isClient)
{
return new NetTcpBinding(SecurityMode.None, false)
{
HostNameComparisonMode = HostNameComparisonMode.StrongWildcard,
TransactionFlow = false,
PortSharingEnabled = true,
Security = {Transport = {ClientCredentialType = TcpClientCredentialType.None}},
ReceiveTimeout = isClient ? TimeSpan.FromSeconds(5) : TimeSpan.FromDays(1),
SendTimeout = isClient ? TimeSpan.FromSeconds(1) : TimeSpan.FromSeconds(5),
OpenTimeout = TimeSpan.FromSeconds(1),
CloseTimeout = TimeSpan.FromSeconds(5),
MaxReceivedMessageSize = int.MaxValue,
ListenBacklog = int.MaxValue,
MaxBufferSize = int.MaxValue,
MaxBufferPoolSize = 524288,
ReaderQuotas =
{
MaxArrayLength = int.MaxValue,
MaxStringContentLength = int.MaxValue,
MaxDepth = int.MaxValue,
MaxBytesPerRead = int.MaxValue,
MaxNameTableCharCount = int.MaxValue
}
};
}
Which should set the imeout to 1 second when a client connects to a non-existing server.
However, when actually calling open, I see a 21 second timeout.
DEBUG 2013-07-31 18:12:44,712 Communication.WcfCommunicator -
NotifyAllReceivers: Type: AskWhoIsAwake, SentDate: 7/31/2013 18:12:44
AM, DetectSessionId: 37106dee-b563-458b-9eb7-a90e81f82563 - 1
DEBUG 2013-07-31 18:13:05,746 Communication.WcfCommunicator - Could not connect to
net.tcp://notup/xxx.svc/motup_www-xxx-com. The connection attempt
lasted for a time span of 00:00:00.9879988. TCP error code 10060: A
connection attempt failed because the connected party did not properly
respond after a period of time, or established connection failed
because connected host has failed to respond 42.42.42.42:808. - 6
What is causing the extra 20 second timeout?
Solved using the async open and setting timeout.
var ar = client.InnerChannel.BeginOpen(null, null);
if (!ar.AsyncWaitHandle.WaitOne(client.Endpoint.Binding.OpenTimeout, true))
throw new CommunicationException("Service is not available");
client.InnerChannel.EndOpen(ar);

Increase MaxItemsInObjectGraph for WCF Service client

I am referencing a WCF service from a C# dll so the app.config file generated is not being read. I am manually trying to create a service client via the code below; however, I am getting errors that I need to increase the MaxItemsInObjectGraph. The service that is running is already set to int.MaxValue so I just need to increase it in the TestServiceClient now. Any ideas?? Thanks in advance!
var client = new TestServiceClient(GetBinding(), GetEndpointAddress());
private static EndpointAddress GetEndpointAddress()
{
var endpoint = new EndpointAddress("https://localhost:8000/ServiceModel/service");
return endpoint;
}
private static Binding GetBinding()
{
var basicHttpBinding = new BasicHttpBinding(BasicHttpSecurityMode.Transport)
{
MessageEncoding = WSMessageEncoding.Text,
TextEncoding = Encoding.UTF8,
BypassProxyOnLocal = false,
UseDefaultWebProxy = true,
CloseTimeout = new TimeSpan(10, 0, 0),
OpenTimeout = new TimeSpan(10, 0, 0),
SendTimeout = new TimeSpan(10, 0, 0),
ReceiveTimeout = new TimeSpan(10, 0, 0),
HostNameComparisonMode = HostNameComparisonMode.StrongWildcard,
MaxBufferPoolSize = Int32.MaxValue,
MaxReceivedMessageSize = Int32.MaxValue,
AllowCookies = false,
TransferMode = TransferMode.StreamedResponse,
ReaderQuotas =
{
MaxDepth = 32,
MaxStringContentLength = Int32.MaxValue,
MaxArrayLength = 6553600,
MaxBytesPerRead = 4096,
MaxNameTableCharCount = 16384
}
};
return basicHttpBinding;
}
Below is my solution:
private static ITestServiceClient GetClient()
{
var factory = new ChannelFactory<ITestServiceClient >(GetBinding(), GetEndpointAddress());
foreach (var dataContractBehavior in factory.Endpoint.Contract.Operations
.Select(operation => operation.Behaviors.Find<DataContractSerializerOperationBehavior>())
.Where(dataContractBehavior => dataContractBehavior != null))
{
dataContractBehavior.MaxItemsInObjectGraph = Int32.MaxValue;
}
var client = factory.CreateChannel();
return client;
}
Try in client.Endpoint.Contract.Operations
foreach (var operation in operations)
{
var dataContractBehavior = operation.Behaviors.Find<DataContractSerializerOperationBehavior>();
if (dataContractBehavior != null)
{
dataContractBehavior.MaxItemsInObjectGraph = value;
}
}

Tridion 2011 Core Service: Unable to connect in a SSO environment

While trying to connect to the Core Service I get the following error:
The HTTP request was forbidden with client authentication scheme 'Anonymous'
The Tridion environment is configured with SSO from SiteMinder.
Here's my code:
public static ICoreService2010 GetTridionClient()
{
var binding = new BasicHttpBinding()
{
Name = "BasicHttpBinding_TridionCoreService",
CloseTimeout = new TimeSpan(0, 1, 0),
OpenTimeout = new TimeSpan(0, 1, 0),
ReceiveTimeout = new TimeSpan(0, 10, 0),
SendTimeout = new TimeSpan(0, 1, 0),
AllowCookies = false,
BypassProxyOnLocal = false,
HostNameComparisonMode = HostNameComparisonMode.StrongWildcard,
MaxBufferSize = 4194304, // 4MB
MaxBufferPoolSize = 4194304,
MaxReceivedMessageSize = 4194304,
MessageEncoding = WSMessageEncoding.Text,
TextEncoding = System.Text.Encoding.UTF8,
TransferMode = TransferMode.Buffered,
UseDefaultWebProxy = true,
ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas()
{
MaxDepth = 32,
MaxStringContentLength = 4194304, // 4MB
MaxArrayLength = 4194304,
MaxBytesPerRead = 4194304,
MaxNameTableCharCount = 16384
},
Security = new BasicHttpSecurity()
{
Mode = BasicHttpSecurityMode.TransportCredentialOnly,
Transport = new HttpTransportSecurity()
{
ClientCredentialType = HttpClientCredentialType.None,
},
Message = new BasicHttpMessageSecurity()
{
ClientCredentialType = BasicHttpMessageCredentialType.UserName
}
}
};
string hostname = ConfigurationManager.AppSettings["TridionUrl"];
string username = ConfigurationManager.AppSettings["TridionUsername"];
hostname = string.Format("{0}{1}{2}",
hostname.StartsWith("http") ? "" : "http://",
hostname,
hostname.EndsWith("/") ? "" : "/");
var endpoint = new EndpointAddress(hostname +
"/webservices/CoreService.svc/basicHttp_2010");
var factory = new ChannelFactory<ICoreService2010>(binding, endpoint);
factory.Credentials.UserName.UserName = username;
return factory.CreateChannel();
}
Does anybody have experience of interacting with the Core Service with an authentication type other than Windows?
UPDATE:
I now get the error:
The HTTP request was forbidden with client authentication scheme 'Basic'.
What clientCredentialType should be used in the /webservices/web.config for the bindings?
When I uncomment the SsoAgentHttpModule in the /webservies/web.config we get a 500 error on the webservice, so SDL told us to leave this commented out.
I take it that this module is required for the CoreService to authenticate with authentication scheme 'Basic'?
There are 2 problems with your code:
You have set authentiction to anonymous on the server and assumed that same should be set on the client, but it's not the case. You have also enabled LDAP SSO module on the server that kicks in as soon as you turn the anonymous authentication on. On the client side it will look like plain basic authentication, so you client security code should be like this:
Security = new BasicHttpSecurity()
{
Mode = BasicHttpSecurityMode.TransportCredentialOnly,
Transport = new HttpTransportSecurity()
{
ClientCredentialType = HttpClientCredentialType.Basic,
}
}
You have set username, but not password, so:
factory.Credentials.UserName.UserName = username;
factory.Credentials.UserName.Password = password;
Also, keep in mind that you might need to specify User Name Qualifier (SSO by default) when setting user, like SSO\user
This should move you a step closer, if you will still have problems - please update your question with recent exception.

Consuming a web service using digest authentication

We are using C# to send XML data via SOAP. The service requires HttpDigest authentication with #PasswordDigest and #Base64Binary Nonce. Our binding code:
protected BasicHttpBinding binding = new BasicHttpBinding()
{
Name = "ShipmentServiceSoapBinding",
CloseTimeout = new TimeSpan(0, 01, 0),
OpenTimeout = new TimeSpan(0, 01, 0),
ReceiveTimeout = new TimeSpan(0, 10, 0),
SendTimeout = new TimeSpan(0, 5, 0),
AllowCookies = false,
BypassProxyOnLocal = false,
HostNameComparisonMode = HostNameComparisonMode.StrongWildcard,
MaxBufferPoolSize = 5242880,
MaxReceivedMessageSize = 655360,
MessageEncoding = WSMessageEncoding.Text ,
TextEncoding = new UTF8Encoding(),
UseDefaultWebProxy = true,
ReaderQuotas = new XmlDictionaryReaderQuotas() { MaxDepth = 32, MaxStringContentLength = 81920, MaxArrayLength = 1638400, MaxBytesPerRead = 409600, MaxNameTableCharCount = 163840 },
Security = new BasicHttpSecurity() { Mode = BasicHttpSecurityMode.TransportWithMessageCredential,
//Message = new BasicHttpMessageSecurity() { AlgorithmSuite = SecurityAlgorithmSuite.Default, ClientCredentialType = BasicHttpMessageCredentialType.UserName},
Transport = new HttpTransportSecurity(){ ClientCredentialType = HttpClientCredentialType.Digest}},
};
We are encountering 3 different problems based on what type of BasicHttpSecurityMode we are choosing.
Transport - The XML does not include any security information
TransportCredentialOnly - The error we get states that the endpoint cannot be https://
TransportWithMessagecredential - This isn't using digest
Now their ServiceReference allows us to use ClientCredentials class, so here is how we tried using HttpDigest:
typeClient.ClientCredentials.HttpDigest.ClientCredential.UserName = "username";
typeClient.ClientCredentials.HttpDigest.ClientCredential.Password = "password";
I've read on other StackOverflow question that for digest we should be using SoapHeader with AuthHeader, but there is no way for us to match it with what they give is in the API. Is there any other way of doing it? Or is their API not written correctly for C#?
It is much more complicated to use digest auth in this scenario - you will need to implement IClientMessageInspector to get it working... this enables you to modify the http headers in a way that is needed for digest auth.
Helpful links:
https://stackoverflow.com/a/3257760/847363
http://benpowell.org/supporting-the-ws-i-basic-profile-password-digest-in-a-wcf-client-proxy/
http://social.msdn.microsoft.com/Forums/en/wcf/thread/0f09954e-3cef-45b3-a00d-f0f579a06bf7
http://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.iclientmessageinspector.aspx
http://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.iclientmessageinspector.beforesendrequest.aspx
http://yuzhangqi.itpub.net/post/37475/500654
http://wcfpro.wordpress.com/category/wcf-extensions/
http://social.technet.microsoft.com/wiki/contents/articles/1322.how-to-inspect-wcf-message-headers-using-iclientmessageinspector-en-us.aspx
http://weblogs.asp.net/paolopia/archive/2007/08/23/writing-a-wcf-message-inspector.aspx
http://wcfpro.wordpress.com/2011/03/29/iclientmessageinspector/

Categories