Azure - dynamically discovering service web role url in stage
Asked Answered
A

2

6

I'm looking into moving an existing app to Azure. It will have an MVC app in one web role and some WCF services in another web role. When live, the site will live at http://www.myapp.com and the services will be at http://api.myapp.com with the MVC app configured to point to the services at http://api.myapp.com.

The problem is when pushing the app to the "stage" configuration on Azure. My understanding is that each push to stage will cause the services to live at a new url (something random like http://4aa5ae2071324585ba5a902f4242a98c.cloudapp.net/). In this case, what is the best way for my MVC app to discover the url of the services?

One option would be to setup a dns entry like http://stage.api.myapp.com and update my DNS CNAME record to point to the new Azure staging url every time I push to stage, but... yuck.

Another option would be to push to stage, get the new urls for the services, RDC to each instance of the MVC role and manually update the configurations. Also yuck.

Is there a simple way to do this? I know I could automate some of the steps above with something like PowerShell, but I'm really hoping there's something baked into the Azure framework that makes this easy. It seems like it would be such a standard scenario.

Ashley answered 16/7, 2011 at 18:54 Comment(0)
B
6

The only way to dynamically discover what the staging URL will be is to have the instance check its own deploymentID. I am assuming here that the MVC website and the WCF service are in the same deployment. If you check the RoleEnvironment.DeploymentID, you will find that this corresponds exactly to the 'random' URL used in staging (i.e. http://[deploymentID].cloudapp.net).

As long as you are dynamically creating the ChannelFactory on the clientside, it should be able to take its own DeploymentID and find the staging URL.

Of course, this is only useful when deployed in staging. Why don't you simply use the Production slot? That name is stable and you can rely on it or the CNAME (more likely) that you set for it. You can always have multiple hosted services (dev, QA, prod, etc.) and just use the production slot on them.

Bootblack answered 16/7, 2011 at 20:44 Comment(6)
This is not good practice! For communication between roles, you need to use endpoints which are there just for this purpose. Sorry I've down-voted, but I really feel it is important to not do this the way you are suggesting.Aerosol
I feel like you have missed the question. It was how to dynamically discover the staging slot. There is only 2 methods (the one I outlined and using mgmt API) - which is all I answered. I don't disagree that using interrole comm is a good idea if possible, but sometimes folks really need to use the Load Balancer address and he did not clarify.Bootblack
I understand what you mean, but sometimes the answer isn't the right way of doing stuff. What I mean is, if I ask you how to tape together the processor and motherboard would you tell me, or would you rather tell me that I can just put it on there and pin it down with the mechanism already in place... The DeploymentId shouldn't be "abused" and I really feel the answer (while correct!) shouldn't be used unless you absolutely know why and what you are doing and have used every other option. Also, if you are using the external endpoint, you pay for traffic!Aerosol
As I mentioned (and the poster indicates), sometimes you really need the load balanced endpoint. However, for SL clients you will have to tell them out of band as they are not in the deployment and won't know the deploymentID. As I suggested, it is very easy to simply use the production slot which has a stable name (or more likely map that to your own CNAME). You can create more hosted services per environment and simply not use staging slot.Bootblack
Use RoleEnvironment.CurrentroleInstance.InstanceEndpoints, every endpoint has a protocol and an IPEndpoint that you can use to create a URL. Filter protocols that are not "http" or "https", create the url like this: endPoint.Protocol + "://" + endpoint.IPEndpoint.ToString() + "/";Torin
@thepumpkin1979 That is true but falls apart if you have more than one role instance that you are trying to call using the method you described.Pintle
D
4

Don't do what @dunnry is suggesting! Azure has a really good concept of endpoints that solve your problem. And you have access to this info from your RoleEnvironment class.

You can take a look at my blog post on how to get the endpoint from the client. The key part is to create an internal endpoint at which your WCF service is listening. Keep in mind though, you don't necessarily need a new role for this, and personally, I would rather host it in IIS alongide the original Web role & have two of these roles for improved reliability.

This way, it doesn't matter what the deployment is, because the service communication will take place inside that deployment, be it staging or production.

Dramatics answered 17/7, 2011 at 11:6 Comment(3)
Note: for api.myapp.com you'd set up one host bound site, and do something simillar for www.myapp.com. But they can still be a part of the same deployment.Aerosol
Thanks for the link. Unfortunately, in an effort to keep my question simple it looks like I left out a key piece of information :(. In reality, the services are being consumed by both an MVC site as well as a Silverlight project. I believe that means using the approach you suggest won't work in my case. Or is there a way to use a similar approach with public facing services?Ashley
The Silverlight client will never have the luxury on having either DeploymentID known or access to internal endpoints. It's a matter of convention then. But for internal communication, use what I've written. For the SL project, I would decide in compile time to point to a staging DNS (where the role always responds) or a production DNS name (e.g. api.myapp.net). I don't see any other way without tying them together using something else, e.g., AppFabric.Aerosol

© 2022 - 2024 — McMap. All rights reserved.