微服务应该形成多叉树结构。
Microservices should form a polytree

原始链接: https://bytesauna.com/post/microservices

## 微服务与多树原则 微服务虽然在理论上很有吸引力,但常常导致复杂且难以管理的系统。团队经常遇到级联故障和开发速度减慢,原因是隐藏的依赖关系和错综复杂的职责。为了缓解这个问题,作者建议将微服务结构化为**多树**——一种有向无环图,形成树状的依赖结构。 多树强制执行清晰的层级结构,服务可以依赖于其*上层*的服务,但不能反过来,从而消除了有害的循环依赖。这可以防止分布式状态、故障回声和资源用量失控等问题。有向和无向循环都被 discouraged,因为即使是看似干净的架构也可能导致容错性降低和调试困难。 多树提供诸如清晰的数据所有权、可预测的故障模式、更容易的新工程师上手以及更安全的服务独立演进等好处。这种结构的数学特性——无环性和明确的层级关系——转化为运营清晰度,以及更易管理、更健壮的系统。本质上,多树原则为微服务架构提供了一条简单而明确的规则,优先考虑简单性并防止架构漂移。

## 微服务与多树架构 - 摘要 最近的 Hacker News 讨论围绕一篇提倡微服务使用“多树”结构而非更开放的网络结构的博文展开。核心思想是避免无向依赖循环,并力求一种分层、平面图,其中依赖关系按线性方式扩展。 讨论强调,严格遵守这种模式并不总是实用的。许多人认为服务应该具有完善接口的独立性,无论连接拓扑如何。当多个服务依赖于单个服务时,就会产生担忧——质疑该共享服务是否正在变得像单体应用。 评论者们争论了重构以消除循环在添加节点时会变得复杂的情况,并质疑如何在实际应用中强制执行这种结构,因为服务间通信通常是必要的(例如,用于身份验证或共享工具)。这个概念被比作避免代码中的循环依赖,并强调了多树结构的优势——线性扩展。最终,讨论指出架构纯粹性和实际实施之间存在权衡。
相关文章

原文

Microservices are a treacherous path. On paper, they look wonderful: small, focused components; independently deployable units; clean, well-defined interfaces. What could go wrong?

Plenty.

Teams often discover that a system that began as a tidy collection of services has quietly evolved into an Armageddon of impossible-to-trace failures and a painfully slow development experience. Microservices are easy to get wrong and a great way to cause infinite pain. They introduce complexity that has the unfortunate tendency to sneak up on you: you add a call here, expose a tiny API there, share a bit of logic “to stay DRY,” and before you know it, the whole thing is a mess.

To avoid this situation in advance, I propose the following principle: microservices should form a polytree.

This is an intentionally strict criterion. Simple enough to enable fast decision-making. The fact is that most teams do not have the time or appetite for endless architecture debates. They just need a straightforward check base for go/no-go decisions on.

What is a polytree

A polytree is a specific type of graph. Stated in precise terms, it's a directed acyclic graph whose underlying undirected graph is a tree. So, for example, this is a polytree:

In order to check that this graph satisfies the definition of a polytree, notice that there are no directed cycles. Also the underlying undirected graph is connected and acyclic, i.e. a tree:

What I mean by microservices should form a polytree is that the dependence structure between the services should be a polytree. So for example, in the case of the above graph, n1 may call n3, but n3 may not call n1.

This rules out painful situations I'll highlight next.

What is not a polytree

For this post, it's important to highlight why a graph may fail to be a polytree, and to explain why excluding such structure is a good idea.

Counterexample #1: A directed cycle

One great way to mess up a microsevice architecture is to create a cyclical dependency structure such as this one:

Theoretically, this exposes you to endless issues:

  • State becomes delocalized. When services in a cycle all read and write pieces of the same conceptual state, no one service has clear ownership. This makes development and debugging potentially difficult.
  • Failures may echo around the cycle, as each service triggers the next.
  • Resource usage can spiral, as services retry or hold open connections while waiting for responses that depend on their own work.

Fix: Cycles are a symptom of tangled responsibilities. Perhaps the services n1, n2 and n3 could be a single one. Sometimes functionality should be rearranged so that they form a tree instead.

Counterexample #2: An undirected cycle

A sneakier one is a dependency structure, where there is no directed cycle, but the underlying undirected graph is cyclical.

Even without a directed cycle this kind of structure can still cause trouble. Although the architecture may appear clean when examined only through the direction of service calls the deeper dependency network reveals a loop that reduces fault tolerance increases brittleness and makes both debugging and scaling significantly more difficult.

Fix: This is, again, a sign of tangled responsibilities. Two ideas to consider are should n2 and n3 be a single service or should n4 actually be two different services.

Why polytrees are nice

A polytree structure enforces a clear, hierarchical flow of responsibility. This brings several practical benefits:

  • Clear ownership of state. Each piece of data or behavior has a single, unambiguous home. When something breaks, you know exactly where to look.
  • Predictable failure modes. A failure at a node can only hit nodes below, and it must terminate after a finite number of steps.
  • Simpler reasoning and onboarding. New engineers can understand the system by starting at the leaves and working upward. No complex back-and-forth call chains to unravel.
  • Independent evolution. With no hidden cycles, teams can change, version, or redeploy services with far less risk of surprising breakage.

A polytree’s practical advantages flow directly from its mathematical structure. Because a polytree is a directed acyclic graph whose edges impose a partial order, every node has a well-defined position in a hierarchy. That same partial order also enables a clean mental model for engineers as reasoning can proceed inductively from leaves upward, with each component depending only on a finite, well-bounded set of predecessors. The shape of the structure does most of the conceptual work.

The acyclicity of polytrees also ensures that all flows terminate: whether we are talking about failure propagation, data updates, or event handling, everything moves according to the partial order and must reach a leaf or a root after a finite number of steps. This rules out feedback loops, oscillations, and other emergent behaviors that make systems unpredictable and fragile. As a result, teams can evolve different branches of the system independently, knowing that changes remain confined to their downstream cones and cannot sneak back indirectly. The mathematical properties (no cycles, unique paths, and guaranteed termination) translate almost one-to-one into operational clarity, predictable behavior, and ease of evolution.

联系我们 contact @ memedata.com