+1.916.577.1977 | Downloads | Buy | Register | Login
 Search  
Saturday, April 05, 2008
Search Blogs
 

Available Blogs
 

Previous Blogs
 

Technorati
 
More blogs about coversant.

About Coversant
 

Windows Sockets and Threading: How well does it scale?
 
Location: BlogsMullin' with Mullins    
Posted by: Chris Mullins 7/9/2006

We were recently asked by a client if the SoapBox Server 2007 could handle 1 million simultaneous users on a single machine. The SoapBox Server 2007 is a .NET 2.0 beast that runs on x86, x64 and Itanium platforms and has been tested without issue up to 100,000 simultaneous users.

The problem with answering the question, “Can you hit a MegaUser?” is that we don’t know the answer. Like most small companies (and even a few small countries), hardware of the scale required is out of our budget range. Dual Core laptops and desktops? No problem. Eight and 16 way machines with 48GB+ of memory? No thank you, not today. That BMW M6 sure looks nice though, and it’s much cheaper. Can I have one of those instead?

Through our partnership with HP (thank you Donna!) we got access to some of the very cool Itanium hardware. Specifically they gave us exclusive access for a week to a pair of 16 processor Itanium2 machines each with 64GB of memory. They even threw a few tadpoles in with the sharks - a quad proc for the database, and a dual proc for whatever else we needed.

I’m going to assume that those of you reading this are familiar with threads and the various techniques for dealing with them. If not, there is a lot of material on the Internet covering basic threading under Windows and C# - just look for stuff written by Richter and begin reading.

Now, some quick background on our server:

The SoapBox Server is a heavily multithreaded server designed around Asynchronous Sockets. When running on Windows 2000, XP, 2003, Vista, and Longhorn this means that we get to use the entire IO Completion Port (IOCP) infrastructure for all of our socket operations. From a practical perspective this means that we call “BeginRead()” on all of our sockets, and whenever data arrives on a socket we magically get a callback from Windows with the right data. No use of the dreaded “1 Thread Per Socket” pattern and no use of the BSD style select pattern the Unix folk tend to use.

SoapBox Server, Stage 1

Our first architecture, years ago, had data coming in from the sockets, processed into valid xml stanzas, appended to a queue, and then the socket put back into BeginRead Mode.

Blog_SoapBoxArchitecture1.PNG

As an architectural pattern, this is a fairly common way to go:

1. Pull data from socket

2. Queue it up for processing

3. Go back to reading from the socket.

This architecture has some clear advantages:

1. Receiving data, and processing data are completely decoupled. As a result of this, you don’t have to worry about IOCP thread starvation. There will always be plenty of threads to service data coming in from the socket, process that data into Xml, and stick it into a processing queue.

2. Logically, the worker threads are simpler to deal with. As the IOCP threads have a clearly defined scope (turn bytes from a socket into xml, and enqueue it) they’re easy to code and debug. The processing threads also have a very defined role (pull data from the queue, and process it). Well defined roles and explicit boundaries between threads means fewer bugs, and easier debugging.

There are some disadvantages to this as well:

1. The penalty for thread context switching is high, and we’re guaranteed at least one context switch per transaction. When we benchmarked this, we saw some fairly ugly performance numbers.

2. In our communication space, packets that come in on a particular socket must be processed in order. This means, in order to keep the worker threads busy, you need to either have a queue per socket or a look-ahead mechanism. The actual problem is this: Let’s say user 1 sends two commands to the server: “This” and “That”. The server begins processing “This” as it was the first to arrive, but now the queue is blocked, because “That” can’t be processed until “This” is completed. Hard problem to solve? Not really – but it’s there and can’t be forgotten about.

