Imagine I have the following, standard WCF, code :
[ServiceContract]
interface ICustomerService {
[OperationContract]
Customer GetCustomer();
}
public ICustomerService {
public Customer GetCustomer()
{
return MyStore.WhatIsNeeded();
}
}
This is working well and allows me to distribute the service and the consuming code.
Is it possible (and is it a good idea) to completely bypass the WCF engine if working in a single box ?
In fact, I want the app to be able to run on farm servers, or on small single box servers.
To reduce WCF messaging cost, I'd like to have something like :
ICustomerService service = null;
if(singlebox)
{
service = new CustomerService(); // Direct instanciation of the service class. No WCF here ...
}
else
{
service = new CustomerServiceClient(); // Wcf client
}
var cust = service.GetCustomer();
If wrapped properly, can this technique reduce server charge ?
That won't work because the client will be attempting to access an endpoint for a service that no longer is exposing one. The WCF plumbing is required for the both the service and the client. For single box scenarios, look at the NetNamedPipeBinding which is the WCF plumbing done through the equivalent of shared memory.
This will surely reduce the overhead of WCF runtime. I'd create a factory class which will check if(singlebox) and new up the right implementation of ICustomerService.
Related
My application needs to comunicate with several external WCF services to satisfy requests from client applications. Being itself a WCF service, it must of course be able to process several simultaneous requests. That being, and since I will be acessing more than one service, I thought about grouping clients in the following manner:
public static class ClientManager
{
private static readonly Service1Client _service1Client = new Service1Client();
private static readonly Service2Client _service2Client = new Service2Client();
...
public static Service1Client Service1DefaultClient { get { return _service1Client; } }
public static Service2Client Service2DefaultClient { get { return _service2Client; } }
}
Then, from the remaining of the code, I would only need to execute
ClientManager.Service1DefaultClient.SomeMethod();
ClientManager.Service2DefaultClient.SomeMethod();
...
The idea is to create a central place to better manage WCF clients. However, I don't really know if this design is the most appropriate one for a service which will be issuing several requests at the same time to Service1DefaultClient and Service2DefaultClient. What do you suggest? Creating a more complex client pool with several proxies from each service to choose from?
Having static client proxies doesn't look like a good idea to me.
If ClientBase instance transitions to the Faulted state, it becomes unusable and you have to re-create it.
If you have a stateful service, session lifetime will be the same as lifetime of a client proxy object, which is very long in your case.
Depending on your binding settings, ClientBase may serialize concurrent calls made on the same proxy instance. In your case, this may strongly affect performance.
I just don't see what problem does this solve.
Proxies are relatively lightweight because of the ChannelFactory caching, so I would just create a new instance every time it is needed.
I'm developing a service oriented architecture for an application and I would like the services to be exposed both over WCF as well as usable through a simple library. Ideally I would like to reduce duplicated code.
Conceptually, this maps to:
Client => WCF Service => Service Library (actual implementation)
or
Client => Service Library (actual implementation)
based on where the client is located (local or remote).
Here's a simple example:
[ServiceContract]
public interface ICalculator
{
[OperationContract]
int Add(int a, int b);
}
public class Calculator : ICalculator
{
public int Add(int a, int b)
{
return a + b;
}
}
public class CalculatorFactory
{
public static ICalculator CreateCalculator()
{
return new Calculator();
}
}
And my client application did the following
int result = CalculatorFactory.CreateCalculator().Add(1,2);
or
int result = IChannelFactory<ICalculator>().CreateChannel().Add(1,2);
depending on if it were local or remote.
Is it a bad practice to call into WCF annotated code directly (i.e., without using WCF)?
Additional comments:
I realize that I could use WCF in all cases and just host the service using NamedPipes for local connections. I would like to avoid this if I can for simplicity sake.
The alternative to the above is to essentially duplicate the ICalculator interface in the service library and change the WCF service implementation to contain CalculatorFactory.CreateCalculator().Add(1,2). This seems like a lot of overhead given that I want the interface to be the same.
You can create and consume WCF annotated classes localy without any problems unless you start to use some WCF related features like OperationContext etc.
Generally this is useually abstracted in different way:
Client => ServiceAgent => Business Service
or
Client => ServiceAgent => WCF Service => Business service
The client itself doesn't know if the service is local all remote. The service agent is client side component which based on its implementation either creates local service instance or callse remote WCF service which in turn creates business service instance. ServiceAgent can be injected as dependency into client which will make your application pretty good configurable. Also you can expose different interface on the service agent (the same as business service implements) and if you want WCF service and proxy can use different one.
If you decite to use WCF service all the time including local calls don't use NamedPipes. NamedPipes are for inter process communication on the same machince. If you want to use communication in the same process use NullTransport or Local Channel instead. It still has worse performance then direct call.
I want to write a high level design document for a application which will expose it's webs ervices for various clients. For this purpose I need to provide the WSDL of webservices that we will develop in the future at server side. I've use web services earlier but never drill down in the details of WSDL.
I searched a lot and found that I need to generate WSDL using XML and XSD. Well, I yet to design both and I think this would be my first step.
Now my concern here is that it is very difficult to work with raw XML and I am not master in WSDL terminology.
Can anyone suggest what are the high level steps that one should perform to create a simple WSDL with some fault information in it?
Any insight would be helpful.
Thanks guys.
It is probably easier to just use WCF to create your WSDL for you. You just need to define your OperationContracts and DataContracts. You don't have to implement the operations just define what they are in an interface.
Actually if you are following contract first development you should generate your "Messages" first .
In classic Web services you would actually start with XSDs for your requests, and responses. Then generate the code from the XSDs to guarantee that your data types are compliant with SOAP. Fortunately the DataContractSerializer has become very smart and will take care of your data types for you.
With that in mind, you should generate your Service Contract(s) and Request / Response messages (Data Contracts) first. When you expose a mex endpoint in WCF your WSDL will be generated for you. Creating your own WSDL can be very complex and really the only reason you should attempt it is if you actually want to hide functionality from certain consumers. Even if you wanted to generate your own WSDL for this reason, it would still be easier to let WCF create if for you and then alter it as you saw fit.
Let's stop here and see if you have any further questions.
My motivation for contract-first web services was to allow the service and the client to be written in parallel by different developers. Using WSDL and "Add Service Reference", you have to publish the service before you write the client.
As an alternative, don't go through WSDL. You can write one .NET interface that is shared by both the client and the service. This class will generate a WCF proxy directly from an interface:
public interface IServiceClientFactory<TServiceInterface>
{
void CallService(Action<TServiceInterface> action);
TResult CallService<TResult>(Func<TServiceInterface, TResult> function);
}
public class ServiceClientFactory<TServiceInterface> :
IServiceClientFactory<TServiceInterface>
where TServiceInterface : class
{
class Client : System.ServiceModel.ClientBase<TServiceInterface>
{
public TServiceInterface Service
{
get { return base.Channel; }
}
}
public void CallService(Action<TServiceInterface> action)
{
Client client = new Client();
try
{
action(client.Service);
client.Close();
}
catch (Exception)
{
client.Abort();
throw;
}
}
public TResult CallService<TResult>(Func<TServiceInterface, TResult> function)
{
Client client = new Client();
try
{
TResult result = function(client.Service);
client.Close();
return result;
}
catch (Exception)
{
client.Abort();
throw;
}
}
}
More details at Adventures in Software.
I am working on an n-Tier application using WCF between the layers such that:
Tier 1: Silverlight application
Invokes the search request
IClientBroker clientBroker = UIContext.CreateWcfInterface<IClientBroker>("Data/ClientBroker.svc");
clientBroker.BeginSearchForClients(SearchTerm, 20, (result) =>
{
SearchResult[] results = ((IClientBroker)result.AsyncState).EndSearchForClients(result).ToArray();
// do stuff, update UI, etc.
}, clientBroker);
Tier 2: is a WCF web service using basicHttp for Silverlight to call. This is acting as a proxy to the 3rd tier.
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
class ClientBroker : IClientBroker
{
[OperationContract] // as defined in IClientBroker
public SearchResult[] SearchForClients(string keywords, int? maxResults)
{
ClientBrokerClient clientBroker = CreateClientBrokerClient();
SearchResult[] searchResults=clientBroker.SearchForClients(keywords, maxResults);
return searchResults;
}
}
Tier 3: is the "server", in that this offers a net.tcp endpoint (allowing secure clients to connect without using Silverlight). This is the ultimate target of a request.
public class ClientBroker : IClientBroker // note this is different to tier 2 interface
{
public SearchResult[] SearchForClients(string keywords, int? maxResults)
{
// do stuff
if (maxResults.HasValue)
{
return results.Take(maxResults.Value).ToArray();
}
else
{
return results.ToArray();
}
}
}
So my calls go:
Silverlight -> httpBasic -> IIS-hosted Proxy WCF service --> net.tcp --> EXE-hosted WCF service
This works well. I can pass headers through the layers, and maintain sessions, etc. And it is pretty trim.
BUT it takes only a few calls through this to cause a Timeout in the communication.
The time the server-EXE takes to do its work is neglible.
The problem I am seeing is that the server "freezes" in returning results to Tier 2.
I think this is to do with a thread getting locked.
I've looked around and see that the ideal way of doing this is to make my Tier 2 run asyncronously, similar to the code below:
public SearchResult[] SearchForClients(string keywords, int? maxResults)
{
ClientBrokerClient clientBroker = CreateClientBrokerClient();
clientBroker.BeginSearchForClients(keywords, maxResults, result =>
{
SearchResult[] searchResults=((ClientBrokerClient)result.AsyncState).EndSearchForClients(result);
// how to return results from here?
}, clientBroker);
}
But how do I achieve this when my Tier 1 client is waiting for the result of this method, which will just drop straight out before the callback execute? Am I missing something on my construction of my OperationContract methods?
UPDATE:
I have since put my server (Tier 3) through its paces from a client avoiding Tier 2 by making many requests from it. Seems the net.tcp WCF channel for Tier 3 is rock solid.
UPDATE 2:
This blog post outlined using the IAsyncResult pattern, which I have eluded to here. Am I barking up the wrong tree here? http://blogs.msdn.com/wenlong/archive/2009/02/09/scale-wcf-application-better-with-asynchronous-programming.aspx
UPDATE 3:
Ok, this paragraph from that blog:
"If you are building N-tier WCF
services, you would have WCF service
operations invoking WCF client proxies
for other backend services. In this
case, you would need to make sure that
the middle-tier (routing layer) has
asynchronous service operation
invoking asynchronous WCF proxy
operations. In this way, your
middle-tier won’t run out of threads
when processing many slow operations."
seems to confirm my suspicions that the problem lies in the middle layer (Tier 2). How can I achieve this Begin/End asynchrony? Do I have to do this manually or can I retain VS tools to generate the proxy classes for me? (REALLY don't want to have to do this manually, the contracts have a degree of flux in them)
Well, I think I've solved it. This topic helped me:
wcf service stops after few requests
Basically, I hadn't been closing my client proxies in my Tier 2, which I realise would cause blocking. The evolution of the code was such that I ended up removing using() {} blocks to facilitate exceptions not getting extinguished with the client proxy. However, I have restructured and retested and my Tier 2 code now looks like:
public SearchResult[] SearchForClients(string keywords, int? maxResults)
{
ClientBrokerClient clientBroker = CreateClientBrokerClient();
SearchResult[] searchResults=clientBroker.SearchForClients(keywords, maxResults);
clientBroker.Close();
return searchResults;
}
... and exceptions are not extinguished.
I'm currently in the process of writing a WCF REST service with SubSonic SimpleRepository and the WCF REST Contrib library. The service is going to be hosted on IIS 7. The database is going to be MS SQL Server. I could not really find a good example which is using this combination of technologies on the internet. The service should expose a database in a RESTful manner but also contains some business rules (e.g. registering users, saving statistics) so I can't use ADO.net Data Services. Because there are going to be a lot of clients accessing the service at the same time it's important that the service can serve several clients at the same time.
For good performance I want to use the following service behaviour:
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession, ConcurrencyMode=ConcurrencyMode.Multiple)]
There are no instance variables in the Service class and as I understand it, those attribute values cause new a instance of the service class to be created for every call (not per session because it is called over https).
I used the following simple class for creating the SimpleRepository once (singleton):
public class DB
{
private static SimpleRepository _Repository;
public static SimpleRepository Repository
{
get
{
if (_Repository == null)
{
_Repository = new SimpleRepository("5Drive", SimpleRepositoryOptions.RunMigrations);
}
return _Repository;
}
}
}
Here is an example method of my service:
Interface:
[OperationContract]
[WebGet(UriTemplate = "vehicles")]
[WebDispatchFormatter]
Vehicles GetVehicles();
Implementation:
public Vehicles GetVehicles()
{
// get all vehicles for the logged in user
var vehicles = from v in DB.Repository.All<Vehicle>()
where v.UserID == GetUserID()
orderby v.Name
select v;
return new Vehicles(vehicles);
}
So, here is my question: can I do it this way? Is SimpleRepository thread-safe? Do I have to create a SimpleRepository in every method instead of using a singleton? What about performance when I do that? I looked at the SimpleRepository source code and I think that the migration code is not thread safe because the "private readonly List migrated;" is not synchronized but I might be wrong.
Maybe I'm missing something and I can just ignore multi-threading and configure IIS differently?
Thanks for your help!