3 ms·
Interesting article. It was initially confusing to me because I wasn't able to find what's unique about this approach, and how it's different from the typical
by ninkendo 11y ago
Interesting article. It was initially confusing to me because I wasn't able to find what's unique about this approach, and how it's different from the typical Ambassador pattern that I'm more familiar with. That is, what does the word "Routing" even mean in this context?
I think the answer is that he's doing essentially layer-7 routing, using the HTTP path (and verb?) to decide what backends to route to, rather than doing it on a per-port basis (which is necessary to support non-HTTP services.)
Implementations I've run into before seem to fall into a few categories:
- A service declares that it needs to talk to, say, 3 other services. Each of these upstream services is assigned a unique client-side port, and an ambassador proxy is launched alongside each instance, which exposes those 3 ports, routing each to the corresponding 3 backend services. To keep the ports out of the source code, typically environment variables are automatically assigned, so you just talk to ie. "my-ambassador:${UPSTREAM_PORT_NAME}"
- A service is responsible for using a service discovery layer like zookeeper or etcd to find backends on its own. This is important for things that use raft/paxos/gossip, where blind routing isn't enough, you actually need to keep track of peer instances (although in that case, the service discovery layer is only used for initial discovery).
- Service discovery is done with just plain DNS on well-known ports (or even SRV records if you're lucky enough to have client software that can tolerate them), and you just hope the right thing happens. This can be accomplished with things like SkyDNS on top of etcd... a surprising amount of flexibility can be accomplished by putting logical things right in a hostname.
This approach seems to be like a more opinionated version of the first approach, but instead of ports, it uses HTTP routes, which is definitely more flexible, but only works with HTTP. The routes can contain enough information to route more intelligently than just enumerating your dependency services ahead of time and getting static port assignments.
It's almost like an API gateway distributed as an ambassador to each service. At least, it looks a lot like an API gateway, in that it presents the whole mesh of services underneath in a single URI namespace, using HTTP to route requests accordingly and handling things like TLS and potentially authentication. It's definitely an interesting approach, and something I'm curious to try.
- lobster_johnson 11y agoYou'll want to read the whole pitch about Linkerd [1], which the article seems to assume the reader has read. In short, it's a sidecar proxy that performs all the functions needed to glue apps together. This allows apps to be simpler; they can implement a minimal interface and rely on simple protocols such as HTTP, with no knowledge of how to reach their remote partners. Linkerd implements a bunch of techniques such as health checks, load balancing and circuit breakers. [1] https://linkerd.io https://linkerd.io
- ninkendo 11y agoWell, linkerd was what the article was about, so it's what I was referring to. A "sidecar" sounds like the more established term for what I was calling an ambassador proxy, so it's nice to learn that that's what people call this pattern. Your explanation sounds a bit "no duh" though, since I can't imagine any way of implementing this pattern that doesn't abstract away knowledge of how to reach remote partners, perform health checks, load balancing, retry logic, etc. It's generally what the term "proxy" implies. Or am I missing something? Edit: I think my confusion is caused by my experience with running vanilla Mesos (not Marathon or DCOS, but our own custom frameworks), where it's expected that you just have to implement this stuff yourself. I never even thought of open sourcing or productizing what I've written, because I kind of thought that everybody else must be rolling their own quick solutions for these problems too? I admit I'm probably the one with a messed up worldview though. I think the mesos community is still in the phase of picking the winners for best practices, and hopefully one day it'll be obvious that you use services like linkerd and don't roll your own solution.
- lobster_johnson 11y agoApologies, I didn't mean to sound condescending. I think you got it. I just wanted to point you to the official explanation, since you seemed to be asking for clarification as to Linkerd's purpose. A proxy can be a lot of things, of course. Linkerd is explicitly designed to route RPC, not just any web traffic. Linkerd is designed to run close to your app and offload all the routing intelligence. For example, it seems quite common these days to build many types of service discovery and so on into the app itself: App wants to find another microservice, so it looks up the target host in Etcd or ZooKeeper or whatever, then talks to it, handling retrying and load-balancing and so on. If you're using a DNS solution like SkyDNS or Consul, then the app is isolated from the lookup mechanism, but you're still talking directly to your peer. The opposite, older trend is to use something like HAProxy to handle the routing, but HAProxy was designed for a fairly static set of routing targets. Linkerd is a bit of a middle way: Make the app stupid and put all the operational intelligence in an external process that isn't actually your app, but still sort of behaves like it is. Linkerd is designed to be dynamically configured to support all the kinds of glue you can think of (ZooKeeper, Kubernetes and so on) so that no app changes are needed to support different routing schemes.
- rdli 11y agoTo expound on the second approach listed, what I've seen is not just a service discovery layer, but client libraries (as opposed to sidecar) that connect to your service discovery (e.g., Netflix Ribbon which is EOL). Curious what people think of a sidecar approach versus the client library approach? Any preference?