I am in the process of writing an enterprise-level application utilizing WCF and NetTCP services. I chose NetTCP initially out of curiosity, but later determined it to be the best option for me since I can have services that are called that take 5+ hours to return results due to the amount of data crunching involved.
The way I currently spawn my services is a multi-step process. I have a configuration piece (using System.Configuration) that specifies some of the default stuff (port number, server name for clients connecting in, whether to enable HTTP as well as NetTCP, etc) and that has a collection of "services" underneath it. For example, here's what a basic one looks like:
<serverConfiguration tcpListenerPortNumber="60000" httpGetEnabled="true" httpListenerPortNumber="6000" serverName="localhost" retryEnabled="true" retryInterval="5" maxRetryAttempts="3">
<services>
<add virtualDirectory="Service1" applicationName="Service1" assembly="SampleService" type="SampleService.Service1" />
</services>
</serverConfiguration>
Basically what's happening here is my Windows service kicks off and looks at everything in the <services /> collection and spawns off a thread per service to speed startup time and each thread contains an AppDomain where the service truly lives so if a service has some kind of fault it doesn't bring the system down.
The "problem" I am running into is this application is hosting approximately 20 services and it takes a good 15-20 seconds for all the services to be up and running. I did the threading and AppDomain pieces to get it down to that value (used to take over a minute as each service was opened sequentially) but it still seems to me that this could actually go a lot faster.
Anyone have any suggestions? Google Bing has a plethora of examples for hosting one service but I'm not finding much out there for real-world applications (sadly "Hello World" just isn't appealing to end users). If you're currently hosting multiple services via a Windows Service and NetTCP, how are you doing it?
I figured it out finally and it had nothing to do with WCF or my configuration pieces after all. When I was creating the AppDomain I stole the code from another project we had that was much smaller in size and found that the section creating AppDomains was using the SingleDomain option. Changing it to MultiDomain made things go to >4 seconds for total load and memory usage dropped to ~40MB from ~150MB.
Thanks for the assistance though - at least it got me reviewing the code again!
I have three suggestions:
Firstly, if a call can take 5+ hours, I would consider a queuing / call back style architecture.
Consider splitting your services into 20 windows services, where each service runs in it's own windows services. This adds complexity and increases memory usage, but an individual service may be available faster.
Lastly, check the code that is in the consructor of the service, for any unneeded code.
Related
I have a situation where I have two programs (one exe and one dll loaded into the process space of another third-party exe) communicating requests with each other using a local machine wcf service (using net named pipe binding). There's a third host exe that starts hosting the service. It all works great (so far anyways... I'm still learning), but I got to thinking about what would happen if the channel faults or the service times out. What would be the best practice for checking and handling faults as well as keep the channel alive?
In my case it will be up to the user to keep the applications open or close them and we do have those users who tend to keep them open overnight, over the weekend, etc... It seems to me this could open the possibility of a fault or loss of service and I don't have a clue how to recover. Any help would be greatly appreciated.
Firstly, why would you keep the channel alive indefinitely?
Imagine you are connecting to a database from which you want to read over the course of one day. Would you create the database connection in the morning and then close it in the evening?
It is relatively cheap to construct a channel in WCF for each call, unless you know you are going to be making multiple calls within a few seconds of each other, in which case you should reuse the channel.
EDIT
This post explains how to do it. It's pretty complicated and it may be easier to just set a huge timeout value for the binding in code (as suggested at the end of the post):
Do WCF Callbacks TimeOut
EDIT
There's tons of stuff on google about this: http://bit.ly/10ZPWE2
This is a design question, I guess there going to be several suggestions (I hope so!)
We are a small travelling agent office, we are developing a software for our need. We have 30 clients on the local LAN, sometime later some other 5-10 from outside the office. (This will be agents on route).
Would you create a WCF service for this scenario or just leave the DL in the client (for direct access to the SQL)??
Our DataAccess Technology is EntityFramework 4.0 (4.1), ALL clients are Windows 7 based.
About the travelling agents, wouldn't it be much more simple to just use a VPN for the agents connection??
We have plans to supply our guides (outside the office ) with 3G tablets in about 1 year from now.
Developing clients with a DL is of course much more straight forward solution, but our plans for the near future will require some kind of service. The tablets application will have a much more simple interface and functionality. So maybe developing a WCF service dedicated for the tablets will be better?
Our first consideration is time, we are in great need for a working software.
Well, I hope I managed to share with you our thoughts clearly enough.
Thank you for reading.
I think one technology that would be a) very well-suited to your needs, and b) doesn't impose a huge overhead on your development effort would be WCF Data Services.
This is a REST-based WCF service based on a model - like your Entity Framework model.
Check out:
the WCF Data Services Developer Center
MSDN docs on WCF Data Services
I would see clear benefits in architecting a new solution from the get-go to use a service-based approach - even if your local LAN client might end up not using that service layer. Thinking in services, thinking also about the limitations of sending data across a potentially slower link than your LAN usually helps avoid silly mistakes like loading 200'000 customers into a dropdown box and stuff like that...
Having a service layer also makes your client app much less dependent on the actual database technology - that client might be a Winforms, WPF or Silverlight app, a web site, a tablet - you name it. If they all share the service layer, development of the client app will become less of a burden - the majority of your work will be in your data model and your service layer (which is shared across all clients).
I am trying to figure out the best way to approach this design... Here is some background of what I'm trying to do:
I have a simple digital I/O controller that sends data to my computer via Ethernet. I have a program that can receive this data over Ethernet. I would like a separate front end application that presents this data in a GUI. I am trying to figure out the best way to interface the program that grabs the I/O data over Ethernet, and the program that displays this as the front end. This interface should run whenever the computer boots and constantly poll the I/O in the background.
I've read about Windows Communication Foundation (WCF) and this seems like a nice way to do this. As the windows service would quietly keep polling the I/O and any clients that attach to the WCF interface can present this data in a GUI.
Am I going about this all wrong? Does this seem like a good way to do things? How will my front end clients grab the data from the WCF service?
Thank you in advance.
That's precisely the way I have done it - hosting a WCF service in a Windows service. The Windows service is the process; the WCF service is where the work is done.
In my case, my WCF-based CollectionService is on standby most of the time. I use WCF to start and stop the collector because the WCF programming model makes this easy. However, to get the data from the collector to the UI, I use a TCP socket, not WCF. I know that WCF has a streaming mode, but (1) I've never used it and (2) I believe there is some amount of overhead using WCF this way. The socket is simply a comfortable fallback for me, but I think WCF could be made to work.
If you're just starting, you can refer to these two answers for getting your Windows service up and running using C#. From there, you'll just need to create the ServiceHost and close it in the OnStart() and OnStop() callbacks of your Windows service, respectively.
Easiest language for creating a
Windows service
How to make a
.NET Windows Service start right
after the installation?
If you are new to WCF, take a look at this SO question.
Good and easy books/tutorials to learn WCF latest stuff
One more thing. In the course of your work on this, you may find that you want the WCF service to provide events to your UI when certain things occur. For example, you might provide an event that periodically notifies the UI of the number of bytes that have been received. For this, I would strongly recommend this article by Juval Lowy, one of the WCF gods.
What You Need To Know About One-Way Calls, Callbacks, And Events
His Publish-Subscribe Framework is available for free at his website, IDesign.net, along with several other working WCF examples.
Hope this helps.
I have a WCF service that works fine in IIS 7, however once deployed to Windows Server 2003, IIS6, I'm now getting - "The thread was being aborted" error message. This happens after a few minutes of the service running.
I've tried manually changing some timeout values and turned off IIS keep alives.
Any ideas on how to fix this problem would be welcomed.
Thanks
If you're having this problem - please read! Hopefully you'll save yourself A LOT of trouble knowing this. Get coffee first!
You might come from a traditional programming background, in fields not SOA related, and now you're writing SOA services with the mindset of "traditional programmer". Here are 4 of the most important lessons I've learnt since building SOA services.
Rule number 1
Try your very best not to write services that take an extended amount of time to complete. I know this can be VERY tricky to accomplish, but it is much more reliable to have smaller operations being called many times, than 1 long service performing all the work, then returning a response. For example recently I wrote a service which processed ALL tasks. Each task was stored as an XML file in the IIS site, and each task would export data to a system for example : SharePoint. At any given times during high volumes there could be up to 30 000 tasks waiting to be processed. Over the past 2 months I have yet to get it 100% reliable, this is after diving deep into timeout settings in IIS, AppPools and WCF bindings. Every now and again I would get - "The thread was being aborted" and no reason or explanation as to why this was happening. I exhausted all online knowledge bases, no one seemed the wiser. Eventually after not being able to fix the issues or even reproduce them in a reliable way, I opted for a complete rewrite. I changed my code to instead of process ALL tasks, process just 1 task at a time.
This essentially meant calling 1 web service 30 000 times, rather than calling it once, but performance wise, it is around the same. Each call issues a response quick, and does a lot less work. This has another benefit, I can provide instant feedback on each operation to the client. In the Long call, you get a response back right at the end and ALL at once.
You can also much more easily catch and retry a service call if it does fail, because you don't have to redo the whole call for each operation again, but simply the operation that failed.
Its easier to test too, not only because of the live feedback, but also because you can test 1 inner operation, without the overhead of the loop if you wanted to.
Lastly it adds better scaling if you plan on extending your application later, because you're broken things down into more manageable units of work. So for example: Before you had 1 service which processed ALL Tasks, now you have a web service that can process 1 TASK, because of this you can more easily extend the functionality if you needed to process 10 Tasks, or tasks by selection.
Rule Number 2
Don't upgrade your existing ASMX web services to WCF 3 just because you think its a better technology. WCF 3 is over architectured and not a real pleasure to work with, or deploy. If you need to go WCF, try your best to hold out for the version that ships with .net 4 of the framework, it seems to have been revamped. Another thing you will miss is that WCF has no test forms, so you can't just fire up a web browser quick to test your services. If you're like me - "Keep it simple stupid" Then WCF 3.5 will frustrate you.
Rule Number 3
IIS6 can be dodgy, if at all possible avoid having to host your services in IIS6, if you're after reliable services. I am not saying its impossible to achieve reliability in IIS6, but it requires a LOT of work, and a great deal of testing. If you're dealing with services that are critical, try avoid using a product developed in 2001.
Rule Number 4
Don't underestimate the development and testing required to create reliable SOA services. To be honest all I can say is it is a massive undertaking.
I thought I'd mention that this error is thrown by SharePoint when calling some functions from a user account. Those functions need to be run with SPSecurity.RunWithElevatedPrivileges
This answer shows up when searching for "wcf sharepoint Thread was being aborted" so hopefully this can be useful to someone since 'thread being aborted' isn't very useful of SharePoint to throw when its a permissions issue.
I'm using perfmon to examine my service behaviour. What I do is I launch 6 instances of client application on separate machines and send requests to server in 120 threads (20threads per client application).
I have examined counters and maximum number of instances (I use PerSession model and set number of instances to 100) is 12, what I consider strange as my response times from service revolve around 120 seconds... I thought that increasing number of instances will cause WCF to create more instances, and as a result response times would be quicker.
Any idea why WCF doesn't create even more instances of service?
Thanks Pawel
WCF services are throttled by default - it's a service behavior, which you can tweak easily.
See the MSDN docs on ServiceThrottling.
Here are the defaults:
<serviceThrottling
maxConcurrentCalls="16"
maxConcurrentInstances="Int.MaxValue"
maxConcurrentSessions="10" />
With these settings, you can easily control how many sessions or concurrent calls can be handled, and you can make sure your server isn't overwhelmed by (fraudulent) requests and brought to its knees.
Ufff, last attempt to understand that silly WCF.
What I did now is:
create client that starts 20 threads, every thread sends requests to service in a loop. Performance counter on server claims that only 2 instances of service object are created all the time. Average request time is about 40seconds (I start measuring before proxy call and finish after call returns).
modify that client to start 5 threads and launch 4 instances of that client (to simulate 20 threads behaviour from previous example). Performance monitor shows that 8 instances of service object are created all the time. Average request time is 20seconds.
Could somebody tell me what is going on? I thought that there is a problem with server that it doesn't want to handle more requests at concurently, but apparently it is client that causes a stir and don't want to send more requests concurently... Maybe there is some kind of configuration option that limits client from sending more then two requests at one time... (buffer,throttling etc...)
Channel factory is created in every thread.
You might want to refer to this article and make adjustment to your WCF configuration (specifically maxConnections) to get the number of connections you want.
Consider using something like http://www.codeplex.com/WCFLoadTest to hit the service.
Also, perfmon will only get you so far. If you want to debug WCF service you should look at the SvcTraceViewer and SvcConfigEditor in the Windows SDK.
On your service binding what have you set the maxconnections to? Calls to connect will block once the limit is reached.
Default is 10 I think.
http://msdn.microsoft.com/en-us/library/ms731379.aspx