Changing ConcurrencyMode - c#

I'm using Castle Windsor WCF Facility.
The docs say:
If you are switching from WCF activation to Windsor's WcfFacility, please make sure to remove the ServiceBehavior attribute from service type.
How can I then control the concurrency mode?
In vanilla WCF I'd do:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Multiple)]
It seems that with WCF Facility the concurrence mode is set to Single and I can't find a way to change it.
EDIT: The client calls asynchronously BeginFoo method and the call is not blocking on client side.
I put logging at the beginning and at the end of the BeginFoo method. The logs indicate that the server call enters and exits BeginFoo method only once at a time.
The following client calls get magically queued.

I figured it out.
If you don't specify the attribute, then WCF Facility creates one for you and adds it to
ServiceHost.Description.Behaviors
So the solution is to add an attribute to Behaviors collection (Yes, the attribute implements IServiceBehavior, a bit counterintuitive though...) and set the relevant properties there.
I'm adding the behaviors in WcfServiceModel's extension OnCreated. As at this point the default behavior is already there, I had to remove it first.

For anyone interested, here's the code for what dzendras posted earlier:
static void Main(string[] args) {
_container = new WindsorContainer();
_container.AddFacility<WcfFacility>();
_container.Register(Component.For<IHelloService>()
.ImplementedBy<HelloService>()
.AsWcfService(new DefaultServiceModel().OnCreated(OnCreated)));
}
private static void OnCreated(ServiceHost serviceHost)
{
var serviceBehavior = (ServiceBehaviorAttribute) serviceHost.Description.Behaviors.Single(_ => _ is ServiceBehaviorAttribute);
serviceBehavior.ConcurrencyMode = ConcurrencyMode.Multiple;
serviceBehavior.InstanceContextMode = InstanceContextMode.PerSession;
}

As I Tried Some ways ,
You can use
[OperationContract(IsOneWay=true)]
this will not make client to wait for response and this can work as or replace multiple or reentrant concurrency model

Related

WCF channel Factory caching

