Can an WCF Service create his own host? - c#

I have a client / server type of application and I'd like the server object to create his own host. It looks something like this:
public class Server : IServer {
private ServiceHost m_Host;
public Server() {
m_Host = new ServiceHost(this);
m_Host.Open();
}
}
It seems to work fine when there are few message transfers occurring. But when it starts to speed up (my application requires that data is transfered every 50 ms), the server hangs and and the transfers stop after a few seconds without throwing an exception.
So, is it possible for an object to create his own host? Or do I really have to create it in the main() or do something else?
EDIT: I think the problem in this case is that I want the object that implements the service itself to create his own ServiceHost.

There's nothing really stopping any object to create an instance of ServiceHost.
The big question then is - can you guarantee that your object containing the service host is "alive"? Or was it garbage collected by any chance?
We use Windows (NT) Services to host our own custom service host classes to provide around-the-clock availability for WCF services - works just fine.
Marc

To be a WCF service it simply needs to implement the service contract. There's nothing to stop you adding more methods to open and close an instance of itself as a service.

Check out the ServiceBehaviorAttribute which allows you to specify how your service ... behaves. ;) The ConcurrencyMode property defined the support for multithreading and defaults to single threaded mode, and the InstanceContextMode defines if the service object is per session, per call or singleton.
Quote from ConcurrencyMode:
Setting ConcurrencyMode to Single instructs the system to restrict instances of the service to one thread of execution at a time, which frees you from dealing with threading issues. A value of Multiple means that service objects can be executed by multiple threads at any one time. In this case, you must ensure thread safety.
Quote from InstanceContextMode:
If the InstanceContextMode value is set to Single the result is that your service can only process one message at a time unless you also set the ConcurrencyMode value to Multiple.
We could really use some code examples of your service to further debug the behavior you're describing. For example, is your service object expensive to construct (assuming non singleton implementation), or do the operation slow down? Do you know where the time is spent, is it code, or could it as well be some firewall that limits connection? What protocol do you use?

Related

PerCall InstanceContextMode behaviour of WCF service

I have a WCF service, exposing a ServiceContract with basicHttpBinding, so from my understanding InstanceContextMode will be set to PerCall (as basicHttpBinding doesn't support sessions) and ConcurrenyMode will be set to Single.
The client of this WCF is a windows service, which invokes 4 different operations on the service at the same time, within the service we have used a singleton class and there are few Static variables. We have been facing a problem where in a wrong value is getting passed to some of the DB Stored Procedures.
With PerCall InstanceContextMode and Single concurrency mode, i understand a new service instacne in created for every call and hence i am thinking that even though there are some singleton classes (we have not made it thread safe) in the service implementation and static variables all the objects will be destroyed, but we have observed running a SQL profiler that on old value is getting passed the DB.
We have written our WCF service code in a kind of 3-tier architecture, i mean ServiceClass, BusinessLogicLayer and DataAccessLayer, with PerCall set as instanceContextMode when we say the service instance is destroyed after the client request is finished, does it mean we destroy all the object in ServiceClass,BusinessLogicLayer and DataAccessLayer?
Pls help me understand what could be going wrong
The InstanceContextMode PerCall means a new class of your service is instantiated per call. Static variables in your AppDomain will not be reset. They will stay between service calls, as long as your AppPool is not recycled.
Remove all statics including singletons from your code. They never belonged to your architecture anyway.
Many WCF requests share the same AppDomain. Static variables are per AppDomain. WCF does nothing to those variables (in fact it cannot even find out they exist). You are responsible for maintaining them.
WCF does not destroy any of your objects because neither does WCF understand what they mean nor does it know they exist.
The settings you mentioned are only relevant to the service object.
My usual advice regarding stateful server apps: You are working under bad practices here. You need to ensure thread-safety. In case the worker process shuts down (deployment, automatic restart, server reboot, app bug crashing the process, power loss, hardware failure, ...) your data is lost.
Though it is restricted in any way static variables needs to be protected for thread safe as a best practice. Static variables will not be destroyed till the service is stopped / app pool recycle.
Using static variables for the data which changes are not recommended for distributed web farms, because those are not safer over a failover.
Visual Studio 2012 and above comes with a Memory profiler. But the simple thing can be done using a counter in the object constructors (only on testing) which can tell if there is a new instance created on every request or not.
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall,ConcurrencyMode=ConcurrencyMode.Single)]
public class TestServiceWithStaticVars : ITestServiceWithStaticVars
{
static int instanceCount = 0;
public TestServiceWithStaticVars()
{
Interlocked.Decrement(ref instanceCount);
}
public string GetInstanceCount()
{
return string.Format("You have created {0} instance", instanceCount);
}
Let you know if better instance counter available to use with ease.
[Edit] as I can't comment now.
Re-assigning the static variable will take the new value as you said. The static variables are loaded in to HighFrequencyHeap for frequent access. For more information http://www.codeproject.com/Articles/15269/Static-Keyword-Demystified

How to check if a WCF service is available?

Can I use Proxy.Open() as an indication to whether the connection should work or not?
I would like to check if a connection is available first, and then, if its not, i won't make any calls to the service during the run of the application.
Note: I only need to check connectivity, not necessarily and entire client-service round-trip.
I Ended up creating a Ping() methods in the service as suggested.
FYI, using simply Open() just didn't work - Open() doesn't raise any exceptions even if the service is offline!
Given the fact that there are so many variables which influence success of a WCF Service call, I tend to add a dummy void KnockKnock()) method to the services to have a real proof if the connection works.
This method can also serve a double purpose: You can call it async to notify the server that he has to be prepared for incoming requests. (Just the initial start-up of the service may take some time.) By invoking the KnockKnock() method the server can start loading the service and give your clients a better initial response performance.

