Azure / dev-spaces

Azure Dev Spaces is retired, please use Bridge to Kubernetes.
MIT License
136 stars 306 forks source link

Documentation around outbound requests is inconsistent #157

Open chrisjohnson opened 5 years ago

chrisjohnson commented 5 years ago

In https://docs.microsoft.com/en-us/azure/dev-spaces/team-development-nodejs#use-dev-spaces-for-team-development you can see a line that says one possibility for developing a single service in a micro-services architecture (with the implication that this is not desirable and that you can use dev spaces to alleviate it) is to Add development-focused code to webfrontend that allows the developer to send requests to a different instance of mywebapi. This complicates the webfrontend service.

However later in the technical description of how routing happens https://docs.microsoft.com/en-us/azure/dev-spaces/how-dev-spaces-works#how-routing-works it says The serviceA application in the serviceA.azureuser pod makes a call to serviceB. The serviceA application also contains code to preserve the existing azds-route-as header, which in this case is azds-route-as: azureuser. which implies to me that the only way to make this work is to modify every application to preserve this header on all outbound requests.

I'm not even sure the former (not modifying the application) is feasible. Consider background workers that get triggered by incoming requests. An incoming request might hit cjohnson.s.app1... and then that will schedule a background job later to reach out to app2. We would have to modify our background job scheduler to support the concept of passing extra headers through to the request. And that's just one simple example, there are many possible egresses that would need to be manually handled in code.

This is in contradiction with the implication that dev spaces solves the issue of having to modify your application for you. Not that I don't think it's a neat feature, but it's not obvious without a lot of technical digging that there are still these modifications you'll have to make to all of your applications.

Unless I'm just misunderstanding something about how this all works?

stepro commented 5 years ago

Your understanding is correct and the documentation is a little misleading. When it says add development-focused code to webfrontend… it refers to inventing your own mechanism for conditionally routing to different service instances based on some custom logic.

The dev spaces approach to routing does require changes to code, but it's the exact same change everywhere and requires no logic in the code - just propagation of a single header. That header is interpreted outside of your code and used to dynamically route to different service versions.

While it's certainly not ideal that code needs to be updated, our hope is that people writing these kinds of micro-service applications will already be propagating headers for other reasons such as correlated diagnostics, and adding another header into the mix would not be hard. We would certainly be interested to hear opinions on this and whether the ability to choose your own header or other means would be useful.

FWIW, we do know that through some ASP .NET Core middleware magic, it would be possible to automatically propagate this header from an incoming request to an outgoing request if it is part of the same context representing the incoming request. We are looking to understand the priority of enabling this to alleviate the need to modify code for many circumstances.

chrisjohnson commented 5 years ago

Like I said, it certainly seems logical to me that the former description is just a little bit impossible. I would suggest a little bit of cleanup around the docs:

A more magical middleware like you describe sounds helpful, but I would caution that it be described more as a helper for the work you need to do to your app than a complete solution, since obviously it wouldn't help with the example of background workers I gave above.

Thanks for the response.

our hope is that people writing these kinds of micro-service applications will already be propagating headers for other reasons such as correlated diagnostics

Are you suggesting that this idea of passing incoming headers onto outbound requests is already commonplace? I've never heard of such a concept until now FWIW. For diagnostics data the common approach seems to be logging to a central log server depending on the app environment (dev, test, prod) at each step rather than passing some message along the chain of requests.

Knowing our internal architecture of a few hundred ruby apps and a few python and elixir apps, I'm pretty positive it would require us to basically make a change to every app and in most cases make several changes across the app to support something like this. As I'm actively trying to solve the problem of "how do developers develop an app or two without standing up the entire org's dependency graph and without each developer having a complete copy (or manually curated incomplete copy) of the graph?", it doesn't seem feasible to me to present this refactor back to the organization as a solution.

stepro commented 5 years ago

Thanks for the feedback. I'll have our doc writer take a look at clarifying the documentation on this. There is no magic solution to achieve the dev spaces experience and it should be called out at an earlier point.

Are you suggesting that this idea of passing incoming headers onto outbound requests is already commonplace? I've never heard of such a concept until now FWIW. For diagnostics data the common approach seems to be logging to a central log server depending on the app environment (dev, test, prod) at each step rather than passing some message along the chain of requests.

Most applications we have seen that are made up of a number of services need to flow contextual information from one service to another when it makes up a single logical flow through the system. Probably the most common usage is for distributed tracing (e.g. like this), but it applies for other request-level contextual information as well such as user identity. This sits above any particular diagnostic solution you might use to log that context as well as other information to some ingestion endpoint.

Our hypothesis with dev spaces was that for one reason or another, code would already be flowing at least one piece of information, and one of the more common ways of doing so would be through HTTP headers. So if code already propagates A, then it could just as easily add B to that. But you are absolutely correct that you would need to go through all the services and add B to the list, and that's a daunting task if you are talking about a few hundred services.

We are considering adding the ability to customize the information that would be used by dev spaces to determine where to route outgoing calls, say to allow choice of a different HTTP header name/value or look at the path or query string of the request. Is there existing context that you propagate in your applications that you could use if this were customizable?

As I'm actively trying to solve the problem of "how do developers develop an app or two without standing up the entire org's dependency graph and without each developer having a complete copy (or manually curated incomplete copy) of the graph?"

If you had tools that made it easy to automate standing up only a specific app's dependencies such that each developer had their own instances of services but only the services they actually need right now to develop their code, would that be an appealing solution to you? Such a solution would avoid the need to refactor any code because each developer effectively has their own privately bound copy of what is needed to run a particular app.

chrisjohnson commented 5 years ago

Our hypothesis with dev spaces was that for one reason or another, code would already be flowing at least one piece of information, and one of the more common ways of doing so would be through HTTP headers. So if code already propagates A, then it could just as easily add B to that. But you are absolutely correct that you would need to go through all the services and add B to the list, and that's a daunting task if you are talking about a few hundred services.

There are places where each app passes in credentials to talk to other services but they aren't done in a consistent way from one to the next that it would be easy to make a repeatable pattern. And even if we were, the use case I mentioned about incoming http requests that schedule background jobs to be executed later which send their own http requests, we would have to modify the schema of every background job record to hold the namespace it should target.

If you had tools that made it easy to automate standing up only a specific app's dependencies such that each developer had their own instances of services but only the services they actually need right now to develop their code, would that be an appealing solution to you? Such a solution would avoid the need to refactor any code because each developer effectively has their own privately bound copy of what is needed to run a particular app.

Yes, that would be great. The tricky part is that depending on which product, offering, or feature the dev is working on, the subset of the dependency graph they're interested will differ from one to the next. So it would have to be very flexible and dynamic -- I would want to be able to spin up and take down different apps from my personal namespace as I see fit. But I definitely think this would be a much more valuable tool for us (and others) -- there are often a core set of re-used services (such as auth) that would be easy to share across many developers, while still allowing for the developers to run their own subset of the cluster within their namespace.

I would imagine this concept you're talking about would be a modification to azure dev spaces and build upon the feature set already offered therein?

stepro commented 5 years ago

@chrisjohnson, we have been exploring the ideas that I mentioned, and it sounds like you are currently facing challenges in this domain. We would love to sync with you offline to learn more and get your feedback on our investigations. Would you be comfortable with us reaching out to you through the email in your profile to set up some time?

chrisjohnson commented 5 years ago

Yep feel free