I'm reusing the title from an article in the latest MSDN magazine and the reason is that I think the article missed one obvious solution. The cooperative solution described in the article is interesting but also hard to implement since it implies a protocol between the outer and inner role. Load balancing by using a random algorithm would be a simpler way to achieve fairness and high availability of your services. Random based load balancing actually comes in two flavors.
First we have "session seeded" random. This means that you use a session identifier to "seed" your choice. Assuming that your session identifier is generated (GUID for example) you could just use the last byte (I assume you have less that 255 internal instances to load balance over) and do a modulo operation on the number of internal instances you have. This way each session will talk to the same internal endpoint. Very similar to the static approach descried in the article with the advantage that it works regardless of the number of internal endpoints. And it also works as new roles are added or removed.
The second alternative is to use pure randomness. This should be enough if there is no caching in the internal role. Getting the endpoint can then be implemented really easily with a little LINQ trick. First you need a nice extension method for IEnumerables.
1: public static T SelectRandom<T>(this IEnumerable<T> collection)
3: var random = new Random();
4: return (from item in collection
5: orderby random.Next()
6: select item).FirstOrDefault();
Then you use that to pick a random endpoint.
Naturally you could use a caching mechanism like described in the article to not query the RoleEnvironment for every endpoint you need.