Scott Hanselman

Squeezing the most out of IIS7 Media Bit Rate Throttling

March 21, '08 Comments [5] Posted in HttpHandler | HttpModule | IIS | Podcast
Sponsored By

image ScottGu blogged about the IIS 7.0 Bit Rate Throttling Module being released. Since IIS 7.0 is totally modular (finally!) I think you'll see lots of increasingly useful modules coming out from the team. I know a couple of cool people over there so I get a little insight into what's coming soon.

Since I'm into podcasting some, I started bugging a PM in the IIS team about the Bit Rate stuff in order to dig deeper into what's going on and how I can exploit it. The next step will be to convince Carl, my producer, that we need to get on this stuff.

His Gu-ness has a better description of Bit Rate Throttling that I could write, so here's the meat of it:

Progressive Download Scenario

In a progressive download scenario a client (like Flash or Silverlight) downloads a video directly off of a web-server, and begins playing it once enough video is downloaded for it to play smoothly.

The benefit of using a progressive download approach is that it is super easy to setup on a web-server. Just copy/ftp a video up to a web-server, obtain a URL to it, and you can wire it up to a video client player. It doesn't require any custom web-server configuration, nor require a streaming server to be installed, in order to enable.

The downside of using a progressive video download approach, though, is that web-servers are by default designed to download files as fast as possible.  So when a user clicks to watch a video on your site, your web-server will attempt to transmit it to the client as fast as possible.  This is fine if the user decides to watch the entire video.  But if the user stops watching the content half way through the video (or navigates to a different page), you will have downloaded a bunch of video content that will never be watched.

If the remaining un-watched video content is several megabytes (or even tens of megabytes) in size, you will end up over time spending a lot of money on bandwidth that is not benefiting your business/site at all....

That's the problem this module tries to solve. If you think it's not a problem, talk to me or Carl. It costs a metric buttload to pay for bandwidth of my podcast and it's a harder problem to solve than you think. (Yes, every show has bittorrent as an option, but few Feed Readers use it). A surprising number of folks visit the site and just click on a show and start listening in whatever Media Player they dig.

If someone starts streaming the first 20 seconds of a 45 minute show, decides they don't like it and stops, we may have to pay for the whole 45 minutes as it might already have been downloaded! This is also good for screencasts.

The media throttling stuff looks at the file you're downloading, "bursts" the first chunk to make the "buffering" part of your listening experience as fast as possible, then it throttles the bandwidth from that point on, making sure it doesn't have to buffer again, but still saving bandwidth.

There's some technical details over here that I care about like (emphasis mine) and more technical details here:

"It's also worth noting that the throttler uses a high-performance asyncronous loop to push the data out, without tying up server threads for what can be a very long operation. For responses coming from files (like most large video files), it also does not need to read the content's of the file being sent into memory, instead just instructing http.sys to send portions of the file out to the client at a time.  Because of this, it won't significantly affect your memory usage. While this mechanism is not as efficient as http.sys's own site-wide bandwidth throttling (which cannot be used to do what we are trying to accomplish here), it is pretty much as lean as it can be."

So, I'm going to give this a try on my local machine. I'll start with a recent WMA of the show and put it in a folder under IIS.

image

Notice that this show is a WMA encoded at 32kps (for low-fi/low-bandwidth listeners) and is in http://mymachine/show. I turned on Bit Rate Throttling from the IIS Management Console.

You can set the throttle rate as a percentage of the encoded rate. I'm leaving it as 100%, so that's 100% of 32kbps after the initial burst of 20 seconds.

image

ASIDE: One of the things that is way better in IIS7 than 6 is dealing with permissions and "blocking issues." You know, when you setup a folder, configure the VDir and you get something like "permission denied" then you spend 20 minutes trying to figure out why you can't serve a freaking text file out of a folder? IIS7 has a "Test Settings" dialog like this that just saved me those 20 minutes.

image

Ok, back to business. When I hit this file I get the quick burst, then throttling hits to slow it down to a value above, but close to, the encoded rate.

image

If I try the hi-fi version of the WMA, you can see the bitrate is higher, so the throttling is smart enough to slow the bandwidth but it's always higher than the encoded rate so there's no skipping.

image

Here's what the burst followed by the throttling looks like charted.

image

Remember that this is just a stock IIS Web Server plus this new module, so we're not running Media Services or a Streaming Server or whatever.

Extending Bit Rate Throttling with Custom Code

I thought this was cool and everything, but I immediately brought up the question that some of my users download directly via RSS Readers, while others click the "play now" button and stream. I don't want to throttle the bandwidth for folks who are downloading, just those who stream. However, I'm not running a streaming server (meaning, that everything is over http://, not some mms:// funky port) so I need to differentiate between the two.

I figured there were a couple ways to handle this. I could make different VDirs in IIS mapped to the same files and have BRT (Bit Rate Throttling) turned off on one and on for the other. It'd work, but meh.

Or, I could add Windows-Media-Player/11.0.5721.5145 the end of the URL and turn BRT off for those using a custom coded IIS Module.

How to I write a module? I could make a bin folder and build a DLL, etc, but I could also just make an App_Code folder, apply the appropriate permissions...

image

...and put the source for my custom module in it. I actually wrote it in Notepad.

using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.IO;

namespace Hanselmodules
{
    public class CustomBRTModule : IHttpModule
    {
        public void Init(HttpApplication application)
        {
            application.BeginRequest += new EventHandler(OnBeginRequest);
        }

        public void Dispose(){}

        public void OnBeginRequest(Object source, EventArgs e)
        {
            HttpApplication app = (HttpApplication)source;
            HttpContext context = app.Context;

            if (context.Request.QueryString["download"] == "true") //make these fast
            {
                context.Request.ServerVariables.Set("ResponseThrottler-InitialSendSize", "60000");
                context.Request.ServerVariables.Set("ResponseThrottler-Rate", "6000");
            }
        }
    }
}

Basically, I just check for ?download=true on my URL and set my initial send size and rate to really big numbers. (Certainly they could be bigger, come from config, or be calculated by me.)

From the Modules section of the IIS Manager I hit Add Module and my new module shows up. I name it and select it and it appears in the web.config in my /show folder.

 image

After installing this module if I hit: http://mymachine/show/foo.wma I get appropriate throttling, and if I hit http://mymachine/show/foo.wma?download=true I don't. Below you can see screenshots of one download finished at 9megs a second while the other is throttled at 28K/s.

image

Now, this is just one example. I might want to do something cool with JavaScript that appends the ?download if a person clicks a button, or I might want to "sniff" for browser User-Agents versus Media Players like "Windows-Media-Player/11.0.5721.5145" or iTunes/Zune or the like. It's up to me, as writing the IIS7 modules is easy.

You could even use BRT and techniques like this to throttle bandwidth to data (non-media) files, and give different chunks of bandwidth to different levels of users. My module could have checked if it was a paid user and give them preferred download speeds. Pretty sweet. Now, off to talk to Carl! :)

Related Links:

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web

Conditionally Serve Files Statically or Dynamically with HttpHandlers

February 1, '07 Comments [3] Posted in ASP.NET | HttpHandler
Sponsored By

I have some static files - RSS XML in fact - that have been served by IIS as static files for a while. I consider them permalinks, and I don't want to change that for now, but I wanted to do some testing with FeedBurner (similar do what I did before with FeedBurner in DasBlog) letting them serve the RSS for a while, gathering statistics. If it went well, I'd go with FeedBurner full time for those files - but not all.

So, given a directory with: foo.xml, bar.xml, bat.xml and others all served statically by IIS, I wanted a quick and dirty way to maintain the permalinks while handling a few of the files dynamically, and a few as redirects to FeedBurner.

There's a number of ways to solved this depending on your version of IIS and ASP.NET; here's an easy way, and the way I'm doing it now.

By default IIS will serve XML files as static files with the text/xml mime type and ASP.NET will never hear about it. As XML files aren't handled by ASP.NET, first I need to configure IIS to pass all requests for XML files for this VDIR to ASP.NET. Do this from the Configuration button under Home Directory in the Properties pages of the app/vdir. I've pointed ".xml" to aspnet_isapi.dll as seen in the figure at right.

Note that you need to be explicit if you want IIS to check if the file exists. For example, if foo.xml is a real static file on disk, but bar.xml is going to be dynamically created, don't select "Verify that file exists." Setting this checkbox wrong is the #1 developer-error that you'll hit when creating HttpHandlers to handle custom extensions.

Next I'll add a handler in web.config for *.xml (or just foo.xml, etc, if I want to be more restrictive).

   1:  <httpHandlers>
   2:  <add verb="GET" 
   3:  path="*.xml"
   4:  type="Foo.Redirector,FooAssembly"
   5:  />
   6:  </httpHandlers>

Now I'll create a VERY simple HttpHandler that will fire for all .xml files (or just the ones you want, if you only associated a few files in your web.config.

This is your chance to:

  • Redirect elsewhere
  • Dynamically generate the file they asked for
  • Pick up the file off disk and serve it statically

The example below checks to see if the UserAgent requesting the files foo.xml or bar.xml is FeedBurner. (You could check other things of course, like IP subnet, etc.) If it isn't FeedBurner's bot, we currently redirect them temporarily with an HTTP 302. There's commented code for a permanent redirect, which RSS Readers respect, that would cause the client to update their bookmarks and never return. For now, I'll do a temporary one.

   1:  using System;
   2:   
   3:  namespace Foo
   4:  {
   5:      public class  Redirector : System.Web.IHttpHandler
   6:      {
   7:          void System.Web.IHttpHandler.ProcessRequest(System.Web.HttpContext context)
   8:          {
   9:              string userAgent = context.Request.UserAgent;
  10:              if (userAgent != null && userAgent.Length > 0)
  11:              {
  12:                  // If they aren't FeedBurner (optional example check)
  13:                  if (userAgent.StartsWith("FeedBurner") == false)
  14:                  {
  15:                      string redirect = String.Empty;
  16:                      string physicalpath = System.IO.Path.GetFileName( 
context.Request.PhysicalPath).ToUpperInvariant();
  17:                      switch (physicalpath)
  18:                      {
  19:                          case "BAR.XML":
  20:                              redirect = "http://feeds.feedburner.com/Bar";
  21:                              break;
  22:                          case "FOO.XML":
  23:                              redirect = "http://feeds.feedburner.com/Foo";
  24:                              break;
  25:                      }
  26:                      if (redirect != String.Empty)
  27:                      {
  28:                          context.Response.Redirect(redirect); //temporary redirect
  29:   
  30:                          //context.Response.StatusCode = 
(int) System.Net.HttpStatusCode.MovedPermanently; //permanent HTTP 301
  31:                          //context.Response.Status = "301 Moved Permanently";
  32:                          //context.Response.RedirectLocation = redirect;
  33:                          return;
  34:                      }
  35:                  }
  36:              }
  37:              context.Response.ContentType = "application/xml";
  38:              context.Response.TransmitFile(context.Request.PhysicalPath);
  39:          }
  40:   
  41:          bool System.Web.IHttpHandler.IsReusable
  42:          {
  43:              get { return true; }
  44:          }
  45:      }
  46:  }

If they ARE FeedBurner, that means their bot is returning to get fresh data from the foo.xml or bar.xml files. If so, we call the new ASP.NET 2.0 TransmitFile API, that supplements/improves on the earlier WriteFile. Transmit file doesn't buffer to memory and solved a number of problems seen when writing out files and buffering.

We also fall to this default code path if any other XML file has been requested, if that file is hooked into ASP.NET via the web.config. In my example, *.xml is hooked up, so all other requests end up in the TransmitFile API.

TransmitFile doesn't pass the request back to IIS, as some folks believe, nor does it handle caching for you. If you need that support you'll need to write it by following the HTTP spec and handling the headers yourself.

To recap:

  • Tell IIS to pass handling of your extension to ASPNET_ISAPI
  • Map files or extensions to Assembly Qualified Names in the web.config httpHandlers section - i.e. What class handles what files dynamically?
  • Create, redirect or serve your files

I'll try to writeup some other ways to solve the same problem, depending on what version of ASP.NET and IIS you're using. If you've got clever ways (there are many) leave them in the comments.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web

A new day, two new browsers compared - Firefox 2.0 Beta 1 and IE 7.0 Beta 3

July 14, '06 Comments [18] Posted in XML | HttpHandler | Bugs | Tools
Sponsored By

Like a schmuck, I can't resist installing beta software, especially REALLY beta software, especially on computers that I really shouldn't be installing beta software on like my computer or my wife's, especially at 2am. After some painful installation chaos/debugging...I got Firefox 2.0 Beta 1 and IE 7.0 Beta 3 installed. Here's my thoughts.

First Impressions:

Firefox 2.0 Beta 1: Still ugly as hell by default. For crying out loud, just make up with the Qute guy and set his theme by default. Sheesh.

IE 7: Different, softer, minimalist. I like the tabs. It's odd, but feels familiar.

RSS

Recall that IE7 installs the new Windows RSS Platform with it's Common Feed List that 90% of Windows Aggregators will start using for storage. Since Firefox doesn't have a Common Feed Store and doesn't recognize the new Windows Common Feed Store (until someone writes a utility to register feed:// with the Common Feed List) it displays a list of registered feed readers on your system. I really like this approach as it works with my FeedDemon addiction, and will work with not only offline aggregators like RSSBandit and SharpReader, but online ones like Bloglines and MyYahoo.

Both browsers show a very nice, styled page rather than the underlying RSS/XML. IE uses heuristics to figure out if it's a feed and also handles lots of malform-edness, while AFAIK Firefox goes by mime/type.

IerssFirefoxrss

In IE, since it includes a feed retrieval engine, there's a number of very nicely designed dialogs for updating the schedules for each feed, as well as their attached (enclosed) files.

Ierss2

Anti-Phishing

The need for a browser to have Anti-Phishing capabilities is huge in my opinion. Comparing Firefox 2.0 Beta 1 with IE 7.0 Beta 3, I visited six brand new, known, phishing sites. (Remember, Corillian knows Anti-Phishing)

Interestingly, and surprisingly to me, only IE detected every single phishing site. Firefox didn't detect a single one. I would point out also, as an aside, that Outlook 2007 went to great lengths to keep me from visiting these sites.

Perhaps the phishing services that Firefox uses at Google were down during my test? When Firefox does detect a phishing site it's supposed to look like this, below. I was hoping to have two identical phishing sites side by side, but again, Firefox didn't detect anything suspicious on these sites, so I visited the Firefox test phishing site. You can also submit naughty sites to Google.

IE7 showing a suspicious websiteFirefox showing a suspicious website

One interesting note, both browsers allowed me to continue working with the known phishing site, even though they knew they were dangerous. I think I'd rather have a dialog that made me type in "I know this is a phishing site."

Usability

IE7 has a new "tile" feature available by default; it's the little 4-square button to the far left of the tabs. It's "exposé" for web pages. There's a number of similar Firefox extensions like Foxpose and Tabexpose, but none for Firefox 2.0 today. Give it a few hours. Interesting that IE7 includes it by default, though, with Ctrl-Q (QuickTabs) as the hotkey.

The little "star" non-committal icon aims to say "click me, it'll make sense soon." This opens a the Favorites|Feeds|History pane. Eh.

IE7 with four sites open, tiledIE7 with History Pane open

In IE7, I love that CTRL-Scroll is how mapped to the new (and WAY more useful) zoom feature (ala Opera 1997), although I was disappointed to see that the useless Text Size Feature is next to it. Breeds confusion I say. Screw you, Text Size and your lies.

Iezoom

There's dozens of other usability things in IE7 that are obvious, including the revamped Tools|Options for Humans, which I wouldn't be afraid to send my Dad into. Except for Tools|Options|Advanced - that's still scary even to me.

In Firefox 2.0, less has changed, at least, less dramatic stuff. The coolest new feature, IMHO, is the inline spell checker.

Firefoxspellcheck

There's another new feature called micro-summaries. Basically it's your page's opportunity to change the title of a bookmark to provide status. For example, Woot provides a micro-summary by specifying this in their HTML:

 <link rel="microsummary" type="application/x.microsummary+xml" href="DefaultMicrosummary.ashx" />

That HttpHandler might responsd with just this: "$69.99 : Nexxtech 7” 16:9 LCD Portable DVD Player" as text/plain. That text could then be used as the title of a bookmark or toolbar button. It's a little early, and very specilized, but it fills a small gap and adds on to the whole link rel="" vibe nicely. Could really take off ono mobile devices as the equivalent of "tiny RSS."

Firefox also includes the trappings of client-side session support that could take AJAX apps to the next level in the next few years if Microsoft jumps on board also.

Downloads

The download windows of each browser look pretty much the same.

Iedownload

There's a new animation in IE's, but otherwise, not much here. I still prefer Firefox's consolidated view.

Firefoxdownload

Conclusion

Before I was pretty much a one browser guy, Firefox. Now I think I'll try IE more, and even more likely I'll notice which browser I'm in less as they are converging. The RSS features of IE7 are compelling and as soon as there's a NewsGator Online/RSS Common Feed Store synchronization story along with FeedDemon support, I might spend more time in IE7.

Most importantly I won't feel back recommending either of these browsers to family. Both are WAY safer than their predecessors. (Assuming the future parity of their phishing feature)

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web

Looking for Senior Software Developer at Corillian

May 17, '06 Comments [19] Posted in ASP.NET | XML | HttpHandler | HttpModule | Tools
Sponsored By

We are looking to add a Senior Software Developer to our Consumer Banking team here at Corillian.  Are you "just the right person"?  If you are, then you fit the following description:

You know web development inside and out and can explain the HTTP protocol and HTML to your mother.

You have deep expertise with development using Microsoft ASP.NET.  You know the page event model, the control event model and the difference between a HTTPModule and a HTTPHandler and when each makes sense.

You understand how DOM and SAX parsers function, how XML schema works and how it is fundamentally different than database schema.

You know that TDD really means "write the test first"
 
You know how to read code, not just write code.

You are prepared to do what it takes to deliver value to the customer.

You work with others in an environment that encourages new ideas and improvement.

You have experience using a source control tool other than VSS.

You are willing to live in Portland, OR.  (To be a part of our team, you have to be here.  No telecommuting.)

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web

ASP.NET MVP Hacks

April 30, '06 Comments [5] Posted in ASP.NET | TechEd | ViewState | HttpHandler | HttpModule
Sponsored By

0764597663.01._SCLZZZZZZZ_V52483501_David Yack got a bunch of folks together and assembled ASP.NET 2.0 MVP Hacks from Wrox. Take a look at the picture on the right, totally looks like we're all in the same room with our twelve-sided dice, no? ;)

Seriously though, it's a good collection of "messing with ASP" hacks. I did the sections on HttpHandlers/HttpModules and the ViewState hacks. Some of the content came from my blog. I also pulled in content, with permission and attribution from a number of other smart ASP.NET blogs. Most hacks work on both ASP.NET 1.x and 2.0 as well.

A book with a Brady Bunch cover full of nerds, yes.

A book with a lot of slick hacks, totally.

Big ups and congrats to David for pulling it all together, he's really been working hard on this book and I'm happy to have been involved along with the other (very seasoned) authors David Yack, Joe Mayo, Fredrik Normén, Dan Wahlin, J. Ambrose Little, and Jonathan Goodyear.

ASP.NET 2.0 MVP HacksProfessional ASP.NET 2.0
Total List Price: $89.98
Buy Together Today: $57.88

If you're looking to get this and Pro ASP.NET 2.0, the total price is only $57.88 on Amazon right now as a bundle. To be clear, the content in these two books doesn't overlap. The Hacks book is focused on specific and finite tips, tricks, and undocumented features and manipulations of ASP.NET Features, while the Pro ASP.NET book starts with fundamentals and builds feature by feature to advanced topics advanced to Professional ASP.NET 2.0 developers.

 

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web
Page 1 of 4 in the HttpHandler category Next Page

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.