3. The locking mechanism on the queue needs to be robust. There are a number of threads reading and writing to the queue (up to 1000 IOCP threads writing to it, and some number of worker threads pulling data from it). This means a reader/writer lock isn’t appropriate, and the only easy way to do this is using Monitors (aka: ‘lock’ in C#). Lots and entering and exiting the monitors. Lots and Lots. Lots! (but hey, monitors are pretty quick, so this isn’t a problem, right? Hah! See below…)

Overall this model worked well, but we just couldn’t get it to scale that well. On a dual processor Xeon box (2.4 ghz, 3 GB of memory, all 32 bit) box we topped out at about 1000 xml transactions per second (a transaction being a Message Echo: Message In, Message out). This isn’t slow but it’s also not fast. Making extensive use of the Compuware Profiler, the SciTech memory profiler, and Windows Performance Counters, we were able to determined that our threading model was holding us back. Too many locks, too many thread context switches.

SoapBox Server, Stage 2

The obvious answer to our troubles is to get rid of our processing queue and our custom thread pool: Process everything in the context of the IOCP thread.

Blog_SoapBoxArchitecture2.PNG

1. Operations on incoming data can be long. Sometimes we have to hit the database, sometimes an LDAP server, sometimes another XMPP server. These can take a long time, and during that time our IOCP thread is blocked. Async database operations weren’t an option in .Net 1.1, and are now only an option when using the SqlDataProvider. They don’t work with Oracle, Postgres, or MySql – all databases that we support.

2. Due to the number of long running operations, we end up with a lot of IOCP threads all alive at once. In fact the number is just scary at times.

There was another subtle problem with this architecture that took us a while to realize: We couldn’t slow things down. We discovered this the hard way – the server would hang, and we would use ADPlus to generate a crashdump. Loading that dump into WinDbg and Son of Strike we would find 1000 IOCP threads (yea, you read that right) all blocked in ADO.Net.

With the IOCP threads all busy doing database reads and writes (or LDAP reads, or AD reads, or any long running operation) the Internal Windows Sockets buffers would fill up. As these internal buffers filled up, client applications would start receiving errors. Once we got into this state, there was no recovering from it short of restarting the process This clearly isn’t good!

Overall this architecture worked well for small scales. Once we had 3000 or more active sockets this architecture started running into the problems described above. (In the general case this architecture could handle significantly more than 3000 sockets, but the customer in question had an LDAP server that couldn’t handle the load. We would see the LDAP server progressively slow down until our threads were essentially locked, then *poof* no more server. Our Dynamic LDAP groups really beat on an LDAP server, especially with caching turned way down so that any changes to the directory take effect immediately).

SoapBox Server, Stage 3

It took a while, but we finally figured out a way to address the issues that we ran into in stages 1 and 2.

As much as we didn’t want to, we reintroduced our threadpool back into the equation. This means data coming in from a socket would once again be put into a work queue. The big difference is where and how we processed data coming off the socket, and the state management around the socket. Once the BeginReceive callback is completed and a work item has been posted to the Queue (complete with the rigth IAsyncResult), we let the IOCP thread just silently go away, to be put back into the pool of available threads.

Blog_SoapBoxArchitecture3.PNG

Once our worker thread finishes processing the work item it's last responsibility is to call BeginRead on the socket thereby putting it back into read mode.

This architecture ends up with some nice advantages:

1. We could put a choke on the number of simultaneous operations being processed. By adjusting the size of the thread pool, or the number of active threads in it, we could effectively tune the number of parallel operations. This kept us from crashing LDAP servers, having too much database lock contention in SQL Server, and several other nice benefits. It also let us tune the CPU Utilization of the server so that customers who freak out when they see a CPU spike can now be appeased (I Know. I Know. I am hanging my head in shame. Really. See?)

2. We never have two simultaneous operations from a single user, so the logic for processing work items can be a standard queue. This is because until the work item for user 1 is completed, we don’t even pull data out of the socket for that user. Data just queues up inside the Socket. Go Windows!

3. Overall responsiveness at the socket level is better, as there are always plenty of IOCP threads available to handle requests.

4. In the case of a hyperactive user, that user may see some delays in their messages being handled, but the overall system performance isn’t impacted at all. Other users continue to see a responsive server.

The drawbacks:

1. Well, we’re back to our original performance problem: Every single operation has at least one thread context switch. Data comes in on an IOCP thread and gets queued up. That queue is process by a worker thread. This means there is always 1 context switch per packet. This isn’t the end of the world, but it would sure be nice not to have this.

2. We’ve got locks to deal with again – all writes to the queue mean grabbing a lock, and all reads from the queue mean grabbing a lock. Ah well. Locks are fast. Usually. That’s a whole topic for an upcoming blog…

3. We’re managing our own threads, and we’re not as good at it as the IOCP infrastructure is.

4. This architecture differs from common IOCP architecture in a signifigant way, and that's always somewhat of a risk.

This architecture is where we’re at today. It handles over 100,000 simultaneous users without breathing hard, and has been over 500,000 a few times in the lab (the issue has always been client firepower, not server horsepower). Handling 10,000 to 20,000 simultaneous users is a breeze. We can log in 10k users, log them out, log in 20k users, log them out, and so forth. Everything is very stable.

SoapBox Server, Stage 4

We’ve got a few things planned that we think will help us out a bit more. It’s not clear yet if these are optimizations that we need to make, but should the need arise we may.

The biggest optimization we're looking at is the elimination of thread context switch for very specific, frequent, use cases. Like all applications, there are a few use cases that happen far more frequently than all the others. For us these cases are:

1. User sends a message

2. User receives a message

3. User announces presence

4. User receives presence

These cases comprise the bulk of the work a server does during day-to-day operations. For these use cases we may try to avoid the thread context switch and perform all processing on the IOCP thread. This elimination of context switches should save us a fair bit of processor time.

Some other options involve special casing algorithms depending on usage and processor count. For example: locking the work queue for reads and writes is very quick on a single or dual processor machine. On a 16 processor machine the contention over that lock is pretty scary. There exist thread safe, lock free data structures. These lock free data structures are slower on single and dual processor machines than their locking counterparts, but as the processor count increases their performance stays constant whereas the locking structures see an exponential performance decrease.

We’re also looking and waiting to see what impact the Windows Scalable Networking Pack has on our performance. From what we’ve seen so far, as the number of connections grow the performance of the Windows Network Stack drops off. When profiling our code with a lot of simultaneous connections there are some performance issues that don’t appear to be in our code, but rather inside Windows Sockets. Hopefully the features in the Scalable Networking Pack will address this. All documentation indicates the future looks bright on this horizon…

The Vista and Longhorn network stacks appear to be higher performance than those found in Windows 2003 Server and Windows XP. There may be improvements seen as we migrate to the new operating systems.

Conclusions

The SoapBox Server scales to a frightening number of simultanious users. This is due to the inherent scalability of Windows Sockets and .NET, as well as the architecture chosen inside the application. With the arrival of 64 bit hardware, .Net 2.0, and the addition of some blood, sweat and tears, it appears that the SoapBox Server can vertically scale high enough to handle any load that is realistically going to be thrown at it.

I’m always happy to discuss this stuff, and I’m open to new ideas and thoughts. Please fire away with the comments and questions!

Permalink |  Trackback

Comments (20)  
Re: Windows Sockets and Threading: How well does it scale?    By jconley on 7/12/2006
Why, what pretty pictures you have. So I guess I'll have to write up the article on the network stack limits we found then, eh? :) I would like to point out that the third drawing is actually slightly incorrect. We don't currently do anything on the IOCP thread except enqueue the IAsyncResult we get back in the callback passed into BeginReceive. We don't call EndReceive, and thus don't have any data to process, until we're in our own threadpool. Then we do everything on our own thread, including the XML parsing/validation and strongly typed object creation.

Re: Windows Sockets and Threading: How well does it scale?    By cmullins on 7/12/2006
The diagram has been updated to be accurate. Peer Review is a good thing....

Re: Windows Sockets and Threading: How well does it scale?    By ritchiep on 7/22/2006
I was under the impression that Asynchronous Sockets in .NET (i.e. BeginReceive/EndReceive and BeginSend/EndSend) did not use completion ports but use overlapped I/O, which limits calling of the AsyncCallback to the thread that called the Begin* method. Which is only alluded to in the documentation for Begin* with the note "All I/O initiated by a given thread is canceled when that thread exits. A pending asynchronous operation can fail if the thread exits before the operation completes."

Re: Windows Sockets and Threading: How well does it scale?    By cmullins on 7/23/2006
On Win98 and WinME, the .Net framework uses overlapped I/O for socket access. On the WinNT platform (all the current generation O/S) IOCP is used. This is easy enough to verify - break out Reflector and start poking through the .Net framework.

There's a new property in .Net 2.0 on the socket called "UseOnlyOverlappedIO" that can force overlapped I/O, and this defaults to False. Details of this can be found at:
http://msdn2.microsoft.com/en-us/library/system.net.sockets.socket.useonlyoverlappedio.aspx

The callbacks into the callback methods happen on different threads than the caller was originally on. We see this all the time, and its normal, expected behavior for the way sockets perform.

I'm not quite sure what to make of the documentation that says:

All I/O initiated by a given thread is canceled when that thread exits. A pending asynchronous operation can fail if the thread exits before the operation completes.

This doesn't make sense to me, and I don't think I've ever seen it happen. But on the other hand, I don't kill threads either - they all live in a long-lived thread pool.

Re: Windows Sockets and Threading: How well does it scale?    By ritchiep on 7/24/2006
Could be that "All I/O initiated by a given thread is canceled when that thread exits. A pending asynchronous operation can fail if the thread exits before the operation completes." is worst-case...

I've analysed the framework with Reflector, which is what prompted the comment; and I couldn't find any reference in the framework to PInvoking, CreateIoCompletionPort or {Get|Post}QueuedCompletionStatus. I'm assuming the use of completion ports is pushed into the native region of the CLR, i.e. IOCompletionCallback.BeginInvoke...

Good to know.

Re: Windows Sockets and Threading: How well does it scale?    By jeremy on 8/30/2006
in fact , is not native I/O completion ports mode , just windows overlapped I/O mode. If you break out the reflector and you would not found the important IOCP APIs in the framework(.net 2.0 & .net 1.1), just like CreateIoCompletionPort , {Get|Post}QueuedCompletionStatus.
The only thing you will find it's the ReadFile/WriteFile native method in Win32Native.cs, mscorlib.dll.


[DllImport("kernel32.dll", SetLastError=true)]
internal static extern unsafe int ReadFile(SafeFileHandle handle, byte* bytes, int numBytesToRead, IntPtr numBytesRead_mustBeZero, NativeOverlapped* overlapped);

[DllImport("kernel32.dll", SetLastError=true)]
internal static extern unsafe int WriteFile(SafeFileHandle handle, byte* bytes, int numBytesToWrite, IntPtr numBytesWritten_mustBeZero, NativeOverlapped* lpOverlapped);

Socket.UseOnlyOverlappedIO is based on that, and this is the words picked out from msdn:
Socket.UseOnlyOverlappedIO Property
Note: This property is new in the .NET Framework version 2.0.
Specifies whether the socket should only use Overlapped I/O mode.





Re: Windows Sockets and Threading: How well does it scale?    By staceyw on 9/25/2006
It seems the primary difference between #1 and #3 is you moved the xml processing and object creation out of IOCP thread and into TP thread. Is that right? Your saying that bit processing in the IOCP thread was slowing it down that much? tia

Re: Windows Sockets and Threading: How well does it scale?    By cmullins on 9/25/2006
Processing in the IOCP thread wasn't slowing things down at all - in fact introducting the additional thread context switch had a measurable performance impact. The problem was that because we NEED to perform some synchronious I/O during requests (mostly DB access, and there's no good Async way to do that) we would end up having our IOCP threads stalled at bad times with no way to manage things.