A WCF service will consume another Wcf service. Now, i want to create channel factory object and cache it manually. I know performance will be good but concern any other issue will be raised or not.
I have found info as follows:
"Using ChannelFactory you can still achieve channel factory caching with your own custom MRU cache. This still implies an important restriction: calls to the same service endpoint that share the channel factory must also share the same credentials. That means you can t pass different credentials for each thread calling application services from the Web server tier. One scenario where this is not an issue is if you use the same certificate or Windows credential to authenticate to downstream services. In this case, if you need to pass information about the authenticated user, you can use custom headers rather than a security token."
Link: http://devproconnections.com/net-framework/wcf-proxies-cache-or-not-cache
I have found a sample code in Google as follows.
internal delegate void UseServiceDelegate<in T>(T proxy);
internal static class Service<T>
{
private static readonly IDictionary<Type, string>
cachedEndpointNames = new Dictionary<Type, string>();
private static readonly IDictionary<string, ChannelFactory<T>>
cachedFactories =
new Dictionary<string, ChannelFactory<T>>();
internal static void Use(UseServiceDelegate<T> codeBlock)
{
var factory = GetChannelFactory();
var proxy = (IClientChannel)factory.CreateChannel();
var success = false;
try
{
using (proxy)
{
codeBlock((T)proxy);
}
success = true;
}
finally
{
if (!success)
{
proxy.Abort();
}
}
}
private static ChannelFactory<T> GetChannelFactory()
{
lock (cachedFactories)
{
var endpointName = GetEndpointName();
if (cachedFactories.ContainsKey(endpointName))
{
return cachedFactories[endpointName];
}
var factory = new ChannelFactory<T>(endpointName);
cachedFactories.Add(endpointName, factory);
return factory;
}
}
private static string GetEndpointName()
{
var type = typeof(T);
var fullName = type.FullName;
lock (cachedFactories)
{
if (cachedEndpointNames.ContainsKey(type))
{
return cachedEndpointNames[type];
}
var serviceModel =
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None)
.SectionGroups["system.serviceModel"] as ServiceModelSectionGroup;
if ((serviceModel != null) && !string.IsNullOrEmpty(fullName))
{
foreach (var endpointName in
serviceModel.Client.Endpoints.Cast<ChannelEndpointElement>()
.Where(endpoint => fullName.EndsWith(endpoint.Contract)).Select(endpoint
=> endpoint.Name))
{
cachedEndpointNames.Add(type, endpointName);
return endpointName;
}
}
}
throw new InvalidOperationException("Could not find endpoint element
for type '" + fullName + "' in the ServiceModel client
configuration section. This might be because no configuration file
was found for your application, or because no endpoint element
matching this name could be found in the client element.");
}
}
I am totally confused what should i do. Can anyone give me a best practice guideline?
This is a complex topic with a lot of details to go over, but here it goes.
First, as a general rule you should be caching a ChannelFactory and not an individual Channel. A ChannelFactory is expensive to construct as well as thread-safe so it is a great candidate for caching. A Channel is cheap to construct and it is generally recommended to only create channels on an as-needed basis and to close them as early as possible. Additionally, when you cache a Channel then you have to worry about it timing out which will cause it to fault which invalidates the entire benefit of caching it in the first place.
The article you linked to by Michele Leroux Bustamante is one of the best resources out there. As she states, there are differences to consider between Windows clients and server-side clients. Mostly only Windows clients benefit from caching as typically the credentials differ from thread to thread on server-side clients. For your typical Windows clients, there are two main options: Caching the references yourself or leveraging the MRU cache.
Leveraging the MRU cache: Essentially this means that you are letting Microsoft take the wheel. The ClientBase class will use an MRU cache for the internal ChannelFactory instance. The caching behavior is controlled via a CacheSetting property and by default caching will be disabled if any of the "security-sensitive" properties are accessed. ClientBase properties which will invalidate and remove a ChannelFactory from the MRU cache when accessed include the Endpoint, ClientCredentials or the ChannelFactory itself. There is a way to override this behavior by setting the CacheSettings property to CacheSettings.AlwaysOn. Additionally, if the Binding is run-time defined then the ChannelFactory is no longer a candidate for the MRU cache. See more details here.
Caching the references yourself: This means that you are going to keep a collection of ChannelFactory references yourself. The snippet you provide in your question uses this approach. The best approach I have ever seen and admittedly use a modified version of at work is by Darin Dimitrov via this related SO question. For those of us who like to have more fine-grained control over the caching mechanism then this is the approach to use. This is typically used when credentials must be set at run-time like is often required by internet services.
Quite similarly, client proxies can be cached to improve performance - Wenlong Dong has an article about this topic.
(Update) Server-side clients as noted before are quite limited in their options when it comes to ChannelFactory caching. For this brief discussion, we will assume that our deployment scenario looks like this:
Client -> Service A -> Service B
The most likely method to use in order to leverage ChannelFactory caching in this scenario is to cache the references yourself for the session between the Client and Service A. This way Service A does not have to construct a different ChannelFactory instance every time Service A needs to call into Service B. However, if the properties of the ChannelFactory need change for each call, then this is no longer going to be appropriate.
Of course this also holds if Service A is a Singleton and each call to the downstream service (Service B) does not require new credentials, but Singleton services have their own set of performance problems.

Does WCF Run the session on more than one thread?

