<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Udi Dahan - The Software Simplist &#187; Performance</title>
	<atom:link href="http://www.udidahan.com/category/performance/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.udidahan.com</link>
	<description>Enterprise Development Expert &#38; SOA Specialist</description>
	<lastBuildDate>Sat, 24 Jul 2010 20:06:18 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>MySpace Architecture Considered Expensive</title>
		<link>http://www.udidahan.com/2009/10/09/myspace-architecture-considered-expensive/</link>
		<comments>http://www.udidahan.com/2009/10/09/myspace-architecture-considered-expensive/#comments</comments>
		<pubDate>Fri, 09 Oct 2009 21:24:09 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Caching]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Scalability]]></category>

		<guid isPermaLink="false">http://www.udidahan.com/?p=1126</guid>
		<description><![CDATA[I just finished listening to the Microsoft presentation on how they use the Concurrency &#038; Coordination Runtime (CCR) in MySpace (the stated largest web site running .NET).
Some interesting numbers were stated in the talk.

Tens of thousands to hundreds of thousands of requests per second
Over 3 thousand web servers
Over a thousand mid-tier servers

No wonder most big [...]]]></description>
			<content:encoded><![CDATA[<p>I just finished listening to the Microsoft <a href="http://channel9.msdn.com/shows/Communicating/CCR-at-MySpace/">presentation</a> on how they use the <a href="http://msdn.microsoft.com/en-us/library/bb905470.aspx">Concurrency &#038; Coordination Runtime (CCR)</a> in MySpace (the stated largest web site running .NET).</p>
<p>Some interesting numbers were stated in the talk.</p>
<ul>
<li>Tens of thousands to hundreds of thousands of requests per second</li>
<li>Over 3 thousand web servers</li>
<li>Over a thousand mid-tier servers</li>
</ul>
<p>No wonder most big web sites don&#8217;t run .NET. The Windows licenses would put them out of business.</p>
<p>Well, that is if you follow those same architectural practices.</p>
<p>I&#8217;ve written in the past of alternative architectural approaches that can scale to those levels at easily an order of magnitude less hardware (I think it&#8217;s closer to two OOMs) &#8211; here&#8217;s one of them on the topic of weather:</p>
<p><a href="http://www.udidahan.com/2008/12/29/building-super-scalable-web-systems-with-rest/">Building Super-Scalable Web Systems with REST</a>.</p>
<p>By the way, the client quoted in that post is now well above 60 million users with only small incremental increases in hardware. Oh, and their running everything on Windows and .NET. The question is not &#8220;can it scale&#8221;, but rather &#8220;how much will it cost to scale&#8221;.</p>
<p>Architecture pays itself back faster than ever in the Web 2.0 world.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2009/10/09/myspace-architecture-considered-expensive/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>MSDN Magazine Smart Client Article</title>
		<link>http://www.udidahan.com/2009/03/28/msdn-magazine-smart-client-article/</link>
		<comments>http://www.udidahan.com/2009/03/28/msdn-magazine-smart-client-article/#comments</comments>
		<pubDate>Sat, 28 Mar 2009 19:16:39 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[ESB]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Pub/Sub]]></category>
		<category><![CDATA[Scalability]]></category>
		<category><![CDATA[Smart Client]]></category>
		<category><![CDATA[WCF]]></category>
		<category><![CDATA[Web Services]]></category>

		<guid isPermaLink="false">http://www.udidahan.com/2009/03/28/msdn-magazine-smart-client-article/</guid>
		<description><![CDATA[
My article on “optimizing a large-scale Software+Services application” has been published in the April edition of MSDN Magazine.
Here’s a short excerpt:
“We had to juggle occasional connectivity, data synchronization, and publish/subscribe all at the same time. We learned that we couldn’t solve all problems either client-side or server-side, but rather that an integrated approach was needed [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://msdn.microsoft.com/en-us/magazine/dd569749.aspx"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; margin: 0px 0px 10px 10px; border-left: 0px; border-bottom: 0px" height="244" alt="image" src="http://www.udidahan.com/wp-content/uploads/MSDNMagazineSmartClientArticle_13E17/image.png" width="189" align="right" border="0" /></a></p>
<p>My article on “optimizing a large-scale Software+Services application” has been published in the April edition of MSDN Magazine.</p>
<p>Here’s a short excerpt:</p>
<blockquote><p>“We had to juggle occasional connectivity, data synchronization, and publish/subscribe all at the same time. We learned that we couldn’t solve all problems either client-side or server-side, but rather that an integrated approach was needed since any changes on one side needed corresponding changes on the other side.”</p></blockquote>
<p><a href="http://msdn.microsoft.com/en-us/magazine/dd569749.aspx">Continue reading… </a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2009/03/28/msdn-magazine-smart-client-article/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Building Super-Scalable Web Systems with REST</title>
		<link>http://www.udidahan.com/2008/12/29/building-super-scalable-web-systems-with-rest/</link>
		<comments>http://www.udidahan.com/2008/12/29/building-super-scalable-web-systems-with-rest/#comments</comments>
		<pubDate>Mon, 29 Dec 2008 21:38:58 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Caching]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[Scalability]]></category>
		<category><![CDATA[Web Services]]></category>

		<guid isPermaLink="false">http://www.udidahan.com/2008/12/29/building-super-scalable-web-systems-with-rest/</guid>
		<description><![CDATA[I&#8217;ve been consulting with a client who has a wildly successful web-based system, with well over 10 million users and looking at a tenfold growth in the near future. One of the recent features in their system was to show users their local weather and it almost maxed out their capacity. That raised certain warning [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been consulting with a client who has a wildly successful web-based system, with well over 10 million users and looking at a tenfold growth in the near future. One of the recent features in their system was to show users their local weather and it almost maxed out their capacity. That raised certain warning flags as to the ability of their current architecture to scale to the levels that the business was taking them.</p>
<p> <center><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="139" alt="danger" src="http://www.udidahan.com/wp-content/uploads/image51.png" width="408" border="0"></center>
</p>
<h3>On Web 2.0 Mashups</h3>
<p>One would think that sites like Weather.com and friends would be the first choice for implementing such a feature. Only thing is that they were strongly against being mashed-up Web 2.0 style on the client &#8211; they had enough scalability problems of their own. Interestingly enough (or not), these partners were quite happy to publish their weather data to us and let us handle the whole scalability issue.</p>
<h3>Implementation 1.0</h3>
<p>The current implementation was fairly straightforward &#8211; client issues a regular web service request to the GetWeather webmethod, the server uses the user&#8217;s IP address to find out their location, then use that location to find the weather for that location in the database, and return that to the user. Standard fare for most dynamic data and the way most everybody would tell you to do it.</p>
<p>Only thing is that it scales like a dog.</p>
<h3>Add Some Caching</h3>
<p>The first thing you do when you have scalability problems and the database is the bottleneck is to cache, well, that&#8217;s what everybody says (same everybody as above).</p>
<p>The thing is that holding all the weather of the entire globe in memory, well, takes a lot of memory. More than is reasonable. In which case, there&#8217;s a fairly decent chance that a given request can&#8217;t be served from the cache, resulting in a query to the database, an update to the cache, which bumps out something else, in short, not a very good hit rate.</p>
<p>Not much bang for the buck.</p>
<p>If you have a single datacenter, having a caching tier that stores this data is possible, but costly. If you want a highly available, business continuity supportable, multi-datacenter infrastructure, the costs add up quite a bit quicker &#8211; to the point of not being cost effective (&#8221;You need HOW much money for weather?! We&#8217;ve got dozens more features like that in the pipe!&#8221;)</p>
<p>What we can do is to tell the client we&#8217;re responding to that they can cache the result, but that isn&#8217;t close to being enough for us to scale.</p>
<h3>Look at the Data, Leverage the Internet</h3>
<p>When you find yourself in this sort of situation, there&#8217;s really only one thing to do:</p>
<div style="border-right: black 1px solid; border-top: black 1px solid; float: right; margin-left: 5px; border-left: black 1px solid; width: 220px; border-bottom: black 1px solid; background-color: beige">
<div style="font-size: 12px; margin: 5px">
<p>In order to save on bandwidth, the most precious commodity of the internet, the various ISPs and backbone providers cache aggressively. In fact, HTTP is designed exactly for that. </p>
<p>If user A asks for some html page, the various intermediaries between his browser and the server hosting that page will cache that page (based on HTTP headers). When user B asks for that same page, and their request goes through one of the intermediaries that user A&#8217;s request went through, that intermediary will serve back its cached copy of the page rather than calling the hosting server.</p>
<p>Also, users located in the same geographic region by and large go through the same intermediaries when calling a remote site.</p>
</div>
</div>
<p>Leverage the Internet</p>
<p>The internet is the biggest, most scalable data serving infrastructure that mankind was lucky enough to have happen to it. However, in order to leverage it &#8211; you need to understand your data and how your users use it, and finally align yourself with the way the internet works.</p>
<p>Let&#8217;s say we have 1,000 users in London. All of them are going to have the same weather. If all these users come to our site in the period of a few hours and ask for the weather, they all are going to get the exact same data. The thing is that the response semantics of the GetWeather webmethod must prevent intermediaries from caching so that users in Dublin and Glasgow don&#8217;t get London weather (although at times I bet they&#8217;d like to).</p>
<h3>REST Helps You Leverage the Internet</h3>
<p>Rather than thinking of getting the weather as an operation/webmethod, we can represent the various locations weather data as explicit web resources, each with its own URI. Thus, the weather in London would be <strong>http://weather.myclient.com/UK/London</strong>.</p>
<p>If we were able to make our clients in London perform an HTTP GET on <strong>http://weather.myclient.com/UK/London</strong> then we could return headers in the HTTP response telling the intermediaries that they can cache the response for an hour, or however long we want.</p>
<p>That way, after the first user in London gets the weather from our servers, all the other 999 users will be getting the same data served to them from one of the intermediaries. Instead of getting hammered by millions of requests a day, the internet would shoulder easily 90% of that load making it much easier to scale. <a href="http://www.perkel.com/politics/gore/internet.htm">Thanks Al</a>.</p>
<p>This isn&#8217;t a &#8220;cheap trick&#8221;. While being straight forward for something like weather, understanding the nature of your data and intelligently mapping that to a URI space is critical to building a scalable system, and reaping the benefits of REST.</p>
<h3>What&#8217;s left?</h3>
<p>The only thing that&#8217;s left is to get the client to know which URI to call. A simple matter, really. </p>
<p>When the user logs in, we perform the IP to location lookup and then write a cookie to the client with their location (UK/London). That cookie then stays with the user saving us from having to perform that IP to location lookup all the time. On subsequent logins, if the cookie is already there, we don&#8217;t do the lookup.</p>
<blockquote><p>BTW, we also show the user &#8220;you&#8217;re in London, <font color="#0000ff"><strong><u>aren&#8217;t you</u></strong></font>?&#8221; with the link allowing the user to change their location, which we then update the cookie with and change the URI we get the weather from.</p>
</blockquote>
<h3>In Closing</h3>
<p>While web services are great for getting a system up and running quickly and interoperably, scalability often suffers. Not so much as to be in your face, but after you&#8217;ve gone quite a ways and invested a fair amount of development in it, you find it standing between you and the scalability you seek.</p>
<p>Moving to REST is not about turning on the &#8220;make it restful&#8221; switch in your technology stack (ASP.NET MVC and WCF, I&#8217;m talking to you). Just like with databases there is no &#8220;make it go fast&#8221; switch &#8211; you really do need to understand your data, the various users access patterns, and the volatility of the data so that you can map it to the &#8220;right&#8221; resources and URIs.</p>
<p>If you do walk the RESTful path, you&#8217;ll find that the scalability that was once so distant is now within your grasp.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2008/12/29/building-super-scalable-web-systems-with-rest/feed/</wfw:commentRss>
		<slash:comments>30</slash:comments>
		</item>
		<item>
		<title>An Answer of Scale</title>
		<link>http://www.udidahan.com/2008/08/13/an-answer-of-scale/</link>
		<comments>http://www.udidahan.com/2008/08/13/an-answer-of-scale/#comments</comments>
		<pubDate>Wed, 13 Aug 2008 11:22:27 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Availability]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Scalability]]></category>

		<guid isPermaLink="false">http://www.udidahan.com/2008/08/13/an-answer-of-scale/</guid>
		<description><![CDATA[To the question of scale Ayende brings up, I thought I&#8217;d tap my concept map.
First of all, I wanted to address the relationship between various topics related to scalability:
 
And on the connection between scalability and throughput:
&#160; 
The important message here is that the scalability of a system is a cost function that gives throughput [...]]]></description>
			<content:encoded><![CDATA[<p>To the <a href="http://ayende.com/Blog/archive/2008/08/11/A-question-of-ScaleAgain.aspx">question of scale</a> Ayende brings up, I thought I&#8217;d tap my <a href="http://www.udidahan.com/2008/08/04/distributed-systems-concept-map/">concept map</a>.</p>
<p>First of all, I wanted to address the relationship between various topics related to scalability:</p>
<p><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="305" alt="performance topics" src="http://www.udidahan.com/wp-content/uploads/image40.png" width="550" border="0" /> </p>
<p>And on the connection between scalability and throughput:</p>
<p>&#160;<img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="334" alt="scalability topics" src="http://www.udidahan.com/wp-content/uploads/image41.png" width="550" border="0" /> </p>
<p>The important message here is that the scalability of a system is a cost function that gives throughput as a function of recurring costs and one time costs &#8211; servers and other hardware, and the join of buy &amp; build:</p>
<blockquote><p>Did you write your own <a href="http://ayende.com/Blog/archive/2008/08/09/Patterns-for-using-Distributed-Hash-Tables-Conclusion.aspx">locking/transaction mechanism</a> on top of an open source distributed cache or did you buy a license for a <a href="http://www.udidahan.com/2007/05/05/using-spaces-with-web-services/">space-based technology</a>?</p>
</blockquote>
<p>Also, don&#8217;t forget that people need to administer all the servers that you have. Those people cost money (easily100K per year). Maybe, because you haven&#8217;t invested in management or monitoring tools you need one person for every two servers. This will influence the breakdown of up front costs and recurring costs. Also, the level of availability you require will impact this as well.</p>
<p>In my experience, architects don&#8217;t consider often enough the operations environment in their &quot;scalability calculations&quot;.</p>
<p>What this means is that there&#8217;s no such thing as technically  &quot;not being able to scale&quot;.</p>
<p>Rather, that the cost (up front + recurring) of supporting higher throughput grows faster than the function of revenue per user/request/whatever.</p>
<p>Sometimes, the solution is just to find ways to make more money per customer.</p>
<p>For more technical solutions, take a look at <a href="http://www.udidahan.com/2007/12/12/scalability-you-wish-youre-gonna-need-it/">the difference between capacity and scalability</a> and how <a href="http://www.udidahan.com/2007/02/02/queues-scalability-availability/">the competing consumer pattern helps scale out</a>.</p>
<p>Scalability, it&#8217;s all about the money.</p>
<p>&#8211;</p>
<p>Oh, I almost forgot, I also had a great conversation with Carl and Richard about scaling web sites that&#8217;s <a href="http://www.dotnetrocks.com/default.aspx?showNum=367">now up</a> on the .NET Rocks site. Enjoy.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2008/08/13/an-answer-of-scale/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Durable Messaging Dilemmas</title>
		<link>http://www.udidahan.com/2008/07/17/durable-messaging-dilemmas/</link>
		<comments>http://www.udidahan.com/2008/07/17/durable-messaging-dilemmas/#comments</comments>
		<pubDate>Thu, 17 Jul 2008 22:18:47 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Availability]]></category>
		<category><![CDATA[Messaging]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Reliability]]></category>
		<category><![CDATA[Scalability]]></category>

		<guid isPermaLink="false">http://udidahan.weblogs.us/2008/07/17/durable-messaging-dilemmas/</guid>
		<description><![CDATA[I&#8217;ve received some great feedback on my MSDN article and some really great questions that I think more people are wondering about, so I think I&#8217;ll try to do a post per question and see how that goes.
Libor asks:
&#8220;Would you recommend using durable messaging for systems where there are similar requirements with respect to data [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve received some great feedback on my <a href="http://msdn.microsoft.com/en-us/magazine/cc663023.aspx">MSDN article</a> and some really great questions that I think more people are wondering about, so I think I&#8217;ll try to do a post per question and see how that goes.<img style="margin: 10px 0px 10px 10px" height="175" src="http://www.ewashtenaw.org/government/departments/cmhpsm/provider_information/Provider%20Training%20Resources/images/scales_of_justice.jpg" width="143" align="right"></p>
<p>Libor asks:</p>
<blockquote><p>&#8220;Would you recommend using durable messaging for systems where there are similar requirements with respect to data reliability as you had – ie. not losing any messages? If so, then why didn&#8217;t the final version of your solution use it? If not, can you explain why?&#8221;</p>
</blockquote>
<p>The answer is, as always, it depends, but here&#8217;s on what it depends:</p>
<p>When designing a system, we need to take a good, hard look at how we manage state, and what properties that state has. In a system of reasonable size we can expect various families of state with respect to their business value, data volatility, and fault-tolerance window. Each family needs to be treated differently. While durable messaging may be suitable for one, it may be overkill or underkill for another.</p>
<p>So, here&#8217;s what we&#8217;re going to be looking at:</p>
<ol>
<li>Business Value</li>
<li>Data Volatility</li>
<li>Fault-Tolerance Window</li>
</ol>
<h4>Business Value</h4>
<p>When talking about business value, I want to talk about what it means &#8220;not losing any messages&#8221;. The question is under what conditions will the messages not be lost, or rather, what are the threshold conditions where messages may start getting lost. If all our datacenters are nuked, we will lose data. It&#8217;s likely the business is OK with that (as much as can be expected under those circumstances). If a single server goes down, it&#8217;s likely the business would not be OK with losing messages containing financial data. However if a message requesting the health of a server were to get lost under those same conditions, that would probably be alright. In other words, what does that message represent in business terms.</p>
<h4>Data Volatility</h4>
<p><img style="margin: 0px 10px 0px 0px" height="150" src="http://www.classicdriver.com/upload/images/_de/3161/img02.jpg" width="270" align="left">Data volatility also has an impact. Let&#8217;s say that we&#8217;re building a financial trading system. The time that it takes us to respond to an event (message) that the cost of a certain financial instrument has changed, and the message that we send requesting to buy that security is critical. Let&#8217;s say that has to be done in under 10ms. Now, some failure has occurred preventing our message from reaching its destination for 20ms. What should we do with that message? Should we keep it around, making sure it doesn&#8217;t get lost? Not in this domain. On the contrary, that message should be thrown away as its &#8220;business lifetime&#8221; has been exceeded. Furthermore, even during that original period of 10ms, the use of durable messaging may make it close to impossible to maintain our response times.</p>
<h4>Fault-Tolerance Window</h4>
<p>These two topics feed into the third and more architectural one &#8211; fault-tolerance window: what period of time do we require fault tolerance, and with respect to how many (and what kind of) faults? This will lead us into an analysis of to how many machines do we need to copy a message before we release the calling thread. We&#8217;d also look at in which datacenters those machines reside. This will also impact (or be impacted by) the kinds of links we have to these datacenters if we want to maintain response times. These numbers will need to change when the system identifies a disaster &#8211; degrading itself to a lower level of fault-tolerance after a hurricane knocks out a datacenter, and returning to normal once it comes back up.</p>
<h4>Re-Evaluating Durable Messaging</h4>
<p>Durable messaging may be used at various points in each part of the solution, but we need to look at message size, the rate those messages are being written to disk, how fast the disk is, how much available disk we have (so we don&#8217;t make things worse in the case of degraded service), etc. Companies like Amazon also take into account disk failure rates, replacement rates (disks aren&#8217;t replaced <em>immediately</em> you know), and many other factors when making these decisions<img style="margin: 10px 0px 10px 10px;" height="231" alt="image" src="http://udidahan.weblogs.us/wp-content/uploads/image-thumb25.png" width="143" align="right" border="0"> </p>
<h4>Summary</h4>
<p>Our job as architects when designing the system is to find that cost-benefit balance for the various parts of the system according to these very applicative parameters. No, it&#8217;s not easy. No, cloud computing will not magically solve all of this for us. But, we are getting more technical tools to work with, operations staff is getting better at working with us in the design phase, and our thought processes more rigorous in dealing with the scary conditions of the real world. </p>
<p>To your question, Libor, as to why we didn&#8217;t eventually use durable messaging in our solution, the answer is that we solved the overall state management problem by setting up an applicative protocol with our partners which was resilient in the face of faults by using idempotent messages that could be resent as many times as necessary. You can read more about it <a href="http://udidahan.weblogs.us/2008/04/10/scalability-article-up-on-infoq/">here</a>. This solution isn&#8217;t viable for other kinds of interactions but was just what we needed to get the job done.</p>
<p>Hope that helps.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2008/07/17/durable-messaging-dilemmas/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>NServiceBus Performance</title>
		<link>http://www.udidahan.com/2008/05/21/nservicebus-performance/</link>
		<comments>http://www.udidahan.com/2008/05/21/nservicebus-performance/#comments</comments>
		<pubDate>Wed, 21 May 2008 07:08:05 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[ESB]]></category>
		<category><![CDATA[MSMQ]]></category>
		<category><![CDATA[Messaging]]></category>
		<category><![CDATA[NServiceBus]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Scalability]]></category>

		<guid isPermaLink="false">http://udidahan.weblogs.us/2008/05/21/nservicebus-performance/</guid>
		<description><![CDATA[I&#8217;ve gotten this question several times already but now companies are beginning to look for performance comparisons in making decisions around the use of nServiceBus. It&#8217;s often compared to straight WCF, BizTalk, and now Neuron ESB. In Sam&#8217;s recent post he posts to a case study of Neuron doing 28 million messages an hour. That&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve gotten this question several times already but now companies are beginning to look for performance comparisons in making decisions around the use of nServiceBus. It&#8217;s often compared to straight WCF, BizTalk, and now Neuron ESB. In Sam&#8217;s <a href="http://samgentile.com/blogs/samgentile/archive/2008/05/19/new-and-notable-243.aspx">recent post</a> he posts to a case study of Neuron doing 28 million messages an hour. That&#8217;s far more than I&#8217;ve ever heard quoted for BizTalk.</p>
<h3>Disclaimer</h3>
<p>Before giving some numbers, please keep in mind that high performance of system infrastructure does not necessarily by itself mean that the system above it is running that fast. For instance, you may have server heartbeats running really quickly but the time it takes to save a purchase order borders on a minute. So, please, take all benchmarks with a grain of salt, or two, or a whole shaker-full.</p>
<p>While I&#8217;m not at liberty to say on which specific domain/company these numbers were measured, I can say that we had the full gamut of &#8220;stateless services&#8221;, statefull services (sagas), number crunching, large data sets, many users, complex visualization, etc. Also, this wasn&#8217;t the largest installation of nServiceBus that I&#8217;m aware of, but its the one I have the most specific numbers for.</p>
<h3>Setup</h3>
<p>OK, so using the default nServiceBus distribution using MSMQ, on servers where the queue files themselves were on separate SCSI RAID disks, we were pumping around 1000 durable, transactionally processed messages per second, per server. That means that similar to the Neuron case, no messages would be lost in the case of a single fault per server per window (time to replace a failed disk set at 3 hours from failure, through detection, to replacement per site &#8211; but that&#8217;s more an operational staffing concern, not the technology itself). </p>
<p>So, that&#8217;s 3.6 million messages per hour per server, at full load. We had a total of 98 servers doing these kinds of processing, not including web servers, databases, etc. Keep in mind that web servers would be communicating with other servers using nServiceBus, but that would maybe be an unfair comparison to the Neuron numbers.</p>
<h3>Server Breakdown</h3>
<p>Anyway, the 48 number crunching servers (blade centers) we had were at full load, so we were pumping more than 170 million messages there. Keep in mind that those servers had a really fast backbone so weren&#8217;t held up by IO. Your environment may be different.</p>
<p>Another 30 (regular pizza boxes) were doing our sagas. Saga state was stored in a distributed in-memory &#8220;cache&#8221;, so once again IO wasn&#8217;t an issue for processing those messages. We were at about 70% utilization there, coming to just over 100 million messages an hour.</p>
<p>The last 20 were clustered boxes (fairly expensive) that handled the various nServiceBus distributor and timeout manager processes were at full load since they handled control messages for all the servers as well as dynamically routing the load. However, on those boxes we used much higher performance disks for the messages, since they had to feed everything else, capable of doing, on average, around 5000 messages a second. That adds up to 360 million messages an hour.</p>
<h3>Unnecessary Durability</h3>
<p>Later, we moved a bunch of messages that didn&#8217;t need all that durability and transactionality off the disks, pushing the total throughput over 1 billion messages an hour. That was about 100 million per hour durable, 900 million per hour non-durable. You can guess that we were left with plenty of IO to spare at that point while we weren&#8217;t yet pushing the limit of our memory.</p>
<p>One thing that&#8217;s important to understand is the size of the messages that didn&#8217;t require durability was less than 1MB, with most weighing in under 10KB. Also, since most of those messages were published, less state management was required around them, enabling us to further improve performance.</p>
<h3>Summary</h3>
<p>NServiceBus didn&#8217;t give us all that by itself. It was the result of skilled architects, developers, and operations staff working together for many iterations, deploying, monitoring, re-designing, etc. You need to understand your technology, your hardware, and your specific performance, availability, and fault-tolerance requirements if you want to get anywhere.</p>
<p>There&#8217;s no magic.</p>
<p>I didn&#8217;t see the number or kinds of servers involved in the Neuron case study so this wasn&#8217;t ever really a comparison. Nor or we talking about the same system here. </p>
<p>So, please, don&#8217;t base your decisions on arbitrary numbers. Spend some time setting up a scaled down version of your target architecture with all the relevant technologies and <em>measure</em>. Be aware that you want high performance end to end, not just of the messaging part. At times, it makes sense to actively throw away messages (of the non-durable, published kind) to help a server come online faster especially after a restart.</p>
<p>Thus ends the tale of another &#8220;benchmark&#8221;.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2008/05/21/nservicebus-performance/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Scalability Article up on InfoQ</title>
		<link>http://www.udidahan.com/2008/04/10/scalability-article-up-on-infoq/</link>
		<comments>http://www.udidahan.com/2008/04/10/scalability-article-up-on-infoq/#comments</comments>
		<pubDate>Fri, 11 Apr 2008 05:59:38 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Articles]]></category>
		<category><![CDATA[ESB]]></category>
		<category><![CDATA[Messaging]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Pub/Sub]]></category>
		<category><![CDATA[Scalability]]></category>

		<guid isPermaLink="false">http://udidahan.weblogs.us/2008/04/10/scalability-article-up-on-infoq/</guid>
		<description><![CDATA[I&#8217;ve published a new article on performance and scalability on InfoQ:
Spectacular Scalability with Smart Service Contracts

In this article, I attempt to debunk some of the myths around stateless-ness as the key to scalability.
Here&#8217;s how it starts:
It was a sunny day in June 2005 and our spirits were high as we watched the new ordering system [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve published a new article on performance and scalability on InfoQ:</p>
<blockquote><p><a href="http://www.infoq.com/articles/scale-with-service-contracts">Spectacular Scalability with Smart Service Contracts</a></p>
</blockquote>
<p>In this article, I attempt to debunk some of the myths around stateless-ness as the key to scalability.</p>
<p>Here&#8217;s how it starts:</p>
<blockquote><p>It was a sunny day in June 2005 and our spirits were high as we watched the new ordering system we&#8217;d worked on for the past 2 years go live in our production environment. Our partners began sending us orders and our monitoring system showed us that everything looked good. After an hour or so, our COO sent out an email to our strategic partners letting them know that they should send their orders to the new system. 5 minutes later, one server went down. A minute after that, 2 more went down. Partners started calling in. We knew that we wouldn&#8217;t be seeing any of that sun for a while.</p>
<p>The system that was supposed to increase the profitability of orders from strategic partners crumbled. The then seething COO emailed the strategic partners again, this time to ask them to return to the old system. The weird thing was that although we had servers to spare, just a few orders from a strategic customer could bring a server to its knees. The system could scale to large numbers of regular partners, but couldn&#8217;t handle even a few strategic partners.
<p>This is the story of what we did wrong, what we did to fix it, and how it all worked out.
<p><a href="http://www.infoq.com/articles/scale-with-service-contracts">Continue reading&#8230;</a></p>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2008/04/10/scalability-article-up-on-infoq/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>WCF Everywhere? Not on my watch.</title>
		<link>http://www.udidahan.com/2007/12/29/wcf-everywhere-not-on-my-watch/</link>
		<comments>http://www.udidahan.com/2007/12/29/wcf-everywhere-not-on-my-watch/#comments</comments>
		<pubDate>Sat, 29 Dec 2007 15:00:19 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Scalability]]></category>
		<category><![CDATA[WCF]]></category>

		<guid isPermaLink="false">http://udidahan.weblogs.us/2007/12/29/wcf-everywhere-not-on-my-watch/</guid>
		<description><![CDATA[ The other day I was at Juval&#8217;s presentation where the main message was WCF is a better .NET. In other words, if you use WCF on every one of your classes, you&#8217;ll benefit. I don&#8217;t know about you, but I&#8217;m quite wary of silver bullets &#8211; they tend to inflict quite a bit of [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://udidahan.weblogs.us/wp-content/uploads/silver_bullets.png" alt="silver bullets" style="border: 0px none ; margin: 0px 20px 20px" align="right" border="0" height="139" width="98" /></a> The other day I was at <a href="http://www.idesign.net/">Juval&#8217;s</a> presentation where the main message was WCF is a better .NET. In other words, if you use WCF on every one of your classes, you&#8217;ll benefit. I don&#8217;t know about you, but I&#8217;m quite wary of silver bullets &#8211; they tend to inflict quite a bit of pain when used indiscriminately. This post is my response to all the people who came up to me at the end of the presentation and wanted to know if I agreed with these far-reaching architectural statements.</p>
<p><a href="http://udidahan.weblogs.us/wp-content/uploads/oz1.jpg"><img src="http://udidahan.weblogs.us/wp-content/uploads/oz-thumb1.jpg" alt="oz" style="border: 0px none ; margin: 0px 20px 20px 0px" align="left" border="0" height="137" width="134" /></a>  First of all let me say that Juval is indeed a master presenter. The &#8220;looks like a class, walks like a class, quacks like a class&#8221; bit was excellent. I could tell that most people didn&#8217;t notice the speedy hands quickly deleting all attributes from the classes before the &#8220;looks like a class&#8230;&#8221; bit. At times, I got flashbacks from the Wizard of Oz &#8211; &#8220;pay no attention to the man behind the curtain&#8221;. If all attributes in WCF only went on the interfaces, then this might actually fly, but we all know that that&#8217;s not the case.</p>
<p>One of the interesting comparisons Juval made with WCF was the introduction of .NET. Few people in the audience seemed to remember (or maybe were just professionally younger than .NET&#8217;s 8 years), but when it came out .NET was marketed as being mainly about XML Web Services. Juval stated that this was done to play down the fact that .NET made the previous Windows programming technologies obsolete. He then drew the same conclusion about WCF &#8211; that it&#8217;s as much .NET 3.0 as .NET was the next version of MFC; besides being written in a language that resembles the previous technology, it&#8217;s really all different. I don&#8217;t think that anyone would argue the difference, but is it really a &#8220;plain .NET&#8221; killer?</p>
<p><a title="answer" name="answer"></a>The answer seemed to come around the overhead of WCF &#8211; yet Juval deftly deflected that issue with a demo showing WCF doing 200 calls a second. And everybody just bought it &#8211; I was shocked. That&#8217;s 5ms per call. If you actually take Juval&#8217;s advice and use WCF on all your classes, you&#8217;ve bought yourself one hell of a performance nightmare. Say you have around 20 of your objects involved in a sequence to handle a user action &#8211; not that many actually. With a 5ms lag per object interaction, that user action is going to take 100ms &#8211; not including any database or webservice stuff you might be doing. If you do that in a server environment, you&#8217;ll be doing roughly 10 concurrent users per core. And that&#8217;s not even doing any heavy calculations or anything. Moderately sized systems are running upwards of 1000 concurrent users &#8211; if they needed 100 cores (or dozens of servers) for that, I&#8217;m guessing that they&#8217;d be out of business.</p>
<p>Let&#8217;s cut this short &#8211; WCF everywhere doesn&#8217;t scale, doesn&#8217;t perform, isn&#8217;t maintainable, or testable either. In other words &#8211; don&#8217;t do it. I know Juval is a brilliant guy, and an amazing presenter &#8211; but I don&#8217;t believe he would be employing this with his own clients. This actually bears repeating. WCF is a fine technology for your application&#8217;s boundaries, but don&#8217;t be pushing it in.</p>
<h1>Don&#8217;t do it.</h1>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2007/12/29/wcf-everywhere-not-on-my-watch/feed/</wfw:commentRss>
		<slash:comments>26</slash:comments>
		</item>
		<item>
		<title>What Makes Smart Clients Safe?</title>
		<link>http://www.udidahan.com/2007/12/26/what-makes-smart-clients-safe/</link>
		<comments>http://www.udidahan.com/2007/12/26/what-makes-smart-clients-safe/#comments</comments>
		<pubDate>Wed, 26 Dec 2007 07:42:13 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Smart Client]]></category>
		<category><![CDATA[Threading]]></category>

		<guid isPermaLink="false">http://udidahan.weblogs.us/2007/12/26/what-makes-smart-clients-safe/</guid>
		<description><![CDATA[ After my recent post on using AOP for smart client development, my partner-in-crime, Arnon, suggested I explain a little bit more on the whole issue of multi-threading in the UI. This isn&#8217;t going to be another tired explanation of how you should only update controls on the main thread. This is going to be [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://udidahan.weblogs.us/wp-content/uploads/doctor-motion2.jpg"><img src="http://udidahan.weblogs.us/wp-content/uploads/doctor-motion2-thumb.jpg" style="border-width: 0px; margin: 0px 20px 20px" alt="doctor_motion2" align="right" border="0" height="244" width="150" /></a> After my <a href="http://udidahan.weblogs.us/2007/12/07/eureka-aop-is-the-final-piece-of-the-multi-threaded-smart-client-puzzle/">recent post</a> on using AOP for smart client development, my partner-in-crime, <a href="http://www.rgoarchitects.com/nblog/default.aspx">Arnon</a>, suggested I explain a little bit more on the whole issue of multi-threading in the UI. This isn&#8217;t going to be another tired explanation of how you should only update controls on the main thread. This is going to be a post on the challenges multi-threading brings and how to address them.</p>
<h3>Multiple Threads &#8211; Why?</h3>
<p>One of the properties of smart clients is that they should be able to work offline. Sometimes that means an explicit action of taking data and bringing it to the local machine so that the user can work on it, and other times it just has to do with the fact that wireless connectivity can be flaky. More interesting scenarios include the submission of batch jobs and receiving notification on when they complete. The bottom line is that the user should be able to continue doing their interactive work uninterrupted as all this is occurring.</p>
<p>While the user is disconnected, obviously the data they are working on is local &#8211; the client is not calling the server to perform the work on its behalf. However, in the flaky connectivity scenario, this happens all the time. In other words, the design should be the same for handling all scenarios. One thread for interacting with the user, and (at least) on other thread for handling the issues of connectivity. The one thing that is clear is that we are going to have data on the client with which the user interacts on one thread, and which the background thread will also be updating as notifications arrive from the server.</p>
<h3>Local Data and Multi-Threading &#8211; a Recipe for Disaster</h3>
<p>When multiple threads are working with the same data, unless some specific code is in that object to make it thread-safe, there&#8217;s a good chance that object will end up in an inconsistent state. This can be catastrophic if we&#8217;re talking about air traffic control systems, dispensing medication, factory floor automation, etc. The problem is that we can&#8217;t just lock down the entire system whenever something needs to be done. While in some cases I&#8217;ve seen projects make each object thread-safe, implementing some base class for handling locking, that doesn&#8217;t work between objects and results in deadlocks.</p>
<p>Just as an example of the multi-object problem, consider the doctor prescribing medication for a patient. Now, the data about a patient in a smart client is not all on the Patient Object &#8211; there are lists of connected test results, medication already being taken, which nurses and doctors have treated this patient so far, etc. As a test result gets pushed to the client from the server, a new doctor unfamiliar with the history of the patient orders the same test again. These two objects under Patient &#8211; TestRequest and TestResult are being acted upon by different threads. One of the goals of the system was to eliminate duplicate testing for patients &#8211; cited as costing the hospital chain millions of dollars a year. Good thing we addressed the cross-object multi-threaded locking thing properly <img src='http://www.udidahan.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<h3>Always Switch from Background to Foreground?</h3>
<p>One solution I&#8217;ve seen used successfully is to always change threads from background to foreground whenever an update comes in from the server. This works when you don&#8217;t have many updates or the work performed on the client as a result of an update doesn&#8217;t take long. Always keep in mind, though, the flaky connectivity scenario. What tends to happen is that server notifications bunch up and then hit the client all together. When this occurs, clients developed this way are rendered unusable.</p>
<p>It would seem like this solution isn&#8217;t valid because of the above, but don&#8217;t dismiss it so quickly. This is an easy solution to implement that may address your specific environment and, as such, be cost effective. A large part of the work I&#8217;ve been doing is to make the more complex environments just as easy to develop as these simpler ones.</p>
<h3>Infrastructure-level, Safe, Multi-Object Locking</h3>
<p>Luckily for us developers, in the .net framework there is a class that handles this for us &#8211; well, 2 actually: <a href="http://msdn2.microsoft.com/en-us/library/system.contextboundobject(VS.90).aspx">ContextBoundObject</a> and <a href="http://msdn2.microsoft.com/en-us/library/system.runtime.remoting.contexts.synchronizationattribute.aspx">SynchronizationAttribute</a>. When using these two classes, we can create something known as a <a href="http://www.ddj.com/architect/184405771">Synchronization Domain</a> which acts as a global lock for all objects belonging to the synchronization domain. What this means is that if the user thread is trying to add a test request object while the background thread is already creating a test result object, the user thread will block automatically until the background thread completes its work.</p>
<p>There is only one teensy-weensy problem &#8211; ContextBoundObjects are really heavy-weight. The last thing you want is having millions of these running around in your client &#8211; you&#8217;ll end up with a multi-threading safe unusable UI. Also, the creation of an object inheriting from ContextBoundObject takes quite a bit longer than a plain-old.net object. In other words, technology by itself will not solve our problems &#8211; we need some patterns for the correct use of the technology so that we can maintain a reasonable level of performance while taking care of safety.</p>
<h3>MVC and Threading &#8211; Controllers</h3>
<p>Regardless of which flavour of MVC you prefer (I&#8217;m in the Supervising Controller camp for smart clients), the logic controlling what goes on in the client is found in the controllers. What this means is that actions from the user as well as background notifications will need to go through these controllers. It is important that these controllers be thread-safe since they are state-full &#8211; managing which windows are open, which step in a given process a user is currently doing, etc.</p>
<p>The characteristics of these controller objects which make them best suited to inherit from ContextBoundObject are that there are only a handful of these objects at any point in time and that they are created at startup &#8211; they&#8217;re singletons (in the &#8220;only-one-of-them&#8221; sense of the word).</p>
<p>The only special thing that controllers need to do in terms of threading is to dispatch calls to view objects on the foreground thread, even if the thread currently running is the background thread. For example, popping up a &#8220;toast&#8221; that a test result has arrived when a notification from the server comes in.</p>
<p>These elements &#8211; inheriting from ContextBoundObject, use of the SynchronizationAttribute, and thread-switching can be pulled up in to a BaseController class:</p>
<div style="overflow: scroll; width: 100%">
<style type="text/css">.csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ }
.csharpcode pre { margin: 0em; }</p>
<p>.csharpcode .rem { color: #008000; }</p>
<p>.csharpcode .kwrd { color: #0000ff; }</p>
<p>.csharpcode .str { color: #006080; }</p>
<p>.csharpcode .op { color: #0000c0; }</p>
<p>.csharpcode .preproc { color: #cc6633; }</p>
<p>.csharpcode .asp { background-color: #ffff00; }</p>
<p>.csharpcode .html { color: #800000; }</p>
<p>.csharpcode .attr { color: #ff0000; }</p>
<p>.csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; }</p>
<p>.csharpcode .lnum { color: #606060; }</style>
<pre class="csharpcode"><span class="kwrd">using</span> System;
<span class="kwrd">using</span> System.ComponentModel;
<span class="kwrd">using</span> System.Runtime.Remoting.Contexts;

<span class="kwrd">namespace</span> ControllerFramework
{
    [Synchronization(SynchronizationAttribute.REQUIRED)]
    <span class="kwrd">public</span> <span class="kwrd">class</span> BaseController : ContextBoundObject
    {
        <span class="kwrd">protected</span> ISynchronizeInvoke invoker;
        <span class="kwrd">public</span> ISynchronizeInvoke Invoker
        {
            get { <span class="kwrd">return</span> invoker; }
            set { invoker = <span class="kwrd">value</span>; }
        }

        <span class="kwrd">protected</span> <span class="kwrd">void</span> MarshalToUiThread(Delegate toCall, <span class="kwrd">params</span> <span class="kwrd">object</span>[] parameters)
        {
            <span class="kwrd">if</span> (<span class="kwrd">this</span>.invoker == <span class="kwrd">null</span>)
                <span class="kwrd">return</span>;

            <span class="kwrd">if</span> (<span class="kwrd">this</span>.invoker.InvokeRequired)
                invoker.BeginInvoke(toCall, parameters);
            <span class="kwrd">else</span>
                toCall.DynamicInvoke(parameters);
        }
    }
}</pre>
</div>
<p>Well, I think that this is long enough for a single blog post. In the next instalment of this series I&#8217;ll be talking about how model objects and views fit into the multi-threaded smart client. After that, we&#8217;ll be seeing how service agents, messaging, and service contract design need to be done in this style. While all this blogging will be going on, I&#8217;ll be getting a software factory up that will tie all these patterns and frameworks together so that all developers will be able to write thread-safe, high-performance smart clients without needing a doctorate in computer science &#8211; not that I have one <img src='http://www.udidahan.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Questions? Comments? Thoughts?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2007/12/26/what-makes-smart-clients-safe/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>ASP.NET Async pages and tasks now supported by nServiceBus</title>
		<link>http://www.udidahan.com/2007/12/18/aspnet-async-pages-and-tasks-now-supported-by-nservicebus/</link>
		<comments>http://www.udidahan.com/2007/12/18/aspnet-async-pages-and-tasks-now-supported-by-nservicebus/#comments</comments>
		<pubDate>Tue, 18 Dec 2007 23:57:08 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[NServiceBus]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Presentations]]></category>

		<guid isPermaLink="false">http://udidahan.weblogs.us/2007/12/18/aspnet-async-pages-and-tasks-now-supported-by-nservicebus/</guid>
		<description><![CDATA[I&#8217;ve been getting quite a few requests to support the asynchronous programming model exposed by ASP.NET 2.0 to enable the higher levels of scalability afforded by its IO completion ports. Well, nServiceBus now supports it. You can find a sample in the &#8220;Samples&#8221; that demonstrates how to use PageAsyncTasks to complete work asynchronously.
If you&#8217;re interested in [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been getting quite a few requests to support the <a href="http://www.google.com/url?sa=t&amp;ct=res&amp;cd=1&amp;url=http%3A%2F%2Fmsdn.microsoft.com%2Fmsdnmag%2Fissues%2F05%2F10%2FWickedCode%2F&amp;ei=W1toR7qyDZfuwwHP27XZDQ&amp;usg=AFQjCNEiK65cU0ETSr0LVSoYkxg-wVCB1g&amp;sig2=MaOGPGOVFpG3Rbk4T-mdNw">asynchronous programming model </a>exposed by ASP.NET 2.0 to enable the higher levels of scalability afforded by its IO completion ports. Well, <a href="http://www.nServiceBus.com">nServiceBus</a> now supports it. You can find a sample in the &#8220;Samples&#8221; that demonstrates how to use PageAsyncTasks to complete work asynchronously.</p>
<p>If you&#8217;re interested in getting a kick-start with nServiceBus, I&#8217;ll be presenting a full day tutorial on it at <a href="http://qcon.infoq.com/london/conference/">QCon in London</a> on March 11th. <a href="http://qcon.infoq.com/london/presentation/Build+Scalable%2C+Maintainable%2C+Distributed+Enterprise+.NET+Solutions+with+nServiceBus">Here </a>are the full details :</p>
<p><strong>Title</strong>:</p>
<p>Build Scalable, Maintainable, Distributed Enterprise .NET Solutions with nServiceBus</p>
<p><strong>Description</strong>:</p>
<p>Despite the recent flood of technologies and releases, distributed enterprise .net solution development remains as hard as ever.</p>
<p>WCF and WF provide valuable runtime components, yet still leave open the risk of developers using the wrong combination of options and ending up with an unscalable solution.</p>
<p>In this tutorial, developers will learn the specific patterns necessary to achieve scalability, as well as use supporting open-source frameworks to enable parallel development (and debugging!) of service interfaces, layers, and domain models.</p>
<p>After delving in to asynchronous message design, long-running workflow state management, and transaction-boundary placement developers will be able to design, debug, and deploy their specific distributed systems.</p>
<p>&#8212;</p>
<p>Hope to see you there.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2007/12/18/aspnet-async-pages-and-tasks-now-supported-by-nservicebus/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Handling messages out of order</title>
		<link>http://www.udidahan.com/2007/12/15/handling-messages-out-of-order/</link>
		<comments>http://www.udidahan.com/2007/12/15/handling-messages-out-of-order/#comments</comments>
		<pubDate>Sat, 15 Dec 2007 23:22:24 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Availability]]></category>
		<category><![CDATA[Data Access]]></category>
		<category><![CDATA[Databases]]></category>
		<category><![CDATA[EDA]]></category>
		<category><![CDATA[NServiceBus]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Threading]]></category>

		<guid isPermaLink="false">http://udidahan.weblogs.us/2007/12/15/handling-messages-out-of-order/</guid>
		<description><![CDATA[I wanted to follow up on my recent post, &#8220;In order messaging a myth?&#8221; by showing the exact code that solves the issue. I have a podcast waiting to come online that deals with the specifics, so keep your eye out for that too.
The important thing to note is that if we just automatically return [...]]]></description>
			<content:encoded><![CDATA[<p>I wanted to follow up on my recent post, &#8220;<a href="http://udidahan.weblogs.us/2007/12/09/in-order-messaging-a-myth/">In order messaging a myth?</a>&#8221; by showing the exact code that solves the issue. I have a podcast waiting to come online that deals with the specifics, so keep your eye out for that too.</p>
<p>The important thing to note is that if we just automatically return the message to the queue, we may get &#8220;stuck&#8221; with that message if the first PolicyCreatedMessage never arrived. This opens us up to a Denial-of-Service attack by quite simply flooding us with a bunch of messages that never get cleaned up.</p>
<p>Anyway, the general idea is to first try the regular happy path, and only if we see that prerequisite data isn&#8217;t available, do we see if another thread may be working on that data. This is done by decreasing the isolation level of our transaction from the regular ReadCommitted to ReadUncommitted. This will enable our thread to see if some other thread inserted the policy in to the Policies table but hasn&#8217;t committed its transaction yet.</p>
<div style="overflow: auto; ">
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">public</span> <span style="COLOR: blue">class</span> <span style="COLOR: #2b91af">PolicyApprovedMessageHandler</span> : BaseDBMessageHandler&lt;PolicyApprovedMessage&gt;<o:p></o:p></font></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>{<o:p></o:p></font></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">public</span> <span style="COLOR: blue">override</span> <span style="COLOR: blue">void</span> Handle(PolicyApprovedMessage message)<o:p></o:p></font></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{<o:p></o:p></font></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">bool</span> policyExists = <span style="COLOR: blue">true</span>;<o:p></o:p></font></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><o:p><font size="3">&nbsp;</font></o:p></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">using</span> (<span style="COLOR: #2b91af">ISession</span> s = OpenSession())<o:p></o:p></font></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">using</span> (<span style="COLOR: #2b91af">ITransaction</span> tx = s.BeginTransaction(<span style="COLOR: #2b91af">IsolationLevel</span>.ReadCommitted))<o:p></o:p></font></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{<o:p></o:p></font></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Policy p = s.Get&lt;Policy&gt;(message.PolicyId);<o:p></o:p></font></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><o:p><font size="3">&nbsp;</font></o:p></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">if</span> (p != <span style="COLOR: blue">null</span>)<o:p></o:p></font></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{<o:p></o:p></font></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>p.Approve();<o:p></o:p></font></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>tx.Commit();<o:p></o:p></font></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}<o:p></o:p></font></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">else<o:p></o:p></span></font></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>policyExists = <span style="COLOR: blue">false</span>;<o:p></o:p></font></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}<o:p></o:p></font></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><o:p><font size="3">&nbsp;</font></o:p></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">if</span> (!policyExists) <span style="COLOR: green">// check to make sure<o:p></o:p></span></font></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">using</span> (<span style="COLOR: #2b91af">ISession</span> s = OpenSession())<o:p></o:p></font></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span><span style="COLOR: blue">using</span> (<span style="COLOR: #2b91af">ITransaction</span> tx = s.BeginTransaction(<span style="COLOR: #2b91af">IsolationLevel</span>.ReadUncommitted))<o:p></o:p></font></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{<o:p></o:p></font></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Policy p = s.Get&lt;Policy&gt;(message.PolicyId);<o:p></o:p></font></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><o:p><font size="3">&nbsp;</font></o:p></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">if</span> (p != <span style="COLOR: blue">null</span>) <span style="COLOR: green">// another thread hasn&#8217;t committed its tx yet, so try message again later<o:p></o:p></span></font></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">this</span>.bus.HandleCurrentMessageLater();<o:p></o:p></font></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">else<o:p></o:p></span></font></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">this</span>.bus.Return((<span style="COLOR: blue">int</span>)ErrorCodes.PolicyNotFound);<o:p></o:p></font></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}<o:p></o:p></font></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}<o:p></o:p></font></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 10pt"><span style="FONT-FAMILY: Consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"><font size="3"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>}</font></span><span style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%"><o:p></o:p></span></p>
</div>
<p>The next step will be how we take this code and make it generic, so that we don&#8217;t have write the same code over and over again for the different kinds of message handlers we have.</p>
<p>But that will have to wait until the next installment <img src='http://www.udidahan.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2007/12/15/handling-messages-out-of-order/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Object Builder &#8211; the place to fix system-wide threading bugs</title>
		<link>http://www.udidahan.com/2007/12/06/object-builder-the-place-to-fix-system-wide-threading-bugs/</link>
		<comments>http://www.udidahan.com/2007/12/06/object-builder-the-place-to-fix-system-wide-threading-bugs/#comments</comments>
		<pubDate>Thu, 06 Dec 2007 10:38:59 +0000</pubDate>
		<dc:creator>thesoftwaresimplist</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[NServiceBus]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Scalability]]></category>
		<category><![CDATA[Smart Client]]></category>
		<category><![CDATA[Threading]]></category>

		<guid isPermaLink="false">http://udidahan.weblogs.us/2007/12/06/object-builder-the-place-to-fix-system-wide-threading-bugs/</guid>
		<description><![CDATA[Last week I was at a client in their test lab and saw a strange bit of behavior. The system could be described as something like an air traffic control system, showing things moving around on a map. For just a second, a fraction of a second, one of the &#8220;planes&#8221; disappeared from the map [...]]]></description>
			<content:encoded><![CDATA[<p>Last week I was at a client in their test lab and saw a strange bit of behavior. The system could be described as something like an air traffic control system, showing things moving around on a map. For just a second, a fraction of a second, one of the &#8220;planes&#8221; disappeared from the map and then reappeared again. </p>
<p>When I asked if anybody else saw it, one of the developers said, &#8220;Yeah, that happens sometimes &#8211; but it fixes itself right after that.&#8221;</p>
<p>&#8220;What if the user sends a command to the server making use of that location?&#8221;, the PM asked. &#8220;Could that cause them to collide?&#8221;</p>
<p>You could hear a pin drop.</p>
<p>After everyone got passed the preliminary shock, we got down to work. I asked if I could look at the logs, but after more than an hour, I found nothing. No reason to explain the strange behavior. I suggested doing some more instrumentation so that whenever a location changed on the client-side entities, we&#8217;d write that to the log.</p>
<p>After that, we ran the system again in the lab under the expected load (several hundred things moving every second, and the user doing the expected activity) and didn&#8217;t notice anything. An intern &#8220;volunteered&#8221; to keep working the system while the rest of us went to lunch. When we came back, he told us that everything seemed to be working OK.</p>
<p>These <a href="http://en.wikipedia.org/wiki/Heisenbug#Heisenbugs">Heisenbugs</a> are the things that keep me up at night. </p>
<p>&#8220;Watching the system changes its behavior&#8221;, one of the older devs nodded his head sagely.</p>
<p>Just as we were about to leave the lab another one of the developers gave a shout, &#8220;It did it again!&#8221;. We quickly stopped the system. Opened the (rather huge) log files and looked for the latest entries.</p>
<p>There it was.</p>
<p>A context switch between setting the latitude and longitude of an entity.</p>
<p>That should not have happened. Not that context switches don&#8217;t happen, but rather that it should have been impossible by design. We had made use of synchronization domains and the appropriate patterns so that two threads could never concurrently be working on the same instance of an entity. The synchronization features baked in to <a href="http://www.nServiceBus.com">nServiceBus</a> had taken care of everything up to that point.</p>
<p>Before getting into the threading solution, I want to address a specific alternate patch that was deployed in the meantime:</p>
<p>The solution for the long/lat problem was simple &#8211; just make Location a value object and use a single setter for it rather than one for Latitide and another for Longitude. We were still worried about other bits of data that were correllated in the domain &#8211; things that couldn&#8217;t be solved the same way. </p>
<p>After getting 3 grizzled C++ veterans in the room, we did a code walkthrough of the threading model of nServiceBus. We went through the nitty gritty details of synchronization domains, how the Bus object was outside of the domain, why that was important for user experience, how the message handlers couldn&#8217;t be ContextBoundObjects because of the performance impact of creating and destroying them at a high rate, why they couldn&#8217;t just be singletons, why they still had to run in the synchronization domain, so that the UI thread couldn&#8217;t work on the same (or related) objects at the same time, etc, etc.</p>
<p>And then it hit me.</p>
<p>The bus was communicated directly with the message handlers.</p>
<p>After the Object Builder created the message handler, the bus dispatched the message to the handler directly. And since the bus was outside the synchronization domain, then the thread calling into the handler wouldn&#8217;t have locked the domain, leaving the UI thread open to go in and touch those very same objects.</p>
<p>They say that really understanding the problem is 90% of the solution. I&#8217;m hoping to meet them some day, because they&#8217;re really smart.</p>
<p>All that we needed to do was have the Object Builder dispatch the message to the handler instead of the bus &#8211; since the builder was configured to be in the synchronization domain (on the client side). Something as simple as just adding the method:</p>
<div style="border-right: black 1px solid; padding-right: 1em; border-top: black 1px solid; padding-left: 1em; padding-bottom: 0em; overflow: auto; border-left: black 1px solid; padding-top: 0em; border-bottom: black 1px solid; font-family: courier; background-color: beige">
void BuildAndDispatch(Type typeToBuild, string methodName, params object[] methodArgs);
</div>
<p>So, instead of the bus using this code:</p>
<div style="border-right: black 1px solid; padding-right: 1em; border-top: black 1px solid; padding-left: 1em; padding-bottom: 0em; overflow: auto; border-left: black 1px solid; padding-top: 0em; border-bottom: black 1px solid; font-family: courier; background-color: beige">
object handler = this builder.Build(messageHandlerType);<br />
MethodInfo method = messageHandlerType.GetMethod(&#8221;Handle&#8221;);<br />
method.Invoke(handler, messageToBeDispatched);
</div>
<p>It would do:</p>
<div style="border-right: black 1px solid; padding-right: 1em; border-top: black 1px solid; padding-left: 1em; padding-bottom: 0em; overflow: auto; border-left: black 1px solid; padding-top: 0em; border-bottom: black 1px solid; font-family: courier; background-color: beige">
this.builder.BuildAndDispatch(messageHandlerType, &#8220;Handle&#8221;, messageToBeDispatched);
</div>
<p>[Just FYI, this is now up on the <a href="http://sourceforge.net/projects/nservicebus">sourceforge site</a>]</p>
<p>We redeployed the system to the lab, ran all the functional, stress, load, etc tests and everything appeared to be stable. The system has been under scrutiny for the past 4 days by batteries of testers instructed specifically to look for those strage kinds of behavior. Other developers are running scripts on the log files looking for other kinds of context switches that may have been missed by the testers. I am happy to report that they haven&#8217;t found anything.</p>
<p>Not that this means that the problem isn&#8217;t there. We really can&#8217;t be sure. However, the PM has decided that we are stable enough to go into pilot mode &#8211; deploying into production beside the current system; having users work on both systems at the same time. I&#8217;m optimistic.</p>
<p>I&#8217;m personally involved in two more production-projects that are making use of <a href="http://www.nServiceBus.com">nServiceBus</a> in similarly high-end situations and we&#8217;ve never had these threading problems &#8211; now two years running.</p>
<p>That was an interesting week.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2007/12/06/object-builder-the-place-to-fix-system-wide-threading-bugs/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Asynchronous, High-Performance Login for Web Farms</title>
		<link>http://www.udidahan.com/2007/11/10/asynchronous-high-performance-login-for-web-farms/</link>
		<comments>http://www.udidahan.com/2007/11/10/asynchronous-high-performance-login-for-web-farms/#comments</comments>
		<pubDate>Sat, 10 Nov 2007 16:08:46 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Autonomous Services]]></category>
		<category><![CDATA[Availability]]></category>
		<category><![CDATA[Caching]]></category>
		<category><![CDATA[Data Access]]></category>
		<category><![CDATA[Databases]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[ESB]]></category>
		<category><![CDATA[NServiceBus]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Pub/Sub]]></category>
		<category><![CDATA[SOA]]></category>
		<category><![CDATA[Scalability]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Web Services]]></category>
		<category><![CDATA[Workflow]]></category>

		<guid isPermaLink="false">http://udidahan.weblogs.us/2007/11/10/asynchronous-high-performance-login-for-web-farms/</guid>
		<description><![CDATA[Often during my consulting engagements I run into people who say, &#34;some things just can&#8217;t be made asynchronous&#34; even after they agree about the inherent scalability that asynchronous communications pattern bring. One often-cited example is user authentication &#8211; taking a username and password combo and authenticating it against some back-end store. For the purpose of [...]]]></description>
			<content:encoded><![CDATA[<p>Often during my consulting engagements I run into people who say, &quot;some things just can&#8217;t be made asynchronous&quot; even after they agree about the inherent scalability that asynchronous communications pattern bring. One often-cited example is user authentication &#8211; taking a username and password combo and authenticating it against some back-end store. For the purpose of this post, I&#8217;m going to assume a database. Also, I&#8217;m not going to be showing more advanced features like ETags to further improve the solution.</p>
<h3>The Setup</h3>
<p>Just so that the example is in itself secure, we&#8217;ll assume that the password is one-way hashed before being stored. Also, given a reasonable network infrastructure our web servers will be isolated in the <a href="http://en.wikipedia.org/wiki/Demilitarized_zone_(computing)">DMZ</a> and will have to access some application server which, in turn, will communicate with the DB. There&#8217;s also a good chance for something like round-robin load-balancing between web servers, especially for things like user login.</p>
<p>Before diving into the meat of it, I wanted to preface with a few words. One of the commonalities I&#8217;ve found when people dismiss asynchrony is that they don&#8217;t consider a real deployment environment, or scaling up a solution to multiple servers, farms, or datacenters.</p>
<h3>The Synchronous Solution</h3>
<p>In the synchronous solution, each one of our web servers will be contacting the app server for each user login request. In other words, the load on the app server and, consequently, on the database server will be proportional to the number of logins. One property of this load is its data locality, or rather, the lack of it. Given that user U logged in, the DB won&#8217;t necessarily gain any performance benefits by loading all username/password data into memory for the same page as user U. Another property is that this data is very non-volatile &#8211; it doesn&#8217;t change that often.</p>
<p>I won&#8217;t go to far into the synchronous solution since its been <a href="http://www.michaelnygard.com/blog/2007/11/two_ways_to_boost_your_flaggin.html">analysed</a> numerous times before. The bottom line is that the database is the bottleneck. You could use sharding solutions. Many of the large sites have numerous read-only databases for this kind of data, with one master for updates &#8211; replicating out to the read-only replicas. That&#8217;s <a href="http://www.michaelnygard.com/blog/2007/11/two_quick_observations.html">great</a> if you&#8217;re using a nice cheap database like mySql (of LAMP), not so nice if you&#8217;re running Oracle or MS Sql Server.</p>
<p>Regardless of what you&#8217;re doing in your data tier, you&#8217;re there. Wouldn&#8217;t it be nice to close the loop in the web servers? Even if you are using Apache, that&#8217;s going to be less iron, electricity, and cooling all around. That&#8217;s what the asynchronous solution is all about &#8211; capitalizing on the low cost of memory to save on other things.</p>
<h3>The Asynchronous Solution</h3>
<p>In the asynchronous solution, we cache username/hashed-password pairs in memory on our web servers, and authenticate against that. Let&#8217;s analyse how much memory that takes:</p>
<p>Usernames are usually 12 characters or less, but let&#8217;s take an average of 32 to be sure. Using Unicode we get to 64 bytes for the username. Hashed passwords can run between 256 and 512 <em>bits</em> depending on the algorithm, divide by 8 and you have 64 bytes. That&#8217;s about 128 bytes altogether. So we can safely cache 8 million of these with 1GB of memory per web server. If you&#8217;ve got a million users, first of all, good for you <img src='http://www.udidahan.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Second, that&#8217;s just 128 MB of memory &#8211; relatively nothing even for a cheap 2GB web server. </p>
<p>Also, consider the fact that when registering a new user we can check if such a username is already taken at the web server level. That doesn&#8217;t mean it won&#8217;t be checked again in the DB to account for <a href="http://udidahan.weblogs.us/2007/01/22/realistic-concurrency/">concurrency issues</a>, but that the load on the DB is further reduced. Other things to notice include no read-only replicas and no replication. Simple. Our web servers are the &quot;replicas&quot;.</p>
<h3>The Authentication Service</h3>
<p>What makes it all work is the &quot;Authentication Service&quot; on the app server. This was always there in the synchronous solution. It is what used to field all the login requests from the web servers, and, of course, allowed them to register new users and all the regular stuff. The difference is that now it publishes a message when a new user is registered (or rather, is validated &#8211; all a part of the internal long-running workflow). It also allows subscribers to receive the list of all username/hashed-password pairs. It&#8217;s also quite likely that it would keep the same data in memory too.</p>
<p>The same message can be used to publish both single updates, and returning the full list when using <a href="http://www.NServiceBus.com">NServiceBus</a>. Let&#8217;s define the message:</p>
<div style="border-right: black 1px solid; padding-right: 1em; border-top: black 1px solid; padding-left: 1em; padding-bottom: 0em; overflow: auto; border-left: black 1px solid; padding-top: 0em; border-bottom: black 1px solid; font-family: courier; background-color: beige">
<p>[Serializable]      <br />public class UsernameInUseMessage : IMessage       <br />{       <br />&#160;&#160;&#160; private string username;       <br />&#160;&#160;&#160; public string Username       <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; get { return username; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; set { username = value; }       <br />&#160;&#160;&#160; } </p>
</p>
<p>&#160;&#160;&#160; private byte[] hashedPassword;      <br />&#160;&#160;&#160; public byte[] HashedPassword       <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; get { return hashedPassword; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; set { hashedPassword = value; }       <br />&#160;&#160;&#160; }       <br />} </p>
</p></div>
<p>And the message that the web server sends when it wants the full list:</p>
</p>
<div style="border-right: black 1px solid; padding-right: 1em; border-top: black 1px solid; padding-left: 1em; padding-bottom: 0em; overflow: auto; border-left: black 1px solid; padding-top: 0em; border-bottom: black 1px solid; font-family: courier; background-color: beige">
<p>[Serializable]      <br />public class GetAllUsernamesMessage : IMessage       <br />{ </p>
<p>} </p>
</p></div>
<p>And the code that the web server runs on startup looks like this (assuming constructor injection):</p>
<p>&#160;</p>
</p>
<div style="border-right: black 1px solid; padding-right: 1em; border-top: black 1px solid; padding-left: 1em; padding-bottom: 0em; overflow: auto; border-left: black 1px solid; padding-top: 0em; border-bottom: black 1px solid; font-family: courier; background-color: beige">
<p>public class UserAuthenticationServiceAgent      <br />{&#160; <br />&#160;&#160;&#160; public UserAuthenticationServiceAgent(IBus bus)&#160; <br />&#160;&#160;&#160; {&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; this.bus = bus;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; bus.Subscribe(typeof(UsernameInUseMessage));&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; bus.Send(new GetAllUsernamesMessages());       <br />&#160;&#160;&#160; } </p>
<p> }</p></div>
<p>And the code that runs in the Authentication Service when the GetAllUsernamesMessage is received:</p>
</p>
<p>&#160;</p>
</p>
<div style="border-right: black 1px solid; padding-right: 1em; border-top: black 1px solid; padding-left: 1em; padding-bottom: 0em; overflow: auto; border-left: black 1px solid; padding-top: 0em; border-bottom: black 1px solid; font-family: courier; background-color: beige">
<p>public class GetAllUsernamesMessageHandler : BaseMessageHandler&lt;GetAllUsernamesMessage&gt;      <br />{       <br />&#160;&#160;&#160; public override void Handle(GetAllUsernamesMessage message)       <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; this.Bus.Reply(Cache.GetAll&lt;UsernameInUseMessage&gt;());       <br />&#160;&#160;&#160; }       <br />}</p>
</p></div>
<p>&#160;</p>
<p>And the class on the web server that handles a UsernameInUseMessage when it arrives:</p>
</p>
<p>&#160;</p>
</p>
<div style="border-right: black 1px solid; padding-right: 1em; border-top: black 1px solid; padding-left: 1em; padding-bottom: 0em; overflow: auto; border-left: black 1px solid; padding-top: 0em; border-bottom: black 1px solid; font-family: courier; background-color: beige">
<p>public class UsernameInUseMessageHandler : BaseMessageHandler&lt;UsernameInUseMessage&gt;      <br />{       <br />&#160;&#160;&#160; public override void Handle(UsernameInUseMessage message)       <br />&#160;&#160;&#160; {&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; WebCache.SaveOrUpdate(message.Username, message.HashedPassword);&#160; <br />&#160;&#160;&#160; }       <br />}</p>
</p></div>
<p>When the app server sends the full list, multiple objects of the type UsernameInUseMessage are sent in one physical message to that web server. However, the bus object that runs on the web server dispatches each of these logical messages one at a time to the message handler above.</p>
<p>So, when it comes time to actually authenticate a user, this the web page (or controller, if you&#8217;re doing MVC) would call:</p>
</p>
<div style="border-right: black 1px solid; padding-right: 1em; border-top: black 1px solid; padding-left: 1em; padding-bottom: 0em; overflow: auto; border-left: black 1px solid; padding-top: 0em; border-bottom: black 1px solid; font-family: courier; background-color: beige">
<p>public class UserAuthenticationServiceAgent      <br />{       <br />&#160;&#160;&#160; public bool Authenticate(string username, string password)       <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; byte[] existingHashedPassword = WebCache[username];       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (existingHashedPassword != null)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return existingHashedPassword == this.Hash(password); </p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; return false;      <br />&#160;&#160;&#160; }       <br />}</p>
</p></div>
<p>&#160;</p>
<p>When registering a new user, the web server would of course first check its cache, and then send a RegisterUserMessage that contained the username and the hashed password.</p>
</p>
<div style="border-right: black 1px solid; padding-right: 1em; border-top: black 1px solid; padding-left: 1em; padding-bottom: 0em; overflow: auto; border-left: black 1px solid; padding-top: 0em; border-bottom: black 1px solid; font-family: courier; background-color: beige">
<p>[Serializable]      <br />[StartsWorkflow]       <br />public class RegisterUserMessage : IMessage       <br />{       <br />&#160;&#160;&#160; private string username;       <br />&#160;&#160;&#160; public string Username       <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; get { return username; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; set { username = value; }       <br />&#160;&#160;&#160; } </p>
</p>
<p>&#160;&#160;&#160; private string email;      <br />&#160;&#160;&#160; public string Email       <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; get { return email; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; set { email = value; }       <br />&#160;&#160;&#160; } </p>
</p>
<p>&#160;&#160;&#160; private byte[] hashedPassword;      <br />&#160;&#160;&#160; public byte[] HashedPassword       <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; get { return hashedPassword; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; set { hashedPassword = value; }       <br />&#160;&#160;&#160; }       <br />} </p>
</p></div>
<p>&#160;</p>
<p>When the RegisterUserMessage arrives at the app server, a new long-running workflow is kicked off to handle the process:</p>
</p>
<div style="border-right: black 1px solid; padding-right: 1em; border-top: black 1px solid; padding-left: 1em; padding-bottom: 0em; overflow: auto; border-left: black 1px solid; padding-top: 0em; border-bottom: black 1px solid; font-family: courier; background-color: beige">
<p>public class RegisterUserWorkflow :      <br />&#160;&#160;&#160; BaseWorkflow&lt;RegisterUserMessage&gt;, IMessageHandler&lt;UserValidatedMessage&gt;       <br />{       <br />&#160;&#160;&#160; public void Handle(RegisterUserMessage message)       <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; //send validation request to message.Email containing this.Id (a guid)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; // as a part of the URL       <br />&#160;&#160;&#160; } </p>
<p>&#160;&#160;&#160; /// &lt;summary&gt;      <br />&#160;&#160;&#160; /// When a user clicks the validation link in the email, the web server       <br />&#160;&#160;&#160; /// sends this message (containing the workflow Id)       <br />&#160;&#160;&#160; /// &lt;/summary&gt;       <br />&#160;&#160;&#160; /// &lt;param name=&quot;message&quot;&gt;&lt;/param&gt;       <br />&#160;&#160;&#160; public void Handle(UserValidatedMessage message)       <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; // write user to the DB </p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; this.Bus.Publish(new UsernameInUseMessage(      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; message.Username, message.HashedPassword));       <br />&#160;&#160;&#160; }       <br />}</p>
</p></div>
<p>That UsernameInUseMessage would eventually arrive at all the web servers subscribed.</p>
<h3>Performance/Security Trade-Offs</h3>
<p>When looking deeper into this workflow we realize that it could be implemented as two separate message handlers, and have the email address take the place of the workflow Id. The problem with this alternate, better performing solution has to do with security. By removing the dependence on the workflow Id, we&#8217;ve in essence stated that we&#8217;re willing to receive a UserValidatedMessage without having previously received the RegisterUserMessage. </p>
<p>Since the processing of the UserValidatedMessage is relatively expensive &#8211; writing to the DB and publishing messages to <em>all</em> web servers, a malicious user could perform a denial of service (<a href="http://en.wikipedia.org/wiki/Denial-of-service_attack">DOS</a>) attack without that many messages, thus flying under the radar of many detection systems. Spoofing a guid that would result in a valid workflow instance is much more difficult. Also, since workflow instances would probably be stored in some in-memory, replicated data grid the relative cost of a lookup would be quite small &#8211; small enough to avoid a DOS until a detection system picked it up.</p>
<h3>Improved Bandwidth &amp; Latency</h3>
<p>The bottom line is that you&#8217;re getting much more out of your web tier this way, rather than hammering your data tier and having to scale it out much sooner. Also, notice that there is much less network traffic this way. Not such a big deal for usernames and passwords, but other scenarios built in the same way may need more data. Of course, the time it takes us to log a user in is much shorter as well since we don&#8217;t have to cross back and forth from the web server (in the DMZ) to the app server, to the db server.</p>
<p>The important thing to remember in this solution is doing pub/sub. NServiceBus merely provides a simple API for designing the system around pub/sub. And publishing is where you get the serious scalability. As you get more users, you&#8217;ll obviously need to get more web servers. The thing is that you probably won&#8217;t need more database servers <em>just to handle logins</em>. In this case, you also get <a href="http://www.michaelnygard.com/blog/2007/11/architecting_for_latency.html">lower latency</a> per request since all work needed to be done can be done locally on the server that received the request. </p>
<h3>ETags make it even better</h3>
<p>For the more advanced crowd, I&#8217;ll wrap it up with the <a href="http://en.wikipedia.org/wiki/HTTP_ETag">ETags</a>. Since web servers do go down, and the cache will be cleared, what we can do is to write that cache to disk (probably in a background thread), and &quot;tag&quot; it with something that the server gave us along with the last UsernameInUseMessage we received. That way, when the web server comes back up, it can send that ETag along with its GetAllUsernamesMessage so that the app server will only send the changes that occurred since. This drives down network usage even more at the insignificant cost of some disk space on the web servers.</p>
<h3>And in closing&#8230;</h3>
<p>Even if you don&#8217;t have anything more than a single physical server today, and it acts as your web server and database server, this solution won&#8217;t slow things down. If anything, it&#8217;ll speed it up. Regardless, you&#8217;re much better prepared to scale out than before &#8211; no need to rip and replace your entire architecture just as you get 8 million Facebook users banging down your front door.</p>
<p>So, go check out <a href="http://www.NServiceBus.com">NServiceBus</a> and get the most out of your iron.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2007/11/10/asynchronous-high-performance-login-for-web-farms/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>[Podcast] Thread-Safe Asynchronous Smart Clients</title>
		<link>http://www.udidahan.com/2007/10/12/podcast-thread-safe-asynchronous-smart-clients/</link>
		<comments>http://www.udidahan.com/2007/10/12/podcast-thread-safe-asynchronous-smart-clients/#comments</comments>
		<pubDate>Fri, 12 Oct 2007 07:08:09 +0000</pubDate>
		<dc:creator>thesoftwaresimplist</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Ask Udi Podcast]]></category>
		<category><![CDATA[OO]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Smart Client]]></category>
		<category><![CDATA[Threading]]></category>

		<guid isPermaLink="false">http://udidahan.weblogs.us/2007/10/12/podcast-thread-safe-asynchronous-smart-clients/</guid>
		<description><![CDATA[In this podcast we&#8217;ll look at various patterns involved in creating MVC-based Smart Clients which communicate using asynchronous messaging and how to avoid threading problems there. 
Neil asks:

Hi Udi,
We&#8217;re building a smart client application that uses WCF for full-duplex communications with our server. This is the asynchronous communication you talk about in your podcast. The [...]]]></description>
			<content:encoded><![CDATA[<p>In this podcast we&#8217;ll look at various patterns involved in creating MVC-based Smart Clients which communicate using asynchronous messaging and how to avoid threading problems there. </p>
<p>Neil asks:</p>
<blockquote><p>
Hi Udi,</p>
<p>We&#8217;re building a smart client application that uses WCF for full-duplex communications with our server. This is the asynchronous communication you talk about in your podcast. The smart-client is based on the MVC pattern, where model objects raise events when they&#8217;re changed so that the views can update themselves.</p>
<p>What&#8217;s started happening recently is that the smart-client has been freezing-up on us intermittently. We don&#8217;t know how to debug this and are wondering if its an architectural problem.</p>
<p>Any help you can give would be most appreciated.</p>
<p>Neil
</p></blockquote>
<p><b>Download</b></p>
<p><a href="http://www.ddj.com/architect/202401468">Download via the Dr. Dobb&#8217;s site</a></p>
<p>Or download directly <a href="http://www.dobbsprojects.com/media/newengine/dynamp.php/071011ud01.mp3?podcast=071011ud01.mp3">here</a></p>
<p><b>Additional References</b></p>
<ul>
<li>Blog post on <A href="http://udidahan.weblogs.us/2007/04/04/occasionally-connected-systems-architecture/">Occasionally Connected Systems Architecture</A></li>
<li>Blog post on <A href="http://udidahan.weblogs.us/2007/09/28/objectbuilder-synchronization-features-needed-for-pubsub-ing-smart-clients/">ObjectBuilder synchronization features needed for pub/sub-ing Smart Clients</A></li>
</ul>
<p><b>Want more?</b></p>
<p>Check out the <a href="/ask-udi/">&#8220;Ask Udi&#8221; archives</a>.</p>
<p><b>Got a question?</b></p>
<p><a href="mailto:podcast@UdiDahan.com">Send Udi your question to answer on the show.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2007/10/12/podcast-thread-safe-asynchronous-smart-clients/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://www.dobbsprojects.com/media/newengine/dynamp.php/071011ud01.mp3?podcast=071011ud01.mp3" length="13030892" type="audio/mp3" />
		</item>
		<item>
		<title>Fetching Strategy NHibernate Implementation Available</title>
		<link>http://www.udidahan.com/2007/09/16/fetching-strategy-nhibernate-implementation-available/</link>
		<comments>http://www.udidahan.com/2007/09/16/fetching-strategy-nhibernate-implementation-available/#comments</comments>
		<pubDate>Mon, 17 Sep 2007 00:54:02 +0000</pubDate>
		<dc:creator>thesoftwaresimplist</dc:creator>
				<category><![CDATA[ADO.NET]]></category>
		<category><![CDATA[Caching]]></category>
		<category><![CDATA[Data Access]]></category>
		<category><![CDATA[Databases]]></category>
		<category><![CDATA[Dependency Injection]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Threading]]></category>

		<guid isPermaLink="false">http://udidahan.weblogs.us/2007/09/16/fetching-strategy-nhibernate-implementation-available/</guid>
		<description><![CDATA[A couple of months ago I put out a post discussing one way to implement custom fetching strategies. Anyway, I finally got around to putting my money where my mouth was&#8230;
So, I&#8217;ve implemented the pattern in NHibernate, adding the following method to ISession:
T Create&#60;T&#62;();
As well as adding the following interface to the NHibernate package:

  [...]]]></description>
			<content:encoded><![CDATA[<p>A couple of months ago I put out a <a href="http://udidahan.weblogs.us/2007/04/23/fetching-strategy-design/">post discussing one way to implement custom fetching strategies</a>. Anyway, I finally got around to putting my money where my mouth was&#8230;</p>
<p>So, I&#8217;ve implemented the pattern in NHibernate, adding the following method to ISession:</p>
<div style="border: solid black 1px; background-color:beige; padding: 0em 1em; overflow:auto; width:550; font-family:courier">T Create&lt;T&gt;();</div>
<p>As well as adding the following interface to the NHibernate package:</p>
<div style="border: solid black 1px; background-color:beige; padding: 0em 1em; overflow:auto; width:550; font-family:courier">
    public interface IFetchingStrategy&lt;T&gt;<br />
    {<br />
        ICriteria AddFetchJoinTo(ICriteria criteria);<br />
    }
</div>
<p>All this enables you to have a stronger separation between your service layer classes and your domain model class, as well as for you to express each service-level use case as a domain concept &#8211; an interface.</p>
<p>Once you have such an interface, you can create a fetching strategy for that use case and define exactly how deep of an object graph you want to load so that you only hit the DB once for that use case.</p>
<p>The nice thing is that its all configured with Spring. In other words, if you the entry for your fetching strategy class exists, you get the improved performance, if it doesn&#8217;t, you don&#8217;t. All without touching your service layer classes.</p>
<p>Just as an example, when I&#8217;m in the use case modeled by &#8220;ICustomer&#8221;, I want to get all the customer&#8217;s orders, and their orderlines. This would be done by having a class like this:</p>
<div style="border: solid black 1px; background-color:beige; padding: 0em 1em; overflow:auto; width:550; font-family:courier">
    public class CustomerFetchingStrategy : IFetchingStrategy&lt;ICustomer&gt;<br />
    {<br />
        public ICriteria AddFetchJoinTo(ICriteria criteria)<br />
        {<br />
            criteria.SetFetchMode(&#8221;orders&#8221;, FetchMode.Eager).<br />
                SetFetchMode(&#8221;orders.orderLines&#8221;, FetchMode.Eager);</p>
<p>            return criteria;<br />
        }<br />
    }
</p></div>
<p>And the configuration would look like this (as a part of the regular spring template):</p>
<div style="border: solid black 1px; background-color:beige; padding: 0em 1em; overflow:auto; width:550; font-family:courier">
      &lt;object id=&#8221;CustomerFetchingStrategy&#8221; type=&#8221;Domain.Persistence.CustomerFetchingStrategy, Domain.Persistence&#8221; /&gt;
</div>
<p>If you want to take a look at the full solution, you can find it here. For some reason, the combined file was too big for the upload on my blog so it&#8217;s split into two. Unzip both packages into the same directory. You&#8217;ll find a file called &#8220;db_scripts.sql&#8221; which contains the schema for the DB. Don&#8217;t forget to update your connection string in the &#8220;hibernate.cfg.xml&#8221;. If you&#8217;re looking for the changes I made to the NHibernate source, you can find it in the &#8220;Updated NHibernate Files&#8221; directory. The only real change is to the &#8220;SessionImpl.cs&#8221; file.</p>
<p><a href='http://udidahan.weblogs.us/wp-content/uploads/libraries.zip' title='libraries.zip'>Relevant NHibernate and Spring binaries</a>.</p>
<p><a href='http://udidahan.weblogs.us/wp-content/uploads/objectrelationalmappingdemo4.zip' title='objectrelationalmappingdemo.zip'>Source code of example</a>.</p>
<p>BTW, there is some intelligent thread-safe caching going on in SessionImpl now so that you get a much smaller performance hit (in terms of code that uses reflection) on subsequent usages of the same interfaces.</p>
<p>Let me know what you think.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2007/09/16/fetching-strategy-nhibernate-implementation-available/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>On rising data volumes</title>
		<link>http://www.udidahan.com/2007/08/20/on-rising-data-volumes/</link>
		<comments>http://www.udidahan.com/2007/08/20/on-rising-data-volumes/#comments</comments>
		<pubDate>Mon, 20 Aug 2007 07:40:47 +0000</pubDate>
		<dc:creator>thesoftwaresimplist</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Autonomous Services]]></category>
		<category><![CDATA[NServiceBus]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Scalability]]></category>
		<category><![CDATA[Space-Based Architecture]]></category>

		<guid isPermaLink="false">http://udidahan.weblogs.us/2007/08/20/on-rising-data-volumes/</guid>
		<description><![CDATA[Larry&#8217;s post Data Volumes Trumping Core Multiplication? Interesting Thought raises some interesting questions as to what will have a larger impact on the way we use program computers &#8211; rising data volumes or more cores:

It seems to me that nowadays we work more and more with data streams and not data sets. On a transaction-to-transaction [...]]]></description>
			<content:encoded><![CDATA[<p>Larry&#8217;s post <a href="http://www.knowing.net/PermaLink,guid,7075ce1b-fa59-4bca-926f-79fb45f9670e.aspx">Data Volumes Trumping Core Multiplication? Interesting Thought</a> raises some interesting questions as to what will have a larger impact on the way we use program computers &#8211; rising data volumes or more cores:</p>
<blockquote><p>
It seems to me that nowadays we work more and more with data streams and not data sets. On a transaction-to-transaction basis, I think it&#8217;s an uncommon application that uses more data than can fit into several gigabytes of RAM (obvious exception: multimedia data).
</p></blockquote>
<p>While data stream processing is the heartbeat of many verticals, I&#8217;m seeing another trend there as well &#8211; the use of historical data as a part of that data stream processing. Some people have begun calling this Complex Event-Stream Processing (CEP), and the analysts are already beginning to eat it up. Regardless, the problem is that it is difficult to hold all historical data in memory so that when events arrive we can process them quickly.</p>
<p>So, my bottom line is that we&#8217;re being hit on multiple fronts &#8211; both the rate at which we need to process events and the amount of data required to process each event. Multiple cores help a bit, but probably not enough to discount scaling up to more machines. All this at the end of the day points out that we should not treat multiple cores any differently than multiple machines.</p>
<p>So, we either need languages to handle this (<a href="http://www.erlang.org/">Erlang</a> for one) or possibly frameworks (<a href="http://www.NServiceBus.com">NServiceBus</a> is my contribution). All I know is that Layered (Tiered) Architectures won&#8217;t cut it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2007/08/20/on-rising-data-volumes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Space-Based Architecture – scalable, but not much to do with SOA</title>
		<link>http://www.udidahan.com/2007/06/20/space-based-architecture-%e2%80%93-scalable-but-not-much-to-do-with-soa/</link>
		<comments>http://www.udidahan.com/2007/06/20/space-based-architecture-%e2%80%93-scalable-but-not-much-to-do-with-soa/#comments</comments>
		<pubDate>Wed, 20 Jun 2007 21:31:25 +0000</pubDate>
		<dc:creator>thesoftwaresimplist</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Autonomous Services]]></category>
		<category><![CDATA[Availability]]></category>
		<category><![CDATA[EDA]]></category>
		<category><![CDATA[ESB]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Pub/Sub]]></category>
		<category><![CDATA[SOA]]></category>
		<category><![CDATA[Scalability]]></category>
		<category><![CDATA[Simplicity]]></category>
		<category><![CDATA[Space-Based Architecture]]></category>
		<category><![CDATA[Web Services]]></category>
		<category><![CDATA[Workflow]]></category>

		<guid isPermaLink="false">http://udidahan.weblogs.us/2007/06/20/space-based-architecture-%e2%80%93-scalable-but-not-much-to-do-with-soa/</guid>
		<description><![CDATA[Space-Based Architecture (or SBA for short) just might be in your future if your building large-scale distributed systems. By focusing on high-throughput and low latency, SBA joins messaging and in-memory data caching and adds a good measure of load partitioning. However, with the entire industry enamoured with SOA, what place is left for SBA?
Before going [...]]]></description>
			<content:encoded><![CDATA[<p>Space-Based Architecture (or SBA for short) just might be in your future if your building large-scale distributed systems. By focusing on high-throughput and low latency, SBA joins messaging and in-memory data caching and adds a good measure of load partitioning. However, with the entire industry enamoured with SOA, what place is left for SBA?</p>
<p>Before going too far ahead, you might want to take a look at my previous post <a href="http://udidahan.weblogs.us/2007/01/20/space-based-architectural-thinking/">&#8220;Space-Based Architectural Thinking</a>, or listen to my podcast <a href="http://udidahan.weblogs.us/2007/04/10/podcast-space-based-architectures-for-the-web/">Space-Based Architecture for the Web</a>. There&#8217;s also a 30 minute webcast online describing SBA more fully <a href="http://www.bejug.org/confluenceBeJUG/display/PARLEYS/SBA+-+Scalable+SOA">here</a>. I&#8217;m also going to try to stay away from things concerning Jini this time after already discussing <a href="http://udidahan.weblogs.us/2007/06/12/don%e2%80%99t-let-the-jini-out-of-the-bottle-on-soa/">the connection between Jini and SOA</a>, and the tradeoffs between two general approaches: <a href="http://udidahan.weblogs.us/2007/05/10/tasks-and-spaces-versus-messages-and-handlers/">Tasks and Spaces vs Message and Handlers</a>.</p>
<p>OK, so the issue of state-management is a big one. Everybody wants to work stateless, because it scales. The only problem is that the business processes that we are automating are long running, meaning that there are external systems or people involved. This makes these processes inherently stateful. So, we need a way to scale statefully &#8211; SBA gives us that. For some background on the &#8220;Shared Nothing Architecture&#8221;, I suggest reading <a href="http://www.dehora.net/journal/2004/04/interprocess_soa.html">this post on inter-process SOA</a> and <a href="http://www.zefhemel.com/archives/2004/09/01/the-share-nothing-architecture">this one as well</a>.</p>
<p>Availability also has to be handled, not only in terms of having enough servers online to handle the required load but in having all the data required to process each request be accessible. This has often been handled by the database using ACID transactions &#8211; durability being that which solved availability issues, but also hurting latency the most. The problem with saving the state of our long-running business processes/workflows in the database is the load and the responsiveness requirements. In many verticals &#8211; telcos, financial, and defense to name a few, we need millisecond level latency on each stage of the workflow. This is what leads SBA to the in-memory, replicated data grid.</p>
<p>Note that SBA only intends to take these workflows out of the database, and not anything else &#8211; especially not Master Data. The lifetime of these workflows is incredibly short compared to that of master data like customers and products. It will have much different backup strategies as well. In terms of load, these workflows will be heavy on reads and writes together in the same transactions, but quite low in terms of just reads. If we have workflows that perform work in parallel, we easily end up with concurrency requirements that make DBAs cringe under the barrage of short transactions. </p>
<blockquote style="background-color:white"><p>
If you&#8217;re worried that Workflow Foundation (WF) won&#8217;t scale because of the above, you needn&#8217;t be. You can (more or less easily) replace the persistence mechanism of WF with your own, saving your workflow instances to an in-memory replicated data grid.
</p></blockquote>
<p>By enabling the objects in the grid to call back into logic on your servers, you have, in essence, done messaging and more. The added benefit that SBA receives from this is a unification of technology between caching and messaging. This translates directly to savings when it comes time to cluster each of those technology&#8217;s environments.</p>
<p>Finally, if we can find an attribute in the incoming stream of messages that creates a nice even distribution, we can then partition our load between our servers by that key. This will work up to the point where the load per key increases beyond a single server&#8217;s capacity, and then we have to look at re-partitioning, a non-trivial problem. However, if we put objects in our grid that represent the master data, and tie them to our workflow instances with both of those tied to the key of our load, a smart infrastructure can make sure all that data is already resident on the server that is handling that piece of the load. That decreases latency even more since we no longer have to pay network roundtrips to collect all the data needed before we can process it. That&#8217;s a substantial advantage for the above verticals.</p>
<p>But all of this has nothing to do with SOA.</p>
<p>Sure, it&#8217;ll change how we implement our Services internally, but it has no impact on their interfaces or the top-level service decomposition. In the Java community, the word &#8220;service&#8221; is often used to describe the logic of a system. Great significance is placed on keeping these &#8220;services&#8221; simple, as in Plain-Old Java Objects. The fact of the matter is that the logic of the system should be simple and independent of other concerns like data access and communcations (a la Web Services), but that does not make it a service, not in the SOA sense.</p>
<p>For more information on what Services in SOA are like, check out this podcast on <a href="http://udidahan.weblogs.us/2006/08/28/podcast-business-and-autonomous-components-in-soa/">Business and Autonomous Components in SOA</a>. Actually, SBA will probably have the biggest impact on the way <a href="http://udidahan.weblogs.us/2007/06/02/podcast-using-autonomous-components-for-slas-in-soa/">autonomous components will handle service-level agreements</a>.</p>
<p>So, it appears that even with SOA, SBA has its place. The former dealing with business level agility, the latter dealing with all the technical aspects of supporting that agility. If you&#8217;re tasked with the designing the architecture of a scalable, available, high-throughput, low-latency distributed system, I&#8217;d strongly advise you to look at SBA &#8211; the technical value is overwhelming. Even if you don&#8217;t utilize all elements of SBA and choose the <a href="http://www.theserverside.com/tt/articles/article.tss?l=DistCompute">Master Worker Pattern</a> instead of load partitioning, you&#8217;ll find the technologies supporting SBA to be quite flexible in that respect.</p>
<p>Will Space-Based Architectures be a part of your future? I don&#8217;t know for sure, but they&#8217;re a most welcome part of my present.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2007/06/20/space-based-architecture-%e2%80%93-scalable-but-not-much-to-do-with-soa/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Performant and Explicit Domain Models</title>
		<link>http://www.udidahan.com/2007/06/04/performant-and-explicit-domain-models/</link>
		<comments>http://www.udidahan.com/2007/06/04/performant-and-explicit-domain-models/#comments</comments>
		<pubDate>Mon, 04 Jun 2007 20:31:34 +0000</pubDate>
		<dc:creator>thesoftwaresimplist</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Business Rules]]></category>
		<category><![CDATA[DDD]]></category>
		<category><![CDATA[Data Access]]></category>
		<category><![CDATA[Databases]]></category>
		<category><![CDATA[Dependency Injection]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[OO]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Simplicity]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Threading]]></category>

		<guid isPermaLink="false">http://udidahan.weblogs.us/2007/06/04/performant-and-explicit-domain-models/</guid>
		<description><![CDATA[Some Technical Difficulties

Ayende and I had an email conversation that started with me asking what would happen if I added an Order to a Customer’s &#8220;Orders&#8221; collection, when that collection was lazy loaded. My question was whether the addition of an element would result in NHibernate hitting the database to fill that collection. His answer [...]]]></description>
			<content:encoded><![CDATA[<h4>Some Technical Difficulties</h4>
<p style="padding: 0em 1em;">
Ayende and I had an email conversation that started with me asking what would happen if I added an Order to a Customer’s &#8220;Orders&#8221; collection, when that collection was lazy loaded. My question was whether the addition of an element would result in NHibernate hitting the database to fill that collection. His answer was a simple &#8220;yes&#8221;. In the case where a customer can have many (millions) of Orders, that’s just not a feasible solution. The technical solution was simple – just define the Orders collection on the Customer as &#8220;inverse=true&#8221;, and then to save a new Order, just write:
</p>
<div style="border: solid black 1px; padding: 0em 1em; background-color:beige; font-family:courier; ">session.Save( new Order(myCustomer) );</div>
<p style="padding: 0em 1em;">
Although it works, it’s not &#8220;DDD compliant&#8221; <img src='http://www.udidahan.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />
</p>
<p style="padding: 0em 1em;">
In Ayende’s post <a href="http://ayende.com/Blog/archive/2007/05/29/Architecting-for-Performance.aspx">Architecting for Performance</a> he quoted a part of our email conversation.  The conclusion I reached was that in order to design performant domain models, you need to know the kinds of data volumes you’re dealing with. It affects both internals and the API of the model – when can you assume cascade, and when not. It’s important to make these kinds of things explicit in the Domain Model’s API.
</p>
<h4>How do you make &#8220;transparent persistence&#8221; explicit?</h4>
<p style="padding: 0em 1em;">
The problem occurs around &#8220;transparent persistence&#8221;. If we were to assume that the Customer object added the Order object to its Orders collection, then we wouldn’t have to explicitly save orders it creates, so we would write service layer code like this:
</p>
<div style="border: solid black 1px; background-color:beige; padding: 0em 1em; overflow:auto; width:600; font-family:courier">
using (IDBScope scope = this.DbServices.GetScope(TransactionOption.On))<br />
{<br />
	IOrderCreatingCustomer c = this.DbServices.Get&lt;IOrderCreatingCustomer&gt;(msg.CustomerId);<br />
	c.CreateOrder(message.OrderAmount);</p>
<p>	scope.Complete();<br />
}
</p></div>
<p style="padding: 0em 1em;">
On the other hand, if we designed our Domain Model around the million orders constraint, we would need to explicitly save the order, so we would write service layer code like this:
</p>
<div style="border: solid black 1px; background-color:beige; padding: 0em 1em; overflow:auto; width:600; font-family:courier">
using (IDBScope scope = this.DbServices.GetScope(TransactionOption.On))<br />
{<br />
	IOrderCreatingCustomer c = this.DbServices.Get&lt;IOrderCreatingCustomer&gt;(msg.CustomerId);<br />
	IOrder o = c.CreateOrder(message.OrderAmount);<br />
	this.DbServices.Save(o);</p>
<p>	scope.Complete();<br />
}
</p></div>
<p style="padding: 0em 1em;">
But the question remains, how do we communicate these guidelines to service layer developers from the Domain Model? There are a number of ways, but it’s important to decide on one and use it consistently. Performance and correctness require it.
</p>
<h4>Solution 1: Explicitness via Return Type</h4>
<p style="padding: 0em 1em;">
The first way is a little subtle, but you can do it with the return type of the &#8220;CreateOrder&#8221; method call. In the case where the Domain Model wishes to communicate that it handles transparent persistence by itself, have the method return &#8220;void&#8221;. Where the Domain Model wishes to communicate that it will not handle transparent persistence, have the method return the Order object created.
</p>
<p style="padding: 0em 1em;">
Another way to communicate the fact that an Order has been created that needs to be saved is with events. There are two sub-ways to do so:
</p>
<h4>Solution 2: Explicitness via Events on Domain Objects</h4>
<p style="padding: 0em 1em;">
The first is to just define the event on the customer object and have the service layer subscribe to it. It’s pretty clear that when the service layer receives a &#8220;OrderCreatedThatRequiresSaving&#8221; event, it should save the order passed in the event arguments.
</p>
<p style="padding: 0em 1em;">
The second realizes that the call to the customer object may come from some other domain object and that the service layer doesn’t necessarily know what can happen as the result of calling some method on the aggregate root. The change of state as the result of that method call may permeate the entire object graph. If each object in the graph raises its own events, its calling object will have to propagate that event to its parent – resulting in defining the same events  in multiple places, and each object being aware of all things possible with its great-grandchild objects. That is clearly bad.
</p>
<h4>What [ThreadStatic] is for</h4>
<p style="padding: 0em 1em;">
So, the solution is to use thread-static events.
</p>
<p style="padding: 0em 1em;">
[Sidebar] Thread-static events are just static events defined on a static class, where each event has the ThreadStaticAttribute applied to it. This attribute is important for server-side scenarios where multiple threads will be running through the Domain Model at the same time. The easiest thread-safe way to use static data is to apply the ThreadStaticAttribute.
</p>
<h4>Solution 3: Explicitness via Static Events</h4>
<p style="padding: 0em 1em;">
Each object raises the appropriate static event according to its logic. In our example, Customer would call:
</p>
<div style="border: solid black 1px; background-color:beige; padding: 0em 1em; font-family:courier">
DomainModelEvents.RaiseOrderCreatedThatRequiresSavingEvent(newOrder);
</div>
<p style="padding: 0em 1em;">And the service layer would write:</p>
<div style="border: solid black 1px; background-color:beige; padding: 0em 1em; font-family:courier">
DomainModelEvents.OrderCreatedThatRequiresSaving +=<br />
	delegate(object sender, OrderEventArgs e) { this.DbServices.Save(e.Order); };
</div>
<p style="padding: 0em 1em;">
The advantage of this solution is that it requires minimal knowledge of the Domain Model for the Service Layer to correctly work with it. It also communicates that anything that doesn’t raise an event will be persisted transparently behind the appropriate root object.
</p>
<h4>Statics and Testability</h4>
<p style="padding: 0em 1em;">
I know that many of you are wondering if I am really advocating the use of statics. The problem with most static classes is that they hurt testability because they are difficult to mock out. Often statics are used as Facades to hide some technological implementation detail. In this case, the static class is an inherent part of the Domain Model and does not serve as a Facade for anything.
</p>
<p style="padding: 0em 1em;">
When it comes to testing the Domain Model, we don’t have to mock anything out since the Domain Model is independent of all other concerns. This leaves us with unit testing at the single Domain Class level, which is pretty useless unless we’re TDD-ing the design of the Domain Model, in which case we’ll still be fiddling around with a bunch of classes at a time. Domain Models are best tested using State-Based Testing; get the objects into a given state, call a method on one of them, assert the resulting state. The static events don’t impede that kind of testing at all.
</p>
<h4>What if we used Injection instead of Statics?</h4>
<p style="padding: 0em 1em;">
Also, you’ll find that each Service Layer class will need to subscribe to all the Domain Model’s events, something that is easily handled by a base class. I will state that I have tried doing this without a static class, and injecting that singleton object into the Service Layer classes, and in that setter having them subscribe to its events. This was also pulled into a base class. The main difference was that the Dependency Injection solution required injecting that object into Domain Objects as well. Personally, I’m against injection for domain objects. So all in all, the static solution comes with less overhead than that based on injection.
</p>
<h4>Summary</h4>
<p style="padding: 0em 1em;">
In summary, beyond the &#8220;technical basics&#8221; of being aware of your data volumes and designing your Domain Model to handle each use case performantly, I’ve found these techniques useful for designing its API as well as communicating my intent around persistence transparency. So give it a try. I’d be grateful to hear your thoughts on the matter as well as what else you’ve found that works.
</p>
<p><u style="padding: 0em 1em;">Related posts:</u></p>
<ul style="padding: 0em 1em;">
<li>
<a href="http://udidahan.weblogs.us/2007/04/23/fetching-strategy-design/">Fetching Strategy Design</a> &#8211; showing how to separate the concern of eager loading from both your Domain Model and your Service Layer.
</li>
<li>
<a href="http://udidahan.weblogs.us/2007/03/06/better-domain-driven-design-implementation/">Better Domain-Driven Design Implementation</a> &#8211; showing the basics of how valuable interfaces between your Domain Model and the Service Layer can be.
</li>
<li>
<a href="http://udidahan.weblogs.us/2007/04/15/lazy-loading-and-how-messaging-fixes-everything-again/">Lazy Loading, and how messaging fixes everything again</a> &#8211; describing the advantage of O/R mapping your message classes as well.
</li>
<li>
<a href="http://udidahan.weblogs.us/2007/03/28/query-objects-vs-methods-on-a-repository/">Query Objects vs Methods on a Repository</a> &#8211; discussing the scalability (in terms of number of developers and queries) of Query Objects.
</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2007/06/04/performant-and-explicit-domain-models/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>BizTalk and Performance</title>
		<link>http://www.udidahan.com/2007/05/02/biztalk-and-performance/</link>
		<comments>http://www.udidahan.com/2007/05/02/biztalk-and-performance/#comments</comments>
		<pubDate>Wed, 02 May 2007 08:04:20 +0000</pubDate>
		<dc:creator>thesoftwaresimplist</dc:creator>
				<category><![CDATA[BizTalk]]></category>
		<category><![CDATA[ESB]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Scalability]]></category>

		<guid isPermaLink="false">http://udidahan.weblogs.us/2007/05/02/biztalk-and-performance/</guid>
		<description><![CDATA[I know I bad-talk BizTalk a lot, but I do it somewhat tongue-in-cheek and to get a rise out of people. BizTalk is a tool, something of a swiss army knife, you know, those huge, honking ones that have everything but the kitchen sink in them. One of the main areas where BizTalk gets a [...]]]></description>
			<content:encoded><![CDATA[<p>I know I bad-talk BizTalk a lot, but I do it somewhat tongue-in-cheek and to get a rise out of people. BizTalk is a tool, something of a swiss army knife, you know, those huge, honking ones that have everything but the kitchen sink in them. One of the main areas where BizTalk gets a bad rap is in performance and <a href="http://udidahan.weblogs.us/category/scalability/">scalability</a>. On the other hand, the number of systems that I come in to assist with performance issues, that don&#8217;t use BizTalk, is still quite large. A systematic approach is needed in all cases.</p>
<p>I ran into another <a href="http://blogs.msdn.com/ewanf/archive/2007/05/01/biztalk-performance-useful-technique-to-baseline-your-infrastructure.aspx">BizTalk optimization story online</a> that once again points out that disk IO is a good first place to look, as I wrote about in my <a href="http://udidahan.weblogs.us/2007/04/30/database-performance-optimization/">Database performance optimization article</a>.</p>
<p>In closing, you need to be aware of the full environment. For instance, in BizTalk, it&#8217;s not just about messages per second. Session contention (multiple parties hitting the same session) can just lock things up tighter than, well, a tight thing. Designing for these things &#8220;up front&#8221; <gasp/> can save you <i>very</i> costly rewrites later.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2007/05/02/biztalk-and-performance/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Database performance optimization</title>
		<link>http://www.udidahan.com/2007/04/30/database-performance-optimization/</link>
		<comments>http://www.udidahan.com/2007/04/30/database-performance-optimization/#comments</comments>
		<pubDate>Mon, 30 Apr 2007 11:12:20 +0000</pubDate>
		<dc:creator>thesoftwaresimplist</dc:creator>
				<category><![CDATA[Availability]]></category>
		<category><![CDATA[Data Access]]></category>
		<category><![CDATA[Databases]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Scalability]]></category>

		<guid isPermaLink="false">http://udidahan.weblogs.us/2007/04/30/database-performance-optimization/</guid>
		<description><![CDATA[I&#8217;ve been doing quite a bit of consulting these past weeks around performance issues for database intensive systems. The fact that we use O/R Mapping makes the business logic possible to get right (using the Domain Model Pattern), but adds another dimension to the performance optimization &#8211; primarily around limiting the number of roundtrips to [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been doing quite a bit of consulting these past weeks around performance issues for database intensive systems. The fact that we use <a href="/category/nhibernate/">O/R Mapping</a> makes the business logic possible to get right (using the <a href="http://udidahan.weblogs.us/2007/04/21/domain-model-pattern/">Domain Model Pattern</a>), but adds another dimension to the performance optimization &#8211; primarily around limiting the number of roundtrips to the database.</p>
<p>However, in the truly large scale scenarios, that isn&#8217;t enough.</p>
<p>On of my customers is having to scale up from 500 concurrent users to 50,000. You need to get seriously close to the metal to handle that. Here&#8217;s a great post on <a href="http://blogs.smugmug.com/don/2007/04/27/the-perfect-db-storage-array/">the kind of hardware storage considerations</a> I went through that I went through there. Of course, sometimes a database is just the wrong hammer for your screw &#8211; sometimes what you really need is a <a href="http://udidahan.weblogs.us/2007/01/20/space-based-architectural-thinking/">space</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2007/04/30/database-performance-optimization/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Fear those Tiers</title>
		<link>http://www.udidahan.com/2007/03/20/fear-those-tiers/</link>
		<comments>http://www.udidahan.com/2007/03/20/fear-those-tiers/#comments</comments>
		<pubDate>Tue, 20 Mar 2007 20:04:44 +0000</pubDate>
		<dc:creator>thesoftwaresimplist</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Scalability]]></category>
		<category><![CDATA[Web Services]]></category>

		<guid isPermaLink="false">http://udidahan.weblogs.us/2007/03/20/fear-those-tiers/</guid>
		<description><![CDATA[Published as a part of the International Association of Software Architects (IASA) Skills Library.
Summary: I was horrified. My beautiful tiered architecture was buckling under the stress tests – at one tenth of the expected load of the system. And this was quality hardware, not the regular junk we scrapped together in most test labs, after [...]]]></description>
			<content:encoded><![CDATA[<p>Published as a part of the <a href="http://www.iasahome.org">International Association of Software Architects</a> (IASA) <a href="http://www.iasahome.org/web/home/skillset">Skills Library</a>.</p>
<p><b>Summary:</b> I was horrified. My beautiful tiered architecture was buckling under the stress tests – at one tenth of the expected load of the system. And this was quality hardware, not the regular junk we scrapped together in most test labs, after all, this was the company’s flagship project. And I began seeing my once-bright career flashing before my eyes. The only redeeming thing about this situation was that I had learned the hard way to do performance tests early in the project, and that there might still be enough time to save the situation. A couple months later things were back on track but I’ll never forget the feeling I had back then – “All the big vendors are pushing this exact architecture. How could this be happening?” Since then, I’ve learned that tiers and networks are not to be taken lightly in any architecture and this article chronicles my journey, and how I got to a robust and scalable architecture. </p>
<p><a href="http://msdn.microsoft.com/en-us/library/cc168629.aspx">Continue reading.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2007/03/20/fear-those-tiers/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>BizTalk&#8217;s as fast as they come (or is that go?)</title>
		<link>http://www.udidahan.com/2005/05/05/biztalks-as-fast-as-they-come-or-is-that-go/</link>
		<comments>http://www.udidahan.com/2005/05/05/biztalks-as-fast-as-they-come-or-is-that-go/#comments</comments>
		<pubDate>Thu, 05 May 2005 22:19:18 +0000</pubDate>
		<dc:creator>thesoftwaresimplist</dc:creator>
				<category><![CDATA[BizTalk]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Scalability]]></category>
		<category><![CDATA[Web Services]]></category>

		<guid isPermaLink="false">http://wp_630.weblogs.us/archives/191</guid>
		<description><![CDATA[Aaron Skonnard is blogging quite a bit about BizTalk these days. <a href="http://pluralsight.com/blogs/aaron/archive/2005/04/25/7717.aspx">An earlier post </a>that caught my eye quoted Mike Woods, the Sr. Technical Product Manager on the BizTalk team:

"... Finally on performance; if you're truly seeing 1 transaction per second then something isn't right. The SOAP adapter and heavy use of orchestration will knock your transaction rates down. Depending on what you're doing you should be able to get that up over a hundred Tx/sec. on a well tuned BizTalk server farm."

Isn't one of the major selling points of BizTalk the whole webservices thing (SOAP) and the ability to express complex workflow (orchestration)? If it can't do these things at a high transaction rate, then why do I need it? If the logic is simple, why don't I just hand code it? I could probably get over 100 Tx/s on a single server, let alone "a well tuned ... server farm".]]></description>
			<content:encoded><![CDATA[<p>Aaron Skonnard is blogging quite a bit about BizTalk these days. <a href="http://pluralsight.com/blogs/aaron/archive/2005/04/25/7717.aspx">An earlier post </a>that caught my eye quoted Mike Woods, the Sr. Technical Product Manager on the BizTalk team:</p>
<p>&#8220;&#8230; Finally on performance; if you&#8217;re truly seeing 1 transaction per second then something isn&#8217;t right. The SOAP adapter and heavy use of orchestration will knock your transaction rates down. Depending on what you&#8217;re doing you should be able to get that up over a hundred Tx/sec. on a well tuned BizTalk server farm.&#8221;</p>
<p>Isn&#8217;t one of the major selling points of BizTalk the whole webservices thing (SOAP) and the ability to express complex workflow (orchestration)? If it can&#8217;t do these things at a high transaction rate, then why do I need it? If the logic is simple, why don&#8217;t I just hand code it? I could probably get over 100 Tx/s on a single server, let alone &#8220;a well tuned &#8230; server farm&#8221;.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2005/05/05/biztalks-as-fast-as-they-come-or-is-that-go/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