This model fixed quite a bit of that. I listed it's various Pro's/Con's in the section in the blog.

Re: Windows Sockets and Threading: How well does it scale?    By RyanLiu_99 on 12/27/2006
Hi Chirs,

Thanks a lot for your article.

First, a basic general question, when will the callback method be called?
Right after BeginReceive() or when the data is available? It shoulb be
called in the same thread which receives data and is called after data is
available, right?

Is that possible to show a few lines sample to demonstrate your idea?

For stage 3:

Is that(if not, what about)per Processing Queue per client/socket?

And where we put the IAsncResult in the queue? From stage 3 diagram, seems
this is done inside BeginReceiveCallBack method. What about we put it into
queue by code immediate follow socket.BeginReceive().

Between the EndRecevie BeginReceive, the socket is not receiving data (if
socket buffer is full) and could block client. Is this the same case for
stage 2 and 3? So the stage 3 does not solve one of the problem stage 2 has?


So is that better to take processing time out of time between EndReceive and
BeginReceive? That is call BeginReceive right after put IAsncResult in the
queue, instead call it at the end of process.


And clients send different kind of message and vary in size, when I call
BeginReceive, how can I specify the size? How can I make sure I won't get
into the middle of message, e.g. get 1.5 message in byte[]?

BeginReceive will use thread in thread pool. And for threads that processing
queue, are explicitly created by our code, right?

