Short version:
If you want to use both, for best results:

Web Proxy clients should use the array routing script/WPAD and need direct connectivity to each array member through a non-load-balanced address.
SecureNAT clients use the NLB VIP as the default gateway.
Firewall Clients connect to either the VIP or a name that maps to the VIP.

Very, very long version:
Cache Array Routing Protocol and Network Load Balancing are both scaling technologies, but have different behaviours and uses. You should assume that this information applies only to the outbound proxy scenario.

CARP

CARP was designed to be used to scale cache size and performance for web proxy servers, and is implemented using ISA Arrays.

The quick’n’dirty explanation of CARP is that if you have N proxies, 1/N of the requests will be serviced by each proxy, based on a hashing mechanism that runs both on the client and on the servers (which means, if you have either, you get some of the CARP benefit).

The standout benefit of CARP is that it multiplies your effective cache size by the number of proxies you have. Your cache size is effectively the combined sum of the size of each proxy’s cache, with negligible duplication of content, which is something not to be sniffed at*. It’s also generally faster, I’m told.

As an example pulled from my daydreams caused by the sugar consumed at lunchtime, the following might illustrate the point:

In a 3-proxy array with CARP:
http://www.microsoft.com/default.aspx - might be requested from “Proxy3”
http://www.microsoft.com/corporatelogo.jpg - might be requested from “Proxy2”
http://www.microsoft.com/includes.js - might be requested from “Proxy1”

Of course, having such an even spread is unlikely with a small number of requests, but as the volume of requests increases, it’ll be roughly equally distributed, more or less.

In the ISA Server context, CARP applies only to Web Proxy traffic, and there are a couple of layers to this:

Client CARP
Believe it or not, through the magic of the array routing script, WPAD.DAT or PAC files, the client browser actually participates in CARP. The client runs the same hash algorithm as the servers, and talks to the server that it believes will own the content for a particular URL.

This means that all other things being equal, if you run a PAC that supports CARP, you’ll get some benefit from it, as if all the clients use CARP, the servers will end up with complimentary cache content.

The client needs to know about all of the proxies, and how to contact them directly for this to work, and run the routing script/WPAD provided by the array. This point is important, so file it away for later on.

Server CARP
ISA Servers installed in an array naturally want to do CARP. This setting is controlled by the “resolve requests within array before routing” checkbox on the Outgoing Web Listener properties page. When the setting is enabled, if the “wrong” server is asked to retrieve a URL, it’ll re-run the CARP algorithm locally, pick the “right” proxy to ask for the content, and forward the request to that proxy, then return the content to the client.

CARP can be implemented purely at the server: if a client is pointed exclusively at Proxy1, Proxy1 will chat to Proxy2 and Proxy3 to retrieve the content that the client asked for. The client only talks to Proxy1, and only requires visibility of Proxy1, but each proxy will need to be able to talk to the other proxies in the array, and the level of server chatter will be increased. The logs will show the computer accounts of the other ISA Servers requesting content from each other for each set of client requests.

NLB

NLB provides box-dead failover and statistical load balancing of TCP and UDP connections across a group of clustered machines.

Box-Dead Failover: NLB has no application-layer smarts. It’s not like MSCS clustering, which can actually detect the health of applications and take nodes out of the cluster. If the service you’re trying to load balance should fail on one node, unless you actually take that box out of the cluster yourself, requests will still be routed to the dead application. Rule of thumb: If the IP stack is still responding, NLB will still be “working”. Likewise, if one node is absolutely pegging the CPU, but the other is idle, connections won’t be transferred to the idle server.

Statistical: The greater the ratio of clients to servers, the greater the probability of an even load across them.

In the ISA world, NLB is generally used to balance Firewall Client (FWC) and SecureNAT traffic – just point the Firewall Client or Default Gateway at the virtual IP (or a name that maps to it).

The default port rules for NLB are to balance TCP 0-65535 evenly across all nodes, with slight stickiness (Single Affinity – any connections from one IP go to one server). If you point a Web Proxy client at the virtual IP, it will end up on (essentially) a random server, which might not be the most efficient server to ask for objects from a CARP perspective. See the KB article 238524 on CARP and WLBS linked below for the detailed scenario.

Combination

As long as Web Proxy clients aren’t connecting to the virtual IP address of the cluster, everything works as you’d expect it to.

If Web Proxy clients are hard-coded to connect to any load balanced IP address, only server-side CARP will occur.

Likewise, if Web Proxy clients are hard-coded to any single proxy array member, only server-side CARP is possible.

If Web Proxy clients use the ISA array WPAD file, then as long as the client can connect to the individual array members directly by un-balanced IP, client-side CARP will work.

If you disable “resolve requests in array before routing”, you get only what your client script gives you (but you can create exceptions to the CARP process fairly simply - see 328248 below).

If You’re Still Interested At This Point, You’ll Love These Gems:

The Network Load Balancing white paper (Windows 2000 edition)
http://www.microsoft.com/windows2000/docs/NLBtech2.doc

Hack your Routing Script:
270524 Get.Info and Get.Routing.Script Functions Return Useful Diagnostic Information
http://support.microsoft.com/?id=270524

Tristan Finds Yet Another Useful KB Article After Writing His Blog:
238524 Using Cache Array Routing Protocol with Windows NT Load Balancing Service
http://support.microsoft.com/?id=238524

The Interesting CARP Caveat:
328428 Web Server Cannot Handle HTTP Request Made with ISA Array
http://support.microsoft.com/?id=328428