Indigo

Interested in Performance?

Monday, October 6th, 2008

Distributed applications are tricky. The internet is a fickle beast that will lost data at will and run counter to many intuitions. Getting distributed applications to run smoothly and performant at scale is particularly difficult.  There isn’t a single "go fast" silver bullet, rather it’s more of an art. At PDC this year you’ll have a great opportunity to learn about the Zen of WCF Performance and Scale at Nicholas Allen’s lunch session. Enjoy!

WCF talks at PDC

Friday, October 3rd, 2008

Matt posted a great description of the WCF (and WF) talks we’re giving at PDC.

In particular there are two sessions that I’d like to call out.

The first is Ed Pinto’s session, where you’ll find out about the significant investments we’ve made to improve the WCF authoring experience:

WCF 4.0: Building WCF Services with WF in Microsoft .NET 4.0.

Eliminate the tradeoff between ease of service authoring and performant, scalable services. Hear about significant enhancements in Windows Communication Foundation (WCF) 4.0 and Windows Workflow Foundation (WF) 4.0 to deal with the ever increasing complexity of communication. Learn how to use WCF to correlate messages to service instances using transport, context, and application payloads. See how the new WF messaging activities enable the modeling of rich protocols. Learn how WCF provides a default host for workflows exposing features such as distributed compensation and discovery. See how service definition in XAML completes the union of WF and WCF with a unified authoring experience that simplifies configuration and is fully integrated with IIS activation and deployment.

Once you’ve built your services, you will need to deploy, host, and manage them.  Windows Server "Dublin" handles this complexity, and Dan Eshner will unveil the details here:

Hosting Workflows and Services

Hear about extensions being made to Windows Server to provide a feature-rich middle-tier execution and deployment environment for Windows Workflow Foundation (WF) and Windows Communication Foundation (WCF) applications. Learn about the architecture of this new extension, how it works, how to take advantage of it, and the features it provides that simplify deployment, management, and troubleshooting of workflows and services.

PDC 2008

Monday, September 15th, 2008

I’ve gone dark on the technical side of this blog for two main reasons:

  1. Most of what I’m working on hasn’t been publicly disclosed
  2. I’m prepping for PDC 2008 where I can finally discuss the past 2 years of my life without an NDA :)

If you want to see the latest and greatest Microsoft technologies that we’ve been cooking up, register now, and then mark your schedule for my talk:

Windows Workflow Foundation 4.0: A First Look

Programs coordinate work. The code for coordination and state management often obscures a program’s purpose. Learn how programming with Windows Workflow Foundation (WF) 4.0 provides clarity of intent while preserving the functional richness of the .NET framework. See how easy it is to build workflows with the new Visual Studio workflow designer. Learn about text-based authoring options for WF. Hear how WF integrates well with other Microsoft technologies (WCF, WPF, ASP.NET). If you’ve looked at WF before, come and see the changes to data flow, composition, and new control flow styles. Significant improvements to usability, composability, and performance make Workflow a great fit for a broad range of solutions on both the client and the server.

Other great (and related) talks include Doug Purdy’s Lap Around Oslo, Matt’s Building WF Activities session, and Ed’s chocolate & peanut butter talk on WCF+WF.

41 days and counting…

Asynchronicity, OneWay, and WCF

Wednesday, August 6th, 2008

I’ve recently encountered some confusion around the behavior of one-way operations in WCF that I’m going to try and clear up.  In particular, developers are under the impression that a one-way operation == a non-blocking call. However, this is not necessarily the case. A one-way operation means that we will call the underlying channel in a "one-way manner".  For IOutputChannel/IDuplexChannel, this maps to channel.Send(). For IRequestChannel this maps to channel.SendRequest() followed by a check for a null response.

Now, sometimes the underlying channel can complete immediately (UDP will drop the packet if the network is saturated, TCP may copy bytes into a kernel buffer if there’s room, etc). However, depending on the amount of data transmitted and the number of simultaneous calls to a proxy, you will often see blocking behavior. HTTP, TCP, and Pipes all have throttling built into their network protocols.

If this isn’t desirable, there are a few alternatives depending on your application design. First off, if you want a truly non-blocking call, you should call channel.BeginSend/client.BeginXXXX (i.e. generate an async proxy). This is step one if you want non-blocking calls. With an asynchronous proxy, we will always be non-blocking from a thread perspective (which is always my recommendation for middle tier solutions, though there’s some quota coordination necessary to avoid flooding outgoing sockets).

For one-way operations, when your async callback is signaled it means that the channel stack has "successfully put the message on the wire". When this happens depends on your channel stack:

  • TCP signals when the socket.[Begin]Send() of the serialized message has completed (either because it’s been buffered by the kernel or put onto the NIC)
  • Pipes are a similar process (NT Named Pipes work similarly to TCP under the covers but without the packet loss)
  • MSMQ signals when the Message has been transferred successfully to the queue manager
  • HTTP signals when we’ve received an empty response. The only other alternative would be to remove all guarantees (and have to arbitrarily propagate the exception through some other call or thread). Trust me, this is better
  • UDP will complete when the UDP socket send completes (which is effectively instantaneous)

For two-way operations, when your async callback is signaled it means that the channel stack has "successfully put the message on the wire and then received a correlated response".