But if as I said, call BeginReceive right after put IAsncResult in the
queue, then we never explicitly create any threads and we seems call
BeginReceive more frequently and use more threads in thread pool. Is this
right statement?

Thanks a lot!
Ryan

Re: Windows Sockets and Threading: How well does it scale?    By cmullins on 12/28/2006
Ryan,

The callback method is called when data has been received, or when the socket has closed down. It's called from the context of an IOCP thread - there's no concept of "this is the thread that received data".

A processing queue per client socket would be difficult to manage in an effective way. With 100k client sockets, I would need to monitor 100k queues for incoming data. The WaitAny() infrastructure can only deal with up to 64 handles at a time, so a custom solution would be needed, and would probably not be that efficient.

Queuing the IAsyncResult is done in the callback, just after EndReceive has been called. There's no need to keep track of an IAsyncResult returned by BeginReceive when using this model.

As for size, (for varying message lenghts), there's no good answer. You've got to read the data you get, parse it to see if it makes sense, and then either processor it or call BeginReceive again to get the rest of the data, meanwhile storing the data you pulled off the socket somewhere were you can get to it later.

Based on where you seem to be at in terms on async socket knowledge, I would recommend you follow model 2 - it's the best cominbation of scalable, and easy to use. You won't have to create and manage your own threads (which is very tricky), and it will scale and perform very well.

