Hi i am in the process of creating a restful service with WCF, the service is likely to be consumed by at least 500 people at any given time. What settings would i need to set in order to deal with this. Please give me any points and tips, thanks.
Here is a sample of what i have so far;
[ServiceBehavior(IncludeExceptionDetailInFaults = true, InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
And this is an example of a method being called;
public UsersAPI getUserInfo(string UserID)
{
UsersAPI users = new UsersAPI(int.Parse(UserID));
return users;
}
[OperationContract]
[WebGet(BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json, UriTemplate = "User/{UserID}")]
[WebHelp(Comment = "This returns a users info.")]
UsersAPI getUserInfo(string UserID);
The best approach would be to use:
InstanceContextMode.PerCall
ConcurrencyMode.Single
This will create a new instance of the service class for each caller and saves you from having to worry about multi-threaded, concurrent access to your code, since each request gets its own service class instance (which in itself is single-threaded - it serves only a single caller at a time).
Also, with this approach, you can easily "scale out", e.g. just simply add more servers to handle higher load (servers at your locations, or "in the cloud", e.g. Windows Azure workers).
Using the ServiceThrottling service behavior, you can control very easily how many concurrent callers are allowed - this depends on the type and size of your machine.
<serviceBehaviors>
<behavior name="Throttling">
<serviceThrottling
maxConcurrentCalls="16"
maxConcurrentInstances="16"
maxConcurrentSessions="10" />
</behavior>
</serviceBehaviors>
Those are the defaults for WCF 3.5 - the maxConcurrentCalls settings defines how many callers can be handled simultaneously.
Check out the MSDN docs on Service throttling for more details.
Related
One of my WCF service operation has transaction enabled-
[OperationBehavior(TransactionScopeRequired = true)]
public Car UpdateCar(Car c)
{
}
Earlier, I was running this service with InstanceContextMode as PerCall and ConcurrencyMode as Multiple which was getting me the below error-
An unhandled exception of type 'System.InvalidOperationException' occurred in System.ServiceModel.dll
Additional information: The 'InventoryManager' service is configured with ReleaseServiceInstanceOnTransactionComplete set to true, but the ConcurrencyMode is not set to Single. The ReleaseServiceInstanceOnTransactionComplete requires the use of ConcurrencyMode.Single.
In order to solve above error, i set 'ReleaseServiceInstanceOnTransactionComplete' to false and this did the trick.
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall
, ConcurrencyMode = ConcurrencyMode.Multiple
, ReleaseServiceInstanceOnTransactionComplete = false)]
Can someone please help to understand how disposing the service instance with 'PerCall' and 'Multiple' case solved this problem. What is the problem WCF thinks if I release service instance.
These are purely design decision made by the WCF designers.
From the book programming WCF services:
The WCF architects did not trust developers to properly manage state of their sessionful service in the face of transactions. Therefore they decided to treat a sessionful transactional service as a per-call service to enforce a proper state aware programming model.
And a Percall service with ConcurrencyMode.Multiple is useless of course. At the service load time WCF verifies that if TransactionScopeRequired is true for at least one operation when ReleaseServiceOnTransactionComplete is true, the ConcurrencyMode is ConcurrencyMode.Single.
That is the behaviour you are observing.
https://books.google.nl/books?id=PvNrurEhmiEC&pg=PA348&lpg=PA348&dq=per-session+transactional+services&source=bl&ots=CiDuKxG_Ox&sig=UvkgF1yTxmirsf_Zb452bW86AmQ&hl=nl&sa=X&ved=0ahUKEwiYjrX-uPrPAhWGfhoKHTgWBckQ6AEIHDAA#v=onepage&q=per-session%20transactional%20services&f=false
The designers were probably right with the decision to let WCF handle concurrency in the face of transactions. It is hard to manage your own concurrency in a service.
For instance, I had a service that also acted as a client of another service.
When changing the concurrency mode to Multiple the service would sometimes throw the exception when trying to open the client connection:
"System.InvalidOperationException: Cannot make a call on this channel because a call to Open() is in progress."
This is the kind of hard to debug kind of bugs the designers wanted to avoid (I think)
The default implementation of Service is
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
If there is a TransactionScope defined on any Operations on your Service implementation:
[OperationBehavior(TransactionScopeRequired = true)]
public void Method() { }
The default Service implementation will be dropped to
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
And this attribute will prevent it and will regain your PerSession semantics:
[ServiceBehavior(ReleaseServiceInstanceOnTransactionComplete = false)]
Take note that this is necessary if you have sessionful service and atleast one TransactionScopeRequired = True, on one of your operations.
We came across a god object in our system. The system consists of public service exposed to our clients, middle office service and back office service.
The flow is the following: user registers some transaction in public service, then manager from middle office service checks the transaction and approves or declines the transaction and finally manager from back office service finalizes or declines the transaction.
I'am using the word transaction, but in reality those are different types of operations like CRUD on entity1, CRUD on entiny2... Not only CRUD operations but many other operations like approve/send/decline entity1, make entity1 parent/child of entity2 etc etc...
Now WCF service contracts are just separated according to those parts of the system. So we have 3 service contracts:
PublicService.cs
MiddleOfficeService.cs
BackOfficeService.cs
and huge amount of operation contracts in each:
public interface IBackOfficeService
{
[OperationContract]
void AddEntity1(Entity1 item);
[OperationContract]
void DeleteEntity1(Entity1 item);
....
[OperationContract]
void SendEntity2(Entity2 item);
....
}
The number of those operation contracts are already 2000 across all 3 services and approximately 600 per each service contract. It is not just breaking the best practices, it is a huge pain to just update service references as it takes ages. And the system is growing each day and more and more operations are added to those services in each iteration.
And now we are facing dilemma as how can we split those god services into logical parts. One says that a service should not contain more then 12~20 operations. Others say some different things. I realize that there is no golden rule, but I just would wish to hear some recommendations about this.
For example if I just split those services per entity type then I can get about 50 service endpoints and 50 service reference in projects. What is about maintainability in this case?
One more thing to consider. Suppose I choose the approach to split those services per entity. For example:
public interface IEntity1Service
{
[OperationContract]
void AddEntity1(Entity1 item);
[OperationContract]
void ApproveEntity1(Entity1 item);
[OperationContract]
void SendEntity1(Entity1 item);
[OperationContract]
void DeleteEntity1(Entity1 item);
....
[OperationContract]
void FinalizeEntity1(Entity1 item);
[OperationContract]
void DeclineEntity1(Entity1 item);
}
Now what happens is that I should add reference to this service both in public client and back office client. But back office needs only FinalizeEntity1 and DeclineEntity1 operations. So here is a classic violation of Interface segregation principle in SOLID. So I have to split that further may be to 3 distinct services like IEntity1FrontService, IEntity1MiddleService, IEntity1BackService.
The challenge here is to refactor your code without changing large portions of it to avoid potential regressions.
One solution to avoid large business code with thousands of lines would be to split your interfaces/implementations into multiple parts, each part representing a given business domain.
For instance, your IPublicService interface could be written as follows (using interface inheritance, one interface for each business domain):
IPublicService.cs:
[ServiceContract]
public interface IPublicService : IPublicServiceDomain1, IPublicServiceDomain2
{
}
IPublicServiceDomain1.cs:
[ServiceContract]
public interface IPublicServiceDomain1
{
[OperationContract]
string GetEntity1(int value);
}
IPublicServiceDomain2.cs:
[ServiceContract]
public interface IPublicServiceDomain2
{
[OperationContract]
string GetEntity2(int value);
}
Now for the service implementation, you could split it into multiple parts using partial classes (one partial class for each business domain):
Service.cs:
public partial class Service : IPublicService
{
}
Service.Domain1.cs:
public partial class Service : IPublicServiceDomain1
{
public string GetEntity1(int value)
{
// Some implementation
}
}
Service.Domain2.cs:
public partial class Service : IPublicServiceDomain2
{
public string GetEntity2(int value)
{
// Some implementation
}
}
For the server configuration, there is still only one endpoint:
<system.serviceModel>
<services>
<service name="WcfServiceLibrary2.Service">
<endpoint address="" binding="basicHttpBinding" contract="WcfServiceLibrary2.IPublicService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8733/Design_Time_Addresses/WcfServiceLibrary2/Service1/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True" />
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Same for the client: still one service reference:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IPublicService" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:8733/Design_Time_Addresses/WcfServiceLibrary2/Service1/"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IPublicService"
contract="ServiceReference1.IPublicService" name="BasicHttpBinding_IPublicService" />
</client>
</system.serviceModel>
This allows to refactor your server side by splitting your huge services into multiple logical parts (each part associated with a given business domain).
This doesn't change the fact each of your 3 services still has 600 operations, so the client proxy generation would still take ages. At least your code would be better organized server-side, and the refactoring would be cheap and not-so-risky.
There is no silver-bullet here, that is just code reorganization for better readability/maintenance.
200 services with 10 operations for each vs 20 services with 100 operations for each is another topic, but what is sure is that the refactoring would require way more time, and you would still have 2000 operations. Unless you refactor your whole application and reduce this number (for instance by providing services that are more "high-level" (not always possible)).
Having too many operation contracts doesn't make sense in a given service as it will leads to maintenance issues. Having said that if operations like Add(), Delete, Update(), AddChildItem(), RemoveChildItem(), etc are supposed to be together, then don't worry about operation contract going up to 30-40 in number. Because things that should be together should come out from a single interface (cohesion).
But 600 operations in a given service contract is really overwhelming number. You can start identifying the operations:-
That are required to be together
And that are not required to be together in a given service.
Based on this you can split the operations into different services.
If some of the methods are not used by client directly, then consider exposing the method based on the BUSSINESS logic (as also suggested by "Matthias Bäßler").
Say you want to expose the MoneyTransfer functionality. Then you are not required to expose
SendEmail()
DebitAccount()
CreditAccount(), etc in the service used by your web application.
So here you can expose just an aggregate service to your web application. In this case it may be IAccountService with methods like just
TransferMoney()
GetBalance(),
Internally in your implementation you can create other service which provides related operation like:-
SendEmail()
DebitAccount()
CreditAccount(), etc. required for IAccountService. MoneyTransfer() method.
This way, the number of methods in a given service will come down to a maintainable level.
I don't have experience with WCF but I think god classes and overloaded interfaces seem to be a general OOD problem.
When designing a system you should look for behaviour (or business logic) instead of data structures and operations. Don't look at how you're going to implement it but how the client would use it and how he would name it. In my experience, having the right names for the methods usually provides a lot of clues about the objects an their coupling.
For me the eye-opener was the design of the Mark IV coffee maker, an excerpt from "UML for Java Programmers" by Robert C. Martin. For meaningful names I recommend his book "Clean Code".
So, instead of building an interface of discrete operations like:
GetClientByName(string name);
AddOrder(PartNumber p, ContactInformation i);
SendOrder(Order o);
Do something like:
PrepareNewOrderForApproval(PartNumber p, string clientName);
Once you've done this, you also might refactor into separate objects.
Your problem is not so much a god object problem, as it is a service composition problem. God objects are problematic for different reasons than huge, crud-based service interfaces are problematic.
I would certainly agree that the 3 service contracts you have described are reaching the point where they are effectively unmanageable. The pain associated with refactoring will be disproportionately higher than if this was in-process code, so it's very important you take the correct approach, hence your question.
Unfortunately, service composability in soa is such a huge topic it's unlikely you'll receive massively useful answers here; though obviously useful, the experiences of others will unlikely apply to your situation.
I have written about this on SO before, so for what it's worth I'll include my thoughts:
I find that it's best if service operations can exist at a level where
they have business meaning.
What this means is that if a business person was told the operation
name, they would understand roughly what calling that operation would
do, and could make a guess at what data it would require to be passed
to it.
For this to happen your operations should fulfill in full or in part
some business process.
For example, the following operation signatures have business meaning:
void SolicitQuote(int brokerId, int userId, DateTime quoteRequiredBy);
int BindPolicyDocument(byte[] document, SomeType documentMetadata);
Guid BeginOnboardEmployee(string employeeName, DateTime employeeDateOfBirth);
If you use this principal when thinking about service composition then
the benefit is that you will rarely stray far from the optimal path;
you know what each operation does and you know when an operation is no
longer needed.
An additional benefit is that because business processes change fairly
rarely you will not need to change your service contracts as much.
I create WCF service with Spring.NET framework. This service is math service
and provide some computations for client apps.
I have question about WCF service parallelization on multi-core server. For simple
example I have server with 20 cores.
First here is a simplified code.
//WS interface
public interface IMatlabService
{
List<ResultData> Calculate(byte [] data);
}
//WS class definition
[ServiceBehavior(Namespace = "http://server.com/MatlabService")]
public class MatlabService: IMatlabService
{
public IMatlabManager MatlabManager{get;set:}
//web metod for math computations
public List<ResultData> Calculate(byte [] data)
{
var result = new List<ResultData>();
//do math work in another thread
Task<List<ResultData>> task = Task.Factory.StartNew<List<ResultData>>(() =>
{
return MatlabManager.CalculateWithFiniteElementMethod(data);
});
result.AddRange(task.Result)
return result;
}
}
public interface IMatlabManager
{
List<ResultData> CalculateWithFiniteElementMethod(byte [] data);
}
public class MatlabManager : IMatlabManager
{
public List<ResultData> CalculateWithFiniteElementMethod(byte [] data)
{
// do some math work
}
}
With Spring.NET I configure web service and manager class as not singleton.
Spring.NET XML configuration is here.
Matlab manager configuration:
<object name="matlabManager"
type="MatlabManager"
singleton="false"/>
MatlabService configuration:
<object name="matlabService"
type="MatlabService"
singleton="false">
<property name="MatlabManager" ref="matlabManager"/>
</object>
WCF service configuration from web.config
<behavior name="Behavior1">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
<services>
<service name="matlabService"
behaviorConfiguration="Behavior1">
<endpoint address=""
binding="basicHttpBinding"
contract="IMatlabService"
bindingNamespace="http://server.com/MatlabService"/>
<endpoint contract="IMetadataExchange"
binding="mexHttpBinding"
address="mex"/>
</service>
</services>
SVC file.
<%# ServiceHost Language="C#" Debug="true" Service="MatlabServiceService" Factory="Spring.ServiceModel.Activation.ServiceHostFactory" %>
I believe for each client web metod call is created new instance of
MatlabService and WCF service work is do on new thread (WCF service
thread) and OS assign this thread to CPU core.
Or I am wrong and behavior create new service object per call I must
define in ServiceBehavior property InstanceContextMode?
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)]
In web method Calculate of MatlabService I use
System.Threading.Tasks for parallelization so math work is do in
another thread (Math thread).
For each call is created WCF service thread and in WCF service
thread is created Math thread.
I am not sure if this is true.
Maybe is needed allow multi-threading in WCF service in
ConcurrencyMode?
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall,ConcurrencyMode
= ConcurrencyMode.Multiple)]
I would like heard ideas how can parallelize web metod calls for multi core CPU.
I google it but not find any clear and usefull for me because I use Spring.NET framework for creation WCF service.
The default instance context mode is PerCall, so setting that explicitly is redundant.
Yes, you're creating an additional thread to do the math operations, but you're not gaining anything because you're blocking until the task is complete. In fact, it is less efficient because you have the overhead of creating and mangaging an additional thread.
Each web call is already serviced in its own thread.
The only place I can see to add additional parallel computing is within the implementation of:
MatlabManager.CalculateWithFiniteElementMethod(data)
However, that looks like a call to Matlab. If you can reimplement that method using parallel code, you might be able to eek out some performance gains.
Whatever you do, profiling is the key to understanding if you're actually making it faster. Remember - parallel doesn't always mean faster. There is overhead in synchronizing these operations and creating the threads for them.
I have a WCF application (vb) which works fine but when a user requests information while the server is doing a call to another user, everybody hangs!
When you configure your service, there are two things you need to configure:
InstanceContextMode - which determines how many service instances are created to service the client requests, try use PerCall/PerSession if possible as they allows for the most concurrency.
ConcurrencyMode - which determines if each service instance is single-threaded or multi-threaded.
Based on the information you've provided so far, I'd recommend changing these two settings and see if it solves your problem:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall,
ConcurrencyMode = ConcurrencyMode.Multiple)]
public class MyService : IMyService { ... }
I put a blog post together of the things I learnt whilst doing some performance work on our WCF services a little while back, maybe it'd be of help:
http://theburningmonk.com/2010/05/wcf-improve-performance-with-greater-concurrency/
I am specifically looking for an example which use a) WCF & REST. After a long googling, though I got some but they are beyond my understanding.
Could some one please give me a very simple example say "Hallow World" or Summation of 2 numbers which will give me a clear insight about how to write a server, and also how to consume the same from the client end.
Also if any good link that explains this kind of example in simple terms kindly tell me that.
Thanks
REST in WCF is not that hard once you figure it out.
First you must define your interface.
Here is an example.
[ServiceContract]
public interface IRESTExample
{
[WebGet(UriTemplate = "interaction/queue?s={site}", RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml)]
[OperationContract]
string QueueInteraction(string site);
[WebGet(UriTemplate = "interaction/cancel?id={interactionId}", RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml)]
[OperationContract]
string CancelInteraction(string interactionId);
[WebGet(UriTemplate = "queue/state?s={site}&q={queue}", RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml)]
[OperationContract]
string QueueState(string site, string queue);
}
You can see in the WebGet you define the final URL. So it depends on where you bind it, but say you bind the endpoint to www.example.com/rest
QueueInteraciton would be www.example.com/rest/interaction/queue?s=SomeSite
Where {stie} or {parameterName} is replaced with the name of the parameter.
The implemetion is just a simple class, I am going to assume you know how to implement an interface. If you need help just leave a comment.
Now binding the endpoint. In the end it is not that hard, you can do it all in the config.
<system.serviceModel>
<services>
<service name="Stackoverflow.Example.Service.RestExample" behaviorConfiguration="MyServiceTypeBehaviors">
<host>
<baseAddresses>
<add baseAddress="http://localhost:2136/RestExample"/>
</baseAddresses>
</host>
<endpoint address="rest" binding="webHttpBinding" behaviorConfiguration="xmlBehavior" contract="Stackoverflow.Example.Service.IRESTExample" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceTypeBehaviors" >
<!-- Add the following element to your service behavior configuration. -->
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="jsonBehavior">
<webHttp/>
</behavior>
<behavior name="xmlBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name = "NoSecurity">
<security mode = "None" />
</binding>
</basicHttpBinding>
</bindings>
</system.serviceModel>
Now the code to start the service and bind it. YOu can do it in anything, for example a console app.
RestExample exampleService = new RestExample();
host = new ServiceHost(exampleService);
host.Open();
This should be enough to get started.
msdn article An Introduction To RESTful Services With WCF with code example at msdn code gallery. Also check out this codeproject article
David Basarab's response is correct, but there's a much simpler way to do this without all the manual wire-up. Especially if you've used to classic ASMX web services and don't have a lot of WCF experience, the following method is dirt simple.
In a Visual Studio 2010 web project, add a reference to System.ServiceModel.Web.
Chose "add new item" in your project. The template you want is in "Web" and is called "AJAX-enabled WCF Service". Don't choose the vanilla "WCF Service"! If you do you have to do all the web.config wiring yourself that David Basarab described, and it's a pain. The "AJAX-enabled WCF Service" does all that setup for you. Name your service whatever you want.
Open up the .svc file. In the [ServiceContract] attribute on your class, fill in the Namespace string parameter with whatever you want.
You'll get a sample DoWork() method and a bunch of comments telling you what to do in the file. The trick to getting the RESTful API is to add [WebGet()] attributes to your web methods. Add one to DoWork() and verify everything functions for you.
So, to call the DoWork() method, you'd hit this in your browser:
http://localhost/MyAjaxEnabledService.svc/DoWork
Let's add a new HelloWorld() method now that shows some parameters and output.
VB:
<OperationContract()>
<WebGet(ResponseFormat:=WebMessageFormat.Xml)>
Public Function HelloWorld(ByVal name As String) As String
WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml"
Return String.Format("Hello, {0}!", If(String.IsNullOrWhiteSpace(name), "world", name))
End Function
C#:
[OperationContract()]
[WebGet(ResponseFormat=WebMessageFormat.Xml)]
public string HelloWorld(String name) {
WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml";
Return String.Format("Hello, {0}!", String.IsNullOrWhiteSpace(name) ? "world" : name);
}
Now you can visit:
http://localhost/MyAjaxEnabledService.svc/HelloWorld?name=MattMc3
There's a lot of crappy and confusing documentation out there about WCF, especially for those who crave the simplicity of the old .ASMX style. Hopefully this helps someone get started with WCF. There's a lot more you can do with it than the old ASMX-style, but it's hard to ramp up and not get discouraged with MS for their poor help with the transition from ASMX. You can read more about quick-and-dirty RESTful WCF services here.
If you really want to do ReST then use a web framework that will lead you down the right path. See OpenRasta.
It is not impossible to do WCF to do ReST, it is just very difficult to learn how to do Rest with a framework that will frequently get in your way and lead you in the wrong direction.
In Microsoft Web Developer, you can use the Online Template "WCF REST Service." It will set up a project for you with the correct web.config and global.asax files.
You can create an WCF REST web service by configuring your endpoint to use a webHttpBinding as seen in this in-depth tutorial:
http://www.west-wind.com/weblog/posts/310747.aspx
Here is another open source web services framework that simplifies creating XML and JSON REST web services without requiring any extra configuration.
Edit: Added link to good article articulating the spirit of REST:
http://tomayko.com/writings/rest-to-my-wife
Link to blog post comment explaining common misconceptions of REST:
http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven