Component Port

Life would treat you as you treat them!
数据加载中……

2008年8月22日

Application Request Routing and the IIS 7.0 Web Management Service

Yesterday I was having a conversation with Anil Ruia who happens to be the ARR (Application Request Routing) developer and based on customer feedback we discussed the idea of using ARR in the context of Remote Management in IIS which solves a question that several people asked me before and thought it would be fun to try it out.

Basically the question that I got asked was "Can I have a single entry-point exposed for Remote Management?", or in other words "Can I provide users with remote administration giving them a single server name like management.myhostingcompany.com, instead of having to give them the specific machine name where their site lives?". So far the answer to these questions was "not easily", however with the use of ARR and URL Rewriter we will see how easy it is to achieve this.

The only thing you need for this to work is install the new URL Rewrite and ARR Module both available here http://blogs.iis.net/bills/archive/2008/07/09/new-iis7-releases-url-rewrite-application-routing-and-load-balancing-and-powershell-cmd-lets.aspx.

Background

The Web Management Service (WMSvc) is the service that enables remote administration for IIS 7.0 Manager, providing an HTTPS end-point that exposes functionality similar to Web Services to manage the Web Server (IIS) remotely. This service uses HTTPS for its communication and exposes several configuration options that support giving access to Non-Windows Users (What we call IIS Manager Users), provide a list of IP Restrictions, support only local connections and many more that can be managed using the Management Service feature inside IIS Manager.

To enable remote administration typically you need to: 1) Configure a valid Certificate for SSL, 2) Allow Remote Connections and 3) Start the WMSvc Service, all of which can be performed in IIS Manager. Once you have successfully enabled the remote service you should be able to go to a different machine and be able to connect remotely.

Note: If you are using Windows Vista, Windows XP, or Windows 2003 to connect to a Windows Server 2008 you need to download and install the client to do this: http://www.iis.net/downloads/default.aspx?tabid=34&g=6&i=1626

However, one of the drawbacks is that in order to be able to connect to a Web Site, the end-user needs to know the machine name, as well as the name of the Web Site they will be connecting to, which sometimes it would be better to be dynamic. The following image shows the information required to enter when connecting to a Web Site. Note that if connecting to an application you will also need to enter the name of the application.

ConnectingToSite

However, this can potentially reduce the flexibility for deployment options, since now your customers have specific knowledge of the physical machine and will limit the flexibility of moving the site to different machines or even changing the name of the site where it is being hosted.

ARR and URL Rewrite to the rescue.

ARR has several very interesting capabilities that are really useful for this scenario. First, we can configure it to act as a proxy and basically forward the requests to another server where they actually get processed. This is the simplest configuration option and what it allows you is to have something similar to the next image:

WMSvcRouting

To set up this configuration where a front-end management server forwards the IIS Remote Management requests to another server running WMSVC you have to:

  1. Install ARR and URL Rewrite in the Server that is intended to be used as the front-end for management requests. Lets call this ServerA.
  2. Create a new Web Site.
    1. Navigate to IIS Manager->Site
    2. Click Add Web Site.
    3. In the dialog set: Site name:ManagementSite, Binding: https, port: 8172 and choose a valid SSL certificate, specify a phisical path. Click OK
  3. Configure URL Rewrite to Route requests to the IIS Management Service running in the other computer.
    1. Navigate to IIS Manager->Sites->Management Site->URL Rewrite Module
    2. Click Add Rule
    3. Set: Name: RouteWMSvc, Pattern:.*, Rewrite URL:https://<RemoteServer>:8172/{R:0}, Stop Processing rules: Checked.
    4. This should generate a web.config with similar content (note that my backend, ie the RemoteServer in my case is carlosag2-iis below):

      <configuration>
         
      <system.webServer>
             
      <rewrite>
                 
      <rules>
                     
      <rule name="RouteWMSvc" stopProcessing="true">
                         
      <match url=".*" />
                          <
      action type="Rewrite" url="https://carlosag2-iis:8172/{R:0}" />
                      </
      rule>
                 
      </rules>
             
      </rewrite>
         
      </system.webServer>
      </configuration>

  4. Now you can run IIS Manager in any client machine, specify the ServerA as the machine name and specify any web site in the remote RemoteServer, the result will be that all requests will be forwarded to the WMSvc running in the remote server.

Now, that is interesting and the scenario it allows you to do is potentially have WMSvc IP Request Filtering in the RemoteServer and only allow calls from the Management Server where you can do further configuration. Note that this also means that you can have a single public SSL Certificate in the management server and use privately issued certificates (or potentially even self-signed certificates in the remoteserver since you can control installing the certificate into the management server). It also means that the customers no longer use the physical name of the RemoteServer machine but instead connect to the Management Server allowing you to completely move them to another machine and not have to update your clients.

Troubleshooting: If you are having troubles testing this, the best thing to do is enable Failed Request Tracing in the ManagementSite, which will tell you exactly what is going on. For example you will get entries like:

Warning: ModuleName="ApplicationRequestRouting", Notification="EXECUTE_REQUEST_HANDLER", HttpStatus="502", HttpReason="Bad Gateway", HttpSubStatus="3", ErrorCode="2147954575", ConfigExceptionInfo=""

If you lookup the ErrorCode, it is actually: ERROR_WINHTTP_SECURE_FAILURE, this means that you have most likely issues with the certificate. In my case, just to test this what I did is generate a self-signed certificate in the RemoteServer with the name of the machine (carlosag2-iis) and then I installed that certificate using the MMC certificates snap-in in the management server into the Trusted Root Certification Authority. Disclaimer Warning!! this is something you should only do for testing purposes or if you know what you are doing.

More Advanced Stuff... Dynamically choosing the machine

Now, trying to push the capabilities of this I decided to solve another requests that we've heard which is closely related "Can I have a single management server and dynamically route the requests to the machine where a particular site lives?"

The following picture represents this, where the Management Server dynamically resolves the server that it should talk to using the URL Rewrite Maps functionality.

WMSvcRoutingMultiple

Turns out this is really simple using URL Rewrite, basically you can write a Rewrite Rule that matches the Site name that is included as part of the Query String and use the Rewrite Maps support for figuring out the machine where this site lives. The following shows such a rule:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
 
<system.webServer>
   
<rewrite>
     
<rules>
       
<rule name="RouteWMSvc" stopProcessing="true">
         
<match url=".*" />
          <
conditions>
           
<add input="{QUERY_STRING}" pattern="Site=([^&amp;]+)" />
          </
conditions>
         
<action type="Rewrite" url="https://{ServersTable:{C:1}}:8172/{R:0}" appendQueryString="true" />
        </
rule>
     
</rules>
     
<rewriteMaps>
       
<rewriteMap name="ServersTable">
         
<add key="CarlosAgWebSite" value="carlosag2-iis" />
          <
add key="SomeOtherUserSite" value="carlosag1-iis" />
          <
add key="SomeOtherUserSite2" value="carlosag3-iis" />
        </
rewriteMap>
     
</rewriteMaps>
   
</rewrite>
 
</system.webServer>
</configuration>

Basically, URL Rewrite matches every request and uses the condition entry to parse the Query String and find the Site name within it. With it, it and using the Map ServersTable to resolve the machine name based on the Site name it rewrites the request to the machine where its currently located. This makes it basically route "https://localhost:8172/Service.axd?...&Site=CarlosAgWebSite into https://carlosag2-iis:8172/Service.axd?...&Site=CarlosAgWebSite. The end result is that can dynamically at any time just update this table and make ARR route the requests to the right machine giving you complete flexibility on the deployment of sites.

One thing to note is that URL Rewrite is one of the ways you can make the ARR scenario work, however, you could also write your own module that uses any dynamic behavior such as going to a database or a provisioning system or anything else and rewrite the URL programmatically in a way that ARR will understand it and do the routing automatically.

Also, worth to mention that ARR has way more features than just this, making it possible to load-balance requests and many more interesting stuff that I will try to get back in a future post.

With all this you can imagine several benefits, such as single public end-point for remote management of multiple servers, only one valid certificate is needed facing public machines, you can relocate sites at your own will since customers will never really know the real machine name where their site lives, you can use a similar technique to rewrite even the Site Name and give them some friendly name such as their user name or whatever.