At this point, your best bet is to go do some research on how async sockets work. There's alot of material and a number of examples on the web. CodeProject has several excellent primers on the topic.

Performance and scalability - simple Benchmark ... ?    By cdemez on 1/10/2007
Hi everybody ;-)

Here I have create a small benchmark... there are :
- Synchronous version of client
- Asynchronous version of client
- Synchronous version of server
- Asynchronous version of server

I have play with all the versions, I have got the following result :
1) Client_Synchrone + Server_Synchrone = 120 Mb/s
2) Client_Synchrone + Server_ASynchrone = 110 Mb/s
3) Client_Asynchrone + Server_Synchrone = 110 Mb/s
4) Client_Asynchrone + Server_ASynchrone = 110 Mb/s

For the 4 versions I'm near of 100% CPU use.

Asynchronous with ManualResetEvent to avoid: "NoBufferSpaceAvailable"
------------------------------------------------------------------------------------------------

So, I'm able to hanlde 10Mb/s more with synchrone Send/Receive !
It is +- 10% faster than asynchronous version !

Also, with this version of Asynchronous Send, sometimes I got a
"SocketError.NoBufferSpaceAvailable" ... because the "Send buffer is full".

To avoid this, I can allow only one BeginSend at a time. (I use a ManualResetEvent), here are the results :

5) Client_Asynchrone_Lock + Server_Synchrone = 80 Mb/s
6) Client_Asynchrone_Lock + Server_ASynchrone = 80 Mb/s

and CPU use is near of 100% too...

So, really... Does BeginSend is really usefull ?

Which version to use to have the faster and more scalable server ?

Krys

Re: Windows Sockets and Threading: How well does it scale?    By cmullins on 1/10/2007
Your benchmark, as you described it, isn't to usefull.

Do you have 1 socket open? Are you exchaning data, or just doing a data blast to the server? If you're getting "NoBufferSpaceAvailable", iit sounds like you're just sending data to the server as fast as you can without doing any processing.

Also, multiple BeginSend's at a time? To a single socket? This doesn't make any sense.

If all you have is a few sockets, you should use whatever method you're most confortable coding. If you have lots of sockets, using the Async methods is your only options.

Re: Windows Sockets and Threading: How well does it scale?    By cdemez on 1/11/2007
Hi,

It is because I'm working on a File Transfer server, so I exchange a lot of data between 2 sockets.

What I have see with BeginSend/BeginReceive is that it is 20% less faster than using normal Send/Receive on high bandwidth networks! It is a simple conclusion.

Re: Windows Sockets and Threading: How well does it scale?    By cmullins on 1/11/2007
It's still anything but simple. If you have 500 sockets going, how do you manage it? 500 threads? How about if your machine has 8 processors? How about if the user doing the sending is on a very slow link? How about it all the users save 1 is on a very slow link?

The resource management around sockets is very complex. Identify what you think your primary use cases are, the scalability you need, and make sure you can do it.

In my experience, sync sockets are not going to scale. The threads you need to start will kill your scalability.

Re: Windows Sockets and Threading: How well does it scale?    By ArneLagrange on 2/11/2007
Hi Chris,

Thank you for sharing yor experiences on Sockets and IOCP.
I'm doing something similar to your application and I also use a model as described in stage 2. I found an axample on codeproject and used it as a start for my server app. Everything is fine so far but now I found your advices and warnings about using ado in this context. I build in a lot of db queries recently and now I'm a little bit concerned about it because of your explanations.
I have to handle up to 200 connections and then I do exactly the same as you described in the picture. I get the binary data, store incomplete messages, and start my processing if I have a complete message that I transfer into an appropriate object. I do not start any other thread because I thought "riding on a IOCP thread" is a good idea. My problem is that I have a lot of db queries which we do by using the netTiers Framework. You are saying that your problems started at 3000 connections ? So I should be save for the moment, should'n I ?
How do you handle the sockets if there is no incoming data any more ? My problem is that I have to send and receive a lot of messages between my server and the client without droping the connection. To avoid any timer I'm always waiting for data that comes out of the socket and then process it (There is always a challenge / response roundtrip ) but if the socket is dropped for any reason and I do not recognize it (which is the case when I'm waiting for a message and someone pulls the hardware wire out of the client) I'm lost...
Any ideas for a timer ? Any help would be appreciated.
Regards,
Arne