Instantiate WCF service object on server, not client?

I am writing two applications in C# that need to be able to communicate (in one direction only). The two apps will always run on the same machine, so using WCF with named pipes, and self-hosting the WCF service, seemed like the logical choice.
I understand that I can use InstanceContextMode to configure if a service instance is instantiated per session, per call, or if there should just be a single instance. In my case I want a single instance, because I will have just the two apps running, so there will be a single client and a single server.
But here's where I'm stuck. When my client makes a call on the service, which I'm doing this way:
var myServiceFactory = new ChannelFactory<IMyService>(
new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/MyService"));
IMyService myService = myServiceFactory.CreateChannel();
myService.DoStuff();
I don't want a new server object instance to be created on the server. Instead I'd like myService to point at the (one and only) IMyService instance that has already been constructed on the server. At the moment, a second IMyService instance gets constructed.
In other words, I want my server object to be constructed by the server (when the server starts up), not when a client first makes a call.
Can anyone explain how to do this? From what I understand, .NET Remoting makes this quite easy, and WCF has supposedly replaced Remoting, so there must be an easy way... right?
WCF's ServiceHost has a constructor which takes a singleton instance of the service class rather than the service type, for exactly this purpose. You must set InstanceContextMode to Singleton if using this constructor in your service host.
Note that in the client side code you quote, IMyService myService is not what you call "the server object" ... it is the client-side proxy through which WCF routes messages from the client to the actual service.

How to persist a webservice reference instance in an SQLCLR stored procedure?

At the moment I have a windows service written in C# that waits for a message in SQL Server Service Broker, and upon receipt calls a webservice method with details passed in the message.
I want to replace this with an SQLCLR stored procedure that calls the webservice directly, which I've found to be quite simple. I can then call this using internal activation.
However it needs to create a new instance of the webservice for each method, and from experience I've found this takes some time. In the windows service I create it with lazy instantiation in a static class, but I understand static fields can't be used to store information in SQLCLR.
Is there a way to persist this webservice reference?
Edit: Here is the lazy instantation code referencing the singleton I'd like to persist:
static class WsSingleton
{
static MWs.MWS mWS = null;
public static MWs.MWS GetMWS()
{
if (mWS == null)
{
mWS = new MWs.MWS();
mWS.Credentials = new System.Net.NetworkCredential("user", "password", "domain");
}
return mWS;
}
}
it needs to create a new instance of the webservice for each method
Do you mean the client has to instantiate a proxy for each HTTP call it makes? If that's what you mean you shouldn't have to persist any reference. An internal activated procedure is launched when there are messages to process and it can stay active and running. Such a locl state could be the proxy instance used to place the WWW calls. Typically the procedure runs a loop and keeps state on the stack as local variables of loop method. See Writing Service Broker Procedures for more details. To be more precise, your code should not RECEIVE one message at a time, but a set of messages.
But I would advise against doing what you're doing. First and foremost, making HTTP calls from SQLCLR is a bad idea. Doing any sort of blocking in SQLCLR is bad, and doing blocking on waiting for bits to respond from the intertubez is particularly bad. The internal SQL Server resources, specially workers, are far too valuable and few to waste them waiting for some WWW service to respond. I would advise keeping things like they are now, namely have hte HTTP call occur from an external process.
A second comment I have is that you may be better of using a table as a queue. See Using tables as Queues. One typical problem with queueing HTTP calls is that the WWW is very unreliable and you have to account for timeouts and retries. Using a table as a quueu can achieve this easier than a true Service Broker Queue. With SSB you'd have to rely on conversation timers for reliable retries, and it makes your activation logic significantly more complicated.

WCF service instance will not close despite only calling oneway method

I have a WCF service running inside a windows service on a remote machine.
In the WCF service's contract, I have a method that takes a long time to run set up as
[OperationContract(IsOneWay = true)]
void Update(myClass[] stuff);
Everything works fine, the method gets called, I can see what it needs to do start getting done.
The problem is when I go to close the instance of the WCF service in my code, it times out and I get:
The socket connection was aborted.
This could be caused by an error
processing your message or a receive
timeout being exceeded by the remote
host, or an underlying network
resource issue. Local socket timeout
was '00:02:00'.
I thought the one way contract allowed me to fire and move on. Is there something I am missing? If not are there workarounds for this?
The ServiceContract attribute on your service's interface definition defaults the SessionMode property to SessionMode.Allowed, i.e.,
[ServiceContract(SessionMode = SessionMode.Allowed)]
public interface IMyContract
{
[OperationContract(IsOneWay = true)]
void Update(myClass[] stuff);
}
According to Juval Lowy's Programming WCF Services,
...when the SessionMode property is
configured with SessionMode.Allowed,
it merely allows transport sessions,
but does not enforce it. The exact
resulting behavior is a product of the
service configuration and the binding
used.
Thus, if you are using the WSHttpBinding with security or reliable messaging, the NetTcpBinding, or the NetNamedPipeBinding, then the service will behave as a per-session service. This simply means that as long as the client proxy has not been closed, a session will still be in place between the service and the client. By closing the client proxy as suggested by Shiraz should fix this.
Juval's book also says this with regard to one-way operations:
If the number queued messages has
exceeded the queue's capacity, then
the client will block, even when
issuing a one-way call. However, one
the call is queued, the client is
unblocked and can continue executing,
while the service processes the
operation in the background.
So while one-way operations do allow for fire-and-forget operation, you can still run into cases where your client may block.
Your "Update" is a method on the service.
When you open the wcf client, a connection to the service remains open until you call Close (or Abort).
You are probably not calling close, and it is therefore remaining open until it timesout.

Categories

Resources