Asynchronous operations can be tricky, and can often get you into flooding trouble when used incorrectly. So be careful, use quotas to manage your flow control, and always remember that the internet is not a big truck; it is a series of tubes and sometimes they get clogged. And you shouldn’t try to fight the clogs by pouring more data down the tubes :)

WF/WCF July MSDN Webcasts

Tuesday, July 1st, 2008

Starting last month, MSDN put together a regular series of webcasts on WCF and WF (focusing on .Net 3.5).  Here are the talks being broadcast in July:

July 7th, 10:00AM (PST)
Transactional Windows Communication Foundation Services with Juval Lowy

July 9th, 10:00AM (PST)
Using Windows Workflow Foundation to Build Services with Jon Flanders

July 11th, 10:00AM (PST)
WCF Extensibility Deep Dive with Jesus Rodriguez

July 18th, 10:00AM (PST)
SharePoint Server and WCF with Joe Klug

WsDualHttp and Faults

Tuesday, May 6th, 2008

The other day a customer was sending unauthenticated messages to a service and the requests were timing out over WsDualHttp. When using WsHttpBinding or NetTcpBinding, the customer received an authentication MessageFault.  Why was there no Fault returned over WsDualHttpBinding?

The reason has to do with securing composite-duplex channels. WsDualHttp uses two HTTP connections to provide its duplex nature, and messages are correlated between these two connections based on WS-Addressing (ReplyTo/MessageId).  Because of this, the server behavior is entirely dependent on data received from the client. If this client is malicious, then he can cause the server to do a couple of things:

  • Initiate arbitrary outbound connections
  • Cause a "bouncing DOS" attack. For example, consider a server A that can send messages to server B that’s behind a firewall. Suppose that client C can send messages to A, but cannot send messages directly to server B (due to the firewall). Now suppose that the client sends a badly secured message to server A, with a ReplyTo equal to server B. If we send back a fault for unsecured messages over WsDualHttp, this would result in C being able to DOS server B due to bounce-assistance from server A.

In addition, since these are two one-way channels, the HTTP response (202 Accepted) has already returned prior to the Security channel (or any higher-layer in the channel/dispatcher stack) being called. So we cannot simply piggy-back the fault over the HTTP back channel.

WCF and TIBCO

Wednesday, April 30th, 2008

Integration has arrived!

http://www.tibco.com/company/news/releases/2008/press900.jsp

When to use Async Service Operations

Tuesday, April 29th, 2008

I was recently asked about the motivation for choosing asynchronous service operations in WCF (i.e. [OperationContract(AsyncPattern = true)]).

If you have an operation that is blocking (accessing SQL, Channels, etc) then you should use AsyncPattern=true.  That way you’ll free up whatever thread we’re using to call your operation from. The general idea is that if you have a blocking call then you should use the async version and it should transparently play well with us.

Put another way: if you are calling a method that returns an AsyncResult (i.e. you’re accessing SQL, or using sockets, files, or channels), then you can wrap that IAsyncResult and return it from the BeginXXX call (or return the raw asyncresult depending on your scenario).

If you aren’t doing something that’s "natively async", then you shouldn’t be using AsyncPattern=true. That is, you shouldn’t just create a thread just for the sake of performing "background work" as part of an asynchronous operation. Note that it is legitimate to spawn a thread because your operation happens to kick off work that is outside of its completion scope (though in that case you should just have a synchronous method, not an async one).

Notes on lifetimes of Channels and their Factories

Tuesday, March 18th, 2008

One question I get from custom channel authors has to do with the various lifetimes of the components involved. Especially since, as per best practice, their heavyweight resources are attached to ChannelFactories and ChannelListeners and simply referenced from the Channel. Nicholas covered the basics in this post. Which to summarize is:

  • ChannelFactory created Channels cannot outlive their creator
  • channelFactory.Close/Abort will Close/Abort all Channels created by that factory
  • ChannelListener created Channels can outlive their creator
    • channelListener.Close/Abort simply disables the ability to accept new channels; existing channels can continue to be serviced

    Which makes life on the ChannelFactory end pretty straightforward.  On the ChannelListener side, there are a few subtleties. 

    First, a Channel is owned by the listener from the time of creation until the successful completion of channel.Open.  So if you are writing a custom listener that has offered up channels, you should clean them up if and only if they haven’t been opened.

    Second, in order to perform eager disposal, you will need to track active ownership of your heavyweight resources. If there are opened channels, then you need to make sure that the shared resources that they leverage have their ownership transferred from the listener to your active channel(s). This can be accomplished through ref-counting, active transfers, or other mechanisms.

    Pumping in a Layered IInputChannel

    Tuesday, March 11th, 2008

    When writing a layered channel, sometime you want to decouple processing without changing the channel shape. One example would be for layered demux purposes. When layering your IInputChannel on top of a "lower" IInputChannel, you have a few options for lifetime management and pumping that are worth noting:

    1. When your innerInputChannel.Receive call returns "null", that means that no more messages will arrive on that particular channel. You should Close that channel and then Accept a new one.
    2. If the innerListener.AcceptChannel call returns null then your inner listener is completely done providing messages and you need to follow suit when you are through with any added messages that you may have buffered.
    3. If someone calls Close/Abort on your IInputChannel, you have the option of holding onto the inner channel within your listener (and providing a new facade on top when a new channel is accepted). Alternatively, you can close the inner channel and create a new one with your new channel. That choice is entirely at your discretion (and at the mercy of your perf tuning results :))