Re: Windows Sockets and Threading: How well does it scale?    By cmullins on 2/12/2007
Arne,

You're really somewhat stuck. If you do I/O bound synchronous processing on your IOCP threads, eventually you're going to break. Your SQL Server may hit a table lock, you may timeout enough operations to tie up your threads, or something else may go on. With SQL, the big bottleneck is the number of connections in the pool - if you set this to 100, then thread 101 is stuck waiting on Connection.Open. This quickly can have all your threads blocked waiting for SQL.

Handling sockets that aren't sending or receiving data isn't a problem at all. Just leave the socket in "BeginReceive(...)", so that if something is send, you wake up. There's no need to shutdown the sockets.

You do 100% need to be aware of dropped sockets. This shows up pretty cleaning though, using the Async Socket infrastructure. If someone pulls the wire out, you're stuck waiting on TCP timeouts - which can take a while. You have 2 options for this: change the default timeouts to something that'll meet your requirements, or have a timer than sends whitespace pings (we use spaces) across the sockets on a regular interval (we do this on the client side). This helps pickup dropped sockets much faster and avoids registry tweaks.

Re: Windows Sockets and Threading: How well does it scale?    By ArneLagrange on 2/20/2007
Hi Chris,

Thank you for your quick response.
Sounds not very good to me. Hope it will work for a while and I come up with a solution in the meanwhile.
You are sending the pings from the client side because you will run out of timer threads on the server, am I right ? What do you think about checking the time a client is connected to the server. My clients will disconnect after 5 minutes of inactivity. Therefore I thoght adding a timestamp to my session could be a solution. Every time I send a message to my client I update this timestamp. At certain points, e.g. when I add new clients to my clients list I check if there is a client with a timespan which is not allowed ( > 5 minutes) of no response. I think this will work although it sounds a bit weired...
Is it possible to buy your general architecture ? I know that I can buy your product but what I need is basically your underlying framework for handling a lot of connections.
Another question regarding ADO. You wrote that it should be possible with asynchronous ADO functions. This might be no problem because we will use just SQL Server 2005 in this project. Do you have any articles / links which provide some examples or suggestions ?
Any additional help will be appreciated.
Thanks in advance.
Arne

Re: Windows Sockets and Threading: How well does it scale?    By haogu on 3/8/2007
We are building a data center server to collect large amount of data (more than 1G total) from many (1 to 10000) devices (either embeded windows or linux devices), who knows protocols like TCP and web services, and other very slow industry protocols. We are currently using web services (in async mode), but are thinking about switching to low level socket programming like what you have. The concern we have is that the overhead of web service may be problem. Howerver web service does give us some advantages, such as marshaling data across platforms and auto generating strongly typed objects. We also implemented the publish/subscription model that is very similar to what .Net remoting has, which solved the issue of the web service's disconnected nature (to track and expire sessions based on lease). I am curious what you think between the web service and raw socket programming.
I believe our model looks like your third diagram. A problem that we ran into is that processing a large piece of data from a client may delay the process from another client, as we have a single work queue.

Re: Windows Sockets and Threading: How well does it scale?    By haogu on 3/8/2007
Forgot to mention that the above data size 1G that we have to consume is on a daily base.

Re: Windows Sockets and Threading: How well does it scale?    By cmullins on 3/8/2007
Haogu,

1GB of data, over a 24 hour period, is really very little data. If you told me it was 1GB over a 1 hour period, I would still consider that to be a pretty small amount of data. Worrying about overhead due to web services is way premature.

I think you would be fine using Web Services, .Net Async Sockets, or WCF (Indigo). You might also want to look into using a persistant MSMQ to hold data that's been received but not yet processed. You could also look at hosting your web service directly inside SQL 2005, and writing your data to SQL as it comes in.

I wouldn't build your own remoting layer - that's just a problem waiting to happen. Either use .Net Remoting, or WCF. There are some WS-* standards you could use as well.

My personal preference (I may be biased) is to use XMPP. But then everything looks like an XMPP problem to me these days.


©2008 Coversant, Inc. | Privacy Policy | About Coversant | Contact Info