I have a wcf service (hosted in IIS) that is setup to use sessions. It seems to work. When Application_PostAcquireRequestState is called I have a session ID.
I end up using it like this (in my Global.asax):
if (Context.Handler is IRequiresSessionState)
{
log4net.ThreadContext.Properties["sessionId"] = Session.SessionID;
}
That seems to work fine. The value is stored off into my log4net property.
But when my service operation begins (my actual WCF service code) the log4net property is null again.
Since the property is stored per thread (ThreadContext), I can only assume that this means that the session is setup on one thread then executed on another thread. Am I right?
Is there anyway to get my log4net property set on the on the correct thread (without having to remember to make the above call at the start of every single service operation)?
Yes, IIS may use multiple thread to service multiple WCF requests. See http://msdn.microsoft.com/en-us/library/cc512374.aspx for more detail.
You might consider using different instances of a logger for each WCF request.
There are multiple scenarios where WCF might change threads on you:
The Global.asx thread is not guaranteed to be used for a service call (in fact its unlikely).
If there are multiple calls during the same session, the thread may also change between calls to the same service instance.
In theory state information like this should be stored in an Operation Context object. However because log4net uses thread local storage it becomes an awkward solution.
Is there anyway to get my log4net property set on the on the correct
thread (without having to remember to make the above call at the start
of every single service operation)?
Yes. Create a custom IOperationInvoker. The best example I know of is Carlos Figueira's blog. If you apply this as a service behavior your log4net property should always be defined for the service code.
One warning: When adding to thread local storage be sure to clean up. That's why log4net.ThreadContext.Stacks[].Push() returns a IDisposable. In other words your Invoke method should look like (incomplete and untested):
public object Invoke(object instance, object[] inputs, out object[] outputs)
{
using (log4net.ThreadContext.Stacks[key].Push(value))
{
return this.originalInvoker.Invoke(instance, inputs, out outputs);
}
}
See Carlos' blog to understand why you are calling the "originalInvoker". Note that if you want to support async operations that you need to implement additional methods.
Custom properties do not need to be strings. So you could store an instance of the following class in the global context:
public class SessionIdProperty
{
public override string ToString()
{
// error handling omitted
return Session.SessionID;
}
}
This way log4net can access the Session object directly when it logs a message. Log4net calls the ToString() method on non-string properties.

Is it possible to track all outgoing WCF call?

Our application calls external services like
//in client factory
FooServiceClient client = new FooServiceClient(binding, endpointAddress);
//in application code
client.BarMethod(); //or other methods
Is it possible to track all of these calls (e.g by events or something like that) so that the application can collect the statistics like number of call, response time, etc? Note that my application itself needs to access the values, not only to write to a log file.
What I can think is to create a subclass of VisualStudio-generated FooServiceClient and then add codes like this
override void BarMethod()
{
RaiseStart("BarMethod");
base.BarMethod();
RaiseEnd("BarMethod);
}
and the RaiseStart and RaiseEnd method will raise events that will be listened by my code.
But this seems tedious (because there are a lot of methods to override) and there is a lot of repeated codes, my code needs to change everytime the service contract changes, etc. Is there a simpler way to achieve this, for example by using reflection to create the subclass or by tapping into a built-in method in WCF, if any?
The first thing I would look at is to see if the counters available in your server's Performance Monitor can provide you with the kind of feedback you need. There's built in counters for a variety of metrics for ServiceModel Endpoints, Operations and Services. Here is some more info http://msdn.microsoft.com/en-us/library/ms735098.aspx
You could try building an implementation of IClientMessageInspector, which has a method to be called before the request is sent and when the reply is received. You can inspect the message, make logs etc in these methods.
You provide an implementation of IEndpointBehavior which applies your message inspector, and then add the endpoint behavior to your proxy client instance.
client.Endpoint.Behaviors.Add(new MyEndpointBehavior())
Check out the docs for MessageInspectors and EndpointBehaviors, there are many different ways of applying them (attributes, code, endpoint xml config), I can't remember of the top of my head which apply to which, as there also IServiceBehavior and IContractBehavior. I do know for sure that the endpoint behaviors can be added to the client proxy collection though.
I found a simple way to do it by using dynamic proxy, for example Castle's Dynamic Proxy.
Firstly, use a factory method to generate your client object
IFooClient GetClient()
{
FooClient client = new FooClient(); //or new FooClient(binding, endpointAddress); if you want
ProxyGenerator pg = new ProxyGenerator();
return pg.CreateInterfaceProxyWithTarget<IFoo>(client, new WcfCallInterceptor());
}
And define the interceptor
internal class WcfCallInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
try
{
RaiseStart(invocation.Method.Name);
invocation.Proceed();
}
finally
{
RaiseEnd(invocation.Method.Name);
}
}
//you can define your implementation for RaiseStart and RaiseEnd
}
I can also change the intercept method as I wish, for example I can add a catch block to call a different handler in case the method throw exception, etc.