Acknowledgements: I want to thank Anil Ruia and Daniel Vasquez Lopez who helped figuring out a few issues during this blog and Ruslan Yakushev and Won Yoo for reviewing its technical accuracy.

posted @ 2008-08-22 19:01 winkingzhang 阅读(22) | 评论 (0)编辑

2008年7月8日

Reference Resources for MOSS and WSS

     摘要: Reference Resources for MOSS and WSS  阅读全文

posted @ 2008-07-08 11:49 winkingzhang 阅读(21) | 评论 (0)编辑

2008年7月4日

FileSystemWatcher事件多次触发的解决方法

     摘要: FileSystemWatcher事件多次触发的解决方法   阅读全文

posted @ 2008-07-04 10:05 winkingzhang 阅读(28) | 评论 (0)编辑

2008年5月28日

ASP.NET Application Life Cycle

     摘要: Have you ever wondered about all the stages that an ASP.NET request goes through? Ever wonder why it is such a performance hit to have a wildcard mapping to map all extensions on your web server to ASP.NET? This information corresponds to IIS 5.0 and 6.0.   阅读全文

posted @ 2008-05-28 14:45 winkingzhang 阅读(35) | 评论 (0)编辑

2008年5月22日

CAS and Native Code

     摘要: CAS is complicated enough to understand when all of the moving parts are written in managed code (and therefore have all the associated managed meta-information like grant sets, etc). However, once native code comes into play things can get even more confusing. Let's take a look at how CAS works when there's native code on the call stack.  阅读全文

posted @ 2008-05-22 10:54 winkingzhang 阅读(33) | 评论 (0)编辑
WPF 3.5 SP1 feature: IEditableCollectionView

     摘要: IEditableCollectionView is a new collection view that you can use to supports adding and removing new items, as well as editing items in a transactional way. It is implemented by ListCollectionView (the default view for ObservableCollection) and BindingListCollectionView (the default view for DataTable). I will go through an example to further describe it and summarize afterwards.   阅读全文

posted @ 2008-05-22 10:38 winkingzhang 阅读(62) | 评论 (0)编辑
Storing text in the clipboard using Silverlight 2

     摘要: To provide users the ability to copy permalinks or store other useful information in the clipboard, there aren’t many options for web developers today. There’s no APIs inside JavaScript to access the clipboard. Here’s a solution that will at least enable this from your Silverlight 2 app for most of your users.  阅读全文

posted @ 2008-05-22 10:32 winkingzhang 阅读(42) | 评论 (0)编辑

2008年3月26日

枚举的多语言显示(2)——使用Attribute

     摘要: 还是jhh0111昨天关于枚举的双语显示问题的帖子的问题,有不少人跟贴询问使用Attribute的实现,于是刚才乘午间休息实现了一个,这里share一下。  阅读全文

posted @ 2008-03-26 14:37 winkingzhang 阅读(2262) | 评论 (5)编辑

2008年3月25日

枚举的多语言显示

     摘要: 早上看到jhh0111昨天关于枚举的双语显示问题的帖子,中午想了想,其实这就是一个Globalization的问题,虽然jhh0111的方案可以工作,但是扩展性不强——当枚举数量很大时可用性很低;另外,如果绑定到其他控件(比如Grid控件)也会有一些问题。
这里给出一个通用的解决方案,虽然复杂了一些,但是可用性和扩张性均有大大提高。  阅读全文

posted @ 2008-03-25 14:52 winkingzhang 阅读(1918) | 评论 (16)编辑

2008年3月19日

如何配置支持Silverlight的Web服务器

     摘要: 部署Silverlight到Web服务器是一个相当容易的过程,尽管有时候会有一些错觉——譬如,认为Silverlight需要部署在基于微软的Web服务器(IIS)上,事实上, Silverlight不强制一定部署在基于微软的Web服务器上,Apache也可以像IIS一样,轻松愉快的支持Silverlight运行。  阅读全文

posted @ 2008-03-19 17:22 winkingzhang 阅读(2075) | 评论 (3)编辑