I will be deploying my first application based on WCF and would like to know the best way to deploy. Here is my architecture. Please see the attached image.
We have a WCF written using 4.0 framework and has 3 methods. A front end ASP.NET website (www.site.com) calls the WCF to save data as well as read data. In figure method1 is saving to data and method2 and 3 are for reading the data from SQL server 2008 R2 database.
In my ASP.Net webstie...
I am calling the Method1 and closing the connection...like this..
ServiceClient client = new ServiceClient();
client.Method1(data to be saved)
client.close();
I am calling method 2 and 3 as follows
ServiceClient client = new ServiceClient();
dropDown1list.datasource = client.Method2()
dropDown2list.datasource = client.Method3()
client.close();
Multiple users could be using the website at the same time to submit the data. Considering this architecture..what would be the best way to deploy the WCF so that it could handle multiple users at same time?. I read the article http://www.codeproject.com/Articles/89858/WCF-Concurrency-Single-Multiple-and-Reentrant-and and http://www.codeproject.com/Articles/86007/ways-to-do-WCF-instance-management-Per-call-Per.
I now believe I need to have my WCF service as
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple , InstanceContextMode = InstanceContextMode.PerCall )]
public class Service : IService
{
public bool Method1(data to be saved)
{
}
public List<string> Method2()
{
}
public List<string> Method2()
{
}
}
Am I right ?. Any suggestions ?.
Just answered a similar question yesterday. Based on your description and the picture, I don't see a need to change your architecture. If you're using one of the main WCF bindings (webHttpBinding, wsHttpBinding or BasicHTTPBinding), the service you deploy should easily be able handle dozens of concurrent users, all saving and reading at the same time.
Each client request will generate its own connection and web service objects, each of which can communicate concurrently with your database, whether that request is to read data or write data. When the response is sent back to the client, your WCF service will destroy the objects and clean up the memory for you as long as you're not doing something strange.
I've spent the last two years working on WCF web services on and industrial scale. Lately I've been working on a load testing / benchmarking project that spins up hundreds of concurrent users, each of which is slamming our WCF test server with XML artifacts that get loaded into the database. We've managed to load up to 160 packages (about 110kb - each per client) per second. WCF is not perfect, but it's quick, clean and scales really well.
My experience has been that your database will be your bottleneck, not your WCF web service. If your client wants to scale this archtecture up to an Amazon size web service, then you bring in an F5 load balancer and scale it up that way.
Related
I am building a c#/wpf project.
It's architecture is this:
A console application which will be on a virtual machine (or my home computer) that will be the server side.
A wpf application that will be the client app.
Now my problem is this - I want the server to be able to send changes to the clients. If for example I have a change for client ABC, I want the server to know how to call a service on the clients computer.
The problem is, that I don't know how the server will call the clients.
A small example in case I didn't explain it well:
The server is on computer 1, and there are two clients, on computers 2 and 3.
Client 2 has a Toyota car and client 3 has a BMW car.
The server on computer 1 wants to tell client 2 that it has a new car, an Avenger.
How do I keep track and call services on the clients?
I thought of saving their ip address (from calling ipconfig from the cmd) in the DB - but isn't that based on the WI-FI/network they are connected to?
Thanks for any help!
You could try implementing SignalR. It is a great library that uses web sockets to push data to clients.
Edit:
SignalR can help you solve your problem by allowing you to set up Hubs on your console app (server) that WPF application (clients) can connect to. When the clients start up you will register them with a specified Hub. When something changes on the server, you can push from the server Hub to the client. The client will receive the information from the server and allow you to handle it as you see fit.
Rough mockup of some code:
namepsace Server{}
public class YourHub : Hub {
public void SomeHubMethod(string userName) {
//clientMethodToCall is a method in the WPF application that
//will be called. Client needs to be registered to hub first.
Clients.User(userName).clientMethodToCall("This is a test.");
//One issue you may face is mapping client connections.
//There are a couple different ways/methodologies to do this.
//Just figure what will work best for you.
}
}
}
namespace Client{
public class HubService{
public IHubProxy CreateHubProxy(){
var hubConnection = new HubConnection("http://serverAddress:serverPort/");
IHubProxy yourHubProxy = hubConnection.CreateHubProxy("YourHub");
return yourHubProxy;
}
}
}
Then in your WPF window:
var hubService = new HubService();
var yourHubProxy = hubService.CreateHubProxy();
yourHubProxy.Start().Wait();
yourHubProxy.On("clientMethodToCall", () => DoSometingWithServerData());
You need to create some kind of subscription model for the clients to the server to handle a Publish-Subscribe channel (see http://www.enterpriseintegrationpatterns.com/patterns/messaging/PublishSubscribeChannel.html). The basic architecture is this:
Client sends a request to the messaging channel to register itself as a subscriber to a certain kind of message/event/etc.
Server sends messages to the channel to be delivered to subscribers to that message.
There are many ways to handle this. You could use some of the Azure services (like Event hub, or Topic) if you don't want to reinvent the wheel here. You could also have your server application track all of these things (updates to IP addresses, updates to subscription interest, making sure that messages don't get sent more than once; taking care of message durability [making sure messages get delivered even if the client is offline when the message gets created]).
In general, whatever solution you choose is plagued with a common problem - clients hide behind firewalls and have dynamic IP addresses. This makes it difficult (I've heard of technologies claiming to overcome this but haven't seen any in action) for a server to push to a client.
In reality, the client talks and the server listens and response. However, you can use this approach to simulate a push by;
1. polling (the client periodically asks for information)
2. long polling (the client asks for information and the server holds onto the request until information arrives or a timeout occurs)
3. sockets (the client requests server connection that is used for bi-directional communication for a period of time).
Knowing those terms, your next choice is to write your own or use a third-party service (azure, amazon, other) to deliver messages for you. I personally like long polling because it is easy to implement. In my application, I have the following setup.
A web API server on Azure with and endpoint that listens for message requests
A simple loop inside the server code that checks the database for new messages every 100ms.
A client that calls the API, handling the response.
As mentioned, there are many ways to do this. In your particular case, one way would be as follows.
Client A calls server API to listen for message
Server holds onto call, waiting for new message entry in database
Client B calls server API to post new message
Server saves message to database
Server instance from step 2 sees new message
Server returns message to Client A.
Also, the message doesn't have to be stored in a database - it just depends on your needs.
Sounds like you want to track users à la https://www.simple-talk.com/dotnet/asp.net/tracking-online-users-with-signalr/ , but in a desktop app in the sense of http://www.codeproject.com/Articles/804770/Implementing-SignalR-in-Desktop-Applications or damienbod.wordpress.com/2013/11/20/signalr-a-complete-wpf-client-using-mvvm/ .
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
I need to write a service in C# that will always run on a PC even if no one is logged in. I need to write a c# winform application that will auto-run when a user logs in and allows the user to interact with the service.My proposed solution is to build a WCF server into the service and write a WCF client into the winform application. This will then allow interaction between the Winform application and the service. Is this the best/easiest method?
Yes - WCF is probably the simplest solution to communication between the WinForms client and the Service back-end.
Your main alternatives would be:
1. TCP sockets (lower-level and would likely require a lot more boilerplate code).
2. Messaging middleware like MSMQ/ActiveMQ NMS (involves adding more third-party libraries)
If you go with WCF, there are a few gotchas/recommendations from my experience:
Instead of handling WCF requests synchronously in the server, handle them asynchronously (if you code is thread-safe), or handle them via a single background processing queue (if your code is not thread-safe). This helps avoid issues with timeouts (which can cause WCF to fault), as well as issues where the WCF requests get triggered at the same time from multiple threads.
Don't forget that you will likely need a WCF interface in the client as well as the server. This is needed if you want the server to be able to send any kind of async communication back to the client.
You can set up a pub/sub mechanism with WCF but it's a bit tricky. Here is a code example:
Interface
//Server interface
[ServiceContract(CallbackContract = typeof(IGUIService))]
public interface IServerService
{
[OperationContract(IsOneWay = true)]
void Subscribe();
[OperationContract(IsOneWay = true)]
void Unsubscribe();
...
}
//Client interface
[ServiceContract]
public interface IGUIService
{
[OperationContract(IsOneWay = true)]
void MessageCallback(string Message);
}
The client will need to call Subscribe() when it starts, and Unsubscribe() when it shuts down. The corresponding server code to handle this is:
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class ServerService : IServerService
{
internal event SettingsUpdatedHandler SettingsUpdated;
internal delegate void SettingsUpdatedHandler(ServerService adminPort, EventArgs e);
private static List<IGUIService> Clients = new List<IGUIService>();
public void Subscribe()
{
IGUIService callback = OperationContext.Current.GetCallbackChannel<IGUIService>();
if(!Clients.Contains(callback))
Clients.Add(callback);
}
public void Unsubscribe()
{
IGUIService callback = OperationContext.Current.GetCallbackChannel<IGUIService>();
if (Clients.Contains(callback))
Clients.Remove(callback);
}
}
Then to send a message from the server to all connected clients:
internal void SendMessage(string message)
{
for(int i=Clients.Count - 1; i >= 0; i--)
{
IGUIService callback = Clients[i];
if (((ICommunicationObject)callback).State == CommunicationState.Opened)
callback.MessageCallback(message);
else
Clients.RemoveAt(i);
}
}
If you want you can use also web api.But note if use web api you can use transaction.
But both web api and wcf is good.
WCF server: hosted in a Windows Service in server.
WCF Client: Winform application. And put the shortcut of the program in the folder "C:\Documents and Settings[username]\Start Menu\Programs\Startup" (Windows XP). program will be run automatically when user is login.
Do you need to maintain state in the service? If not then can you not just host in IIS or self host a wcf, web api or even service stack service. Also is the service going to be utilised by more than one client? Does the persistence store access need to live in another process, if not then "in process" would be just fine too, without the overhead of all the service related stuff.
What you have, are two processes that need to communicate with each other. One of the processes happens to be a Windows services, while the other is a Windows application. This is a classic problem of interprocess communication. There is a number of available solutions, probably the most popular being:
WCF, already mentioned by you. Your Windows service implements a host for WCF services and the app communicates with the exposed service. Here's a good example how to implement this.
Named Pipes, old and preferred by many. Look here and here for some examples.
Other, more exotic examples:
Custom TCP ports
Win32 RPC. You can use .NET wrapper like this library.
MSMQ
File system. One process writes to a defined location, where the other listens to. You can write simple messages understood by both sides, or even whole objects using serializtion.
Database. Variation of the point 4, using a third process providing database functionality.
Given that WCF is quite mature technology with a sufficient performance, built with .NET and reasonably easy to implement, this seems like a natural choice.
I have a self hosted WCF service, using basic http binding. I am finding that calls made to the wcf service, accessing functions exposed by the WCF, take much much longer to complete (internally) than when using the functions directly (from the wcf service).
So to clarify, I am not talking about taking longer "over" the wcf call. Once the internal exposed functions behind the WCF are run, they, in their own processing, take much longer to do their work and return something back to the wcf service, for sending to the client, than when I access those same functions directly from a form in my hosted wcf app.
I have added extensive logging, logging start and stop time for all functions, and it seems to be consistent. The same functions, when activated through WCF, seems as if they are run at a much lower "priority" than when calling them bypassing the WCF interface.
Taking this into account, I am pretty sure this started sticking its head out after I decorated my main wcf class with the following, due to my UI thread locking up:
<ServiceBehavior(useSynchronizationContext:=False)>
Are the threads created due to the above decoration, running at a lower priority?
Direct Call from form in WCF hosted App: 5 seconds
Call Through WCF Interface: 20-30 seconds (Excluding time over the wire)
The physical return from the WCF service itself, once the internal functions are complete, is quite quick.
I do quite a lot of "work" once the internal functions are reached.
Any ideas?
Thanks
Basic WCF Service Code:
Dim myservicehost As ServiceHost
Dim myServiceAddress As New Uri("http://" & LocalIpAddress & ":" & tcp_port & "/" & servicename)
myservicehost = New ServiceHost(GetType(myWCFFunctions), myServiceAddress)
' Enable metadata publishing.
Dim smb As New ServiceMetadataBehavior()
smb.HttpGetEnabled = True
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15
myservicehost.Description.Behaviors.Add(smb)
myservicehost.Open()
I could not get this solved, and reverted back to my previous implementation.
This question already has answers here:
check the availability of the WCF Web Service
(4 answers)
Closed 8 years ago.
I will have a client application using a proxy to a WCF Service. This client will be a windows form application doing basicHttpBinding to N number of endpoints at an address.
The problem I want to resolve is that when any windows form application going across the internet to get my web server that must have my web server online will need to know that this particular WCF Service is online. I need an example of how this client on a background thread will be able to do a polling of just "WCF Service.., Are You There?" This way our client application can notify clients before they invest a lot of time in building up work client-side to only be frustrated with the WCF Service being offline.
Again I am looking for a simple way to check for WCF Service "Are You There?"
What this obsession with checking whether those services are there??
Just call the service and as any defensive programming course will teach you, be prepared to handle exceptions.
There's really no benefit in constantly sending "are you there?" requests all over the wire...
Even if you could have something like a Ping() method (that just returns a fixed value or something - your service name or whatever) - that only checks whether your service is reachable - what about the database you need to query to get data from? What about other services your service method depends on? It gets quite messy and very very tricky to figure out a way to check all that - just to see if it's there.
In brief: no, there is no reliable and meaningful way to check whether a given service is "there" and "alive" - just call it ! And be prepared to handle a failure - it will fail at times....
There is no value in checking if a service is alive or not. Absolutely none. Why?
if(serviceIsAlive())
{
callService();
}
else
{
handleFailure()
}
Do you see the problem with this snippet? What happens if between the time you check if the service is alive, and the time you call it, the service goes down? This is a race condition, and a bug waiting to happen. So what you need to do, even if you can check the service condition, is:
if(serviceIsAlive())
{
try
{
callService();
}
catch(CommunicationException)
{
handleFailure();
}
}
else
{
handleFailure();
}
But in this block, the handleFailure() call is in two different places - we've got two different paths to handle the same error condition - which seems like a bad thing. So this can be safely reduced to:
try
{
callService();
}
catch(CommunicationException)
{
handleFailure();
}
If your service is hosted in IIS (or WAS), you can perform a resiliency built-in to the IIS6/7 process model. If an worker process fails, another will be started in its place. How it works? Using Ping to analyse. Its called AppoPool Health Monitoring (described here).
I am just getting started with WCF and would like to set up a distributable networked system as follows: (but am not sure if it is possible.)
I have a .net client that has business logic. It will need various data from various sources so I would like to add a 'server' that contains an in-memory cache but also WCF capabilities to send/receive and publish/subscribe from data sources for data that is not cached. I think it should be possible for these server applications to be identical in terms of code, but highly configurable so that requests could be dealt with in a peer to peer fashion, or traditional client-server as required. I think it could be done so that essentially a server sends a request to wherever it has the endpoint configured and gets a response.
Essentially a server would be configured as below:
Server A
========
Operation 1 - Endpoint I
Operation 2 - Endpoint II
Server B
========
Operation 1 - Endpoint IV
Operation 2 - Endpoint III
The configuration would be stored for each server in app.config and loaded into memory at startup. So each WCF operation would have its own WCF config (in terms of endpoints etc.) and it would send particular requests to different places according to that configuration.
From what I have read of WCF I think this is possible. I don't know have enough experience to know if this is a standard WCF pattern that I am describing (if so please let me know). Otherwise, my main question is, how do I programatically configure each operation (as above) in WCF?
Please let me know if I have not explained myself clearly.
Thanks in advance for any help,
Will
I don't know if this exactly will get you what you are looking for, but I this is what I use to add my WCF endpoints to my Windows Service. This is the code that the service runs to load all the wcf services:
IDictionary<string, ServiceHost> hosts;
NetTcpBinding binding;
CustomBinding mexBinding;
private void AddService(Type serviceImp, Type serviceDef, string serviceName)
{
ServiceHost host = new ServiceHost(serviceImp);
string address = String.Format(baseAddress, wcfPort, serviceName);
string endAdd = address;
string mexAdd = address + "/mex";
ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
host.Description.Behaviors.Add(behavior);
host.AddServiceEndpoint(serviceDef, binding, endAdd);
host.AddServiceEndpoint(typeof(IMetadataExchange), mexBinding, mexAdd);
host.Open();
hosts.Add(serviceDef.Name, host);
}
There's a baseAddress string that I didn't copy in, but it just has the net.tcp address for the endpoint. Likewise for the wcfPort. Different baseAddresses and ports are used for debug, testing and production.
Just in case it isn't clear, serviceImp is the service implementation and serviceDef is the interface that defines the contract. Hope this helps.
EDIT - Here are some references I used to help me figure all of this stuff out:
Creating WCF Service Host Programmatically
Net.Tcp Port Sharing Sample, Part 2
Service Station: WCF Addressing In Depth
As far as I know you can't specify configuration on per operation basis. The lowest level is the interface level. The simplest (ugly) solution would be to put each operation in a separate interface.
Putting each operation in a separate interface is a valid and good design approach. Agatha Request/Response Layer follows this approach. Have a look at this and this is pretty useful and extensible
http://code.google.com/p/agatha-rrsl/