WCF, ServiceHost - CreateChannel, don't create new remote instance

I got a usual WCF service set up like this:
private ServiceHost serviceHost = null;
protected override void OnStart(string[] args)
{
if (serviceHost != null)
serviceHost.Close();
Uri[] baseAddress = new Uri[]{
new Uri("net.pipe://localhost")};
string PipeName = "DatabaseService";
serviceHost = new ServiceHost(typeof(Kernel), baseAddress); // Kernel implements IDatabase
serviceHost.AddServiceEndpoint(typeof(IDatabase), new NetNamedPipeBinding(), PipeName);
serviceHost.Open();
}
protected override void OnStop()
{
if (serviceHost != null && serviceHost.State != CommunicationState.Closed)
{
serviceHost.Close();
serviceHost = null;
}
}
From this code, i guess, one instance of "Kernel" is created, because I got this service running only once.
I create a proxy Object using the ChannelFactory like this:
pipeFactory = new ChannelFactory<IDatabase>(new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/DatabaseService"));
m_Database = pipeFactory.CreateChannel();
I have to say, that my Kernel instance access a local file, and therefore it's very important I got only once physical instance of this class. I want my service to take care of that but here come's my problem.
While the service is running and a single channel is created and active, a second client comes up and wants to create a channel too. That works properly but if I start using the proxy Object a FaultException is thrown because a second instance of my Kernel class is created.
Therefore I'm guessing that an instance of the Kernel class is created by every CreateChannel call.
Is it possible to avoid the creation of a new instance and return always a reference to a single Kernel class instance when CreateChannel is called?
Regards,
inva
Yes, by default, WCF uses the per-session or per-call calling convention, e.g. each incoming service request from a client gets a new, separate instance of your service (implementation) class.
You can control this, of course, using things like the InstanceContextMode (PerSession is the default - at least on bindings that support it -, PerCall the recommended best practice, and Single is the Singleton) and the ConcurrencyMode settings on your service.
You can define these either in config, or directly on your service class.
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class CalculatorService : ICalculatorInstance
{
...
}
See the MSDN documentation on WCF Sessions, Instancing and Concurrency for a great and extensive explanation of all details. Also read the excellent MSDN Magazine article Discover Mighty Instance Management Techniques For Developing WCF Apps by Juval Lowy, a great resource always!
If you do switch your service class to be a singleton (InstanceContextMode=InstanceContextMode.Single), you need to be aware of the two trade-offs:
either you define the ConcurrencyMode to also be Single, which effectively means only one single request can ever be handled at once; requests will be serialized, that is, if handling the request takes a fairly long time, subsequent requests will have to start waiting and might end up timing out
the other option is to set the ConcurrencyMode to Multiple, then your singleton service class can handle multiple requests at once; but this also means, you have to write your service class in a fully thread-safe manner and you need to synchronize and protect any concurrent access to shared data members - typically a very tricky and hard-to-do-right programming exercise

Dealing with concurrency and complex WCF services interacting with objects of the overall application

I am enjoying creating and hosting WCF services.
Up until now I can create services defining contracts for the service and data (interfaces) and defining hosts and configuration options to reach them (endpoint specifications).
Well, consider this piece of code defining a service and using it (no mention for endpoints that are defined in app.config not shown here):
[ServiceContract]
public interface IMyService {
[OperationContract]
string Operation1(int param1);
[OperationContract]
string Operation2(int param2);
}
public class MyService : IMyService {
public string Operation1(int param1) { ... }
public string Operation2(int param2) { ... }
}
public class Program {
public static void Main(stirng[] args) {
using (ServiceHost host = new ServiceHost(typeof(MyService))) {
host.Open();
...
host.Close();
}
}
}
Well, this structure is good when creating something that could be called a Standalone service.
What if I needed my service to use objects of a greater application.
For example I need a service that does something basing on a certain collection defined somewhere in my program (which is hosting the service). The service must look into this collection and search and return a particular element.
The list I am talking about is a list managed by the program and edited and modified by it.
I have the following questions:
1) How can I build a service able to handle this list?
I know that a possible option is using the overloaded ServiceHost constructor accepting an Object instead of a Type service.
So I could pass my list there. Is it good?
[ServiceContract]
public interface IMyService {
[OperationContract]
string Operation1(int param1);
[OperationContract]
string Operation2(int param2);
}
public class MyService : IMyService {
private List<> myinternallist;
public MyService(List<> mylist) {
// Constructing the service passing the list
}
public string Operation1(int param1) { ... }
public string Operation2(int param2) { ... }
}
public class Program {
public static void Main(stirng[] args) {
List<> thelist;
...
MyService S = new MyService(thelist)
using (ServiceHost host = new ServiceHost(S)) {
host.Open();
...
host.Close();
// Here my application creates a functions and other that manages the queue. For this reason my application will edit the list (it can be a thread or callbacks from the user interface)
}
}
}
This example should clarify.
Is it the good way of doing? Am I doing right?
2) How to handle conflicts on this shared resource between my service and my application?
When my application runs, hosting the service, my application can insert items in the list and delete them, the same can do the service too. Do I need a mutex? how to handle this?
Please note that the concurrency issue concerns two actors: the main application and the service. It is true that the service is singleton but the application acts on the list!!!
I assume that the service is called by an external entity, when this happens the application still runs right? Is there concurrency in this case???
Thankyou
Regarding point 2, you can use Concurrent Collections to manage most of the thread safety required.
I'm not sure what you mean by point 1. It sounds like you're describing basic polymorphism, but perhaps you could clarify with an example please?
EDIT: In response to comments you've made to Sixto's answer, consider using WCF's sessions. From what you've described it sounds to me like the WCF service should be sat on a seperate host application. The application you are using currently should have a service reference to the service, and using sessions would be able to call an operation mimicking your requirement for instantiating the service with a list defined by the current client application.
Combine this with my comment on exposing operations that allow interaction with this list, and you'll be able to run multiple client machines, working on session stored Lists?
Hope that's explained well enough.
Adding the constructor to MyService for passing the list certainly will work as you'd expect. Like I said in my comment to the question however, the ServiceHost will only ever contain a single instance of the MyService class so the list will not be shared because only one service instance will consume it.
I would look at a dependency injector (DI) container for WCF to do what you are trying do. Let the DI container provide the singleton list instance to your services. Also #Smudge202 is absolutely correct that using the Concurrent Collection functionality is what you need to implement the list.
UPDATE based on the comments thread:
The DI approach would works by getting all of an object's dependencies from the DI container instead of creating them manually in code. You register all the types that will be provided by the container as part of the application start up. When the application (or WCF) needs a new object instance it requests it from the container instead of "newing" it up. The Castle Windsor WCF integration library for example implements all the wiring needed to provide WCF a service instance from the container. This posts explains the details of how to use the Microsoft Unity DI container with WCF if you want to roll your own WCF integration.
The shared list referenced in this question would be registered in the container as an already instantiated object from your application. When a WCF service instance is spun up from the DI container, all the constructor parameters will be provided including a reference to the shared list. There is a lot of information out there on dependency injection and inversion of control but this Martin Fowler article is a good place to start.

Categories

Resources