# 为何你应该使用微服务 @( @Yet@)#

<!--category-- Architecture, Microservices, Opinion -->
<datetime class="hidden">2025-12-29T20:00</datetime>

微服务已成为默认的“"”严重系统 “"”架构“MS K2”

如果您想声音“ 成熟” @,, 您可以谈论服务 meshes@ ,事件 Busas *,分布追踪}\ ,和{"独立可调用性>\".如果你想查看企业#-ready,你画框直到图表看起来像一碗意大利面条为止... ...有人扔到白板上...".

但这里 ' 多数初中的矫正者 是' 不给: *

**微服务不是应用程序架构升级 .}它们是一个组织规模战略**

如果您已经有组织上的痛苦, 他们解决了: ,_BARBAR_采用它们很早... ...它不会让你成为未来#'}#-@servict@. 它会使你介绍 @-_Broken_.}

这是理论上的论调 .,它是一个工程行业 就像所有贸易一样 它只有在你明白 你缴纳的税

I'一直像任何人一样有罪 没有完全内部化 组织管理... ...他们带来的.

归根结底,这是软件工程中最古老的模式 **KISS 韩国国际空间服务社** @-# 保持简单 #,#愚蠢的#.#

[TOC]

## 微观服务神话

微服务作为默认结构出售,因为叙述是诱导性:

* 小型服务为 @"_cleaner@"}小服务。
* 分布式系统为 @"modern@"
* 自主是 @" @free@" @%
* 稍后您可以使用“"”缩放“MS K1”,因为您开始使用 “" @right}"

此框架向后@ . @

微缩服务是'}主要有关代码结构的 **谁可以改变什么? , 不和谁说话吗?**.

如果你没有' 就没有:

* 独立运输多队
* 相互冲突的优先事项
* 协调瓶颈
* 部署争议
* 实际所有权边界

{\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}你没有解决组织问题...

架构最终是要帮助人们 @,# 不在@.}周围移动框

## 应该是一个警告标签的图表图

您已经看过LinkedIn 广告微服务课程的图表,

> Ontó:我从那得到真实的图像... ...但我用这个很不方便 所以它删除了...

这不是用于复制“".”的 "%#example 架构

课程通常将微观服务作为图表来教授,因为图表比传授业务责任更容易 #.#

重要的重新组合是此:}该图表不是目标状态@._It\'}a **成本表面**.

每个框都是承诺 :

* 运行的运行时间
* 管理部署
* A. 合同到版本
* 您现在拥有的失败模式
* 一个您可以忽略的关于 -呼叫故事的故事

箭头看起来令人印象深刻 它们也隐藏着现实

因为每一箭头都是:

* 时间间隔
* 部分失败
* 重试
* 超时超时
* 跟踪环境传播
* "" 工作在中场""谎言

如果建筑在第一天需要这个, 您不是正在制造产品\ .}您正在建造一个平台.}

## 微观服务隐藏成本模型

就像所有建筑设计决定一样 ,微服务带来一个 **复杂综合税** (See( MSk0_ see) [使用 Code=:}复杂税游戏](/blog/playing-with-code-efficient-agile)不同之处在于,每个服务边界的税费加在一起 每个任务边界的税率加起来... ...

通常伪装成「"」,

### 业务间接费用

每个服务都想要 :

* 自行建造管道
* 自己的部署配置
* 其本身的监测和警戒
* 其自己的日志@,仪表板 @,运行簿
* 自己的安全姿势(秘书 ,* auth*,* ingress *)

如果团队能顺利地完成此任务,它就会有微服务 **a 配有额外步骤的分布板块。**.

### 延迟和故障乘数

在单曲中 @ , @ 调用是函数调用@ MS K1 @ {

在微观服务中=,a "{call}"}是:}之间谈判的休战

* 网络网
* 负载平衡器
* TLS 电话系统
* 认证中继器
* 序列化
* 超时超时
* 重试
* 后压

失败模式乘以@: @%

* 一个下游是缓慢的 →上游线堆积
* 重试放大负载@→ @DDoS 您自己礼貌点
* 单一依赖性扇形 @→}三种服务会降低@"#irdomly"}

您不再% ' @ t调试错误@ MS K1 @ You debug **系统状态**.

### 连环税,无任何人谈论

微服务宣传几乎从未讨论过这个成本。 **(SerDe)间接费用**.

每个服务边界意指:

```csharp
// Monolith: direct object reference
var user = _userService.GetUser(userId);  // < 1μs
var tier = user.Tier;                      // Memory access

// Microservices: serialize → network → deserialize
var json = JsonSerializer.Serialize(user);        // ~50μs for a complex object
var bytes = Encoding.UTF8.GetBytes(json);         // ~10μs
// ... send over network ...
var responseJson = await response.Content.ReadAsStringAsync();  // ~20μs
var user = JsonSerializer.Deserialize<User>(responseJson);      // ~70μs
var tier = user.Tier;                                           // Finally
```

**网络连线前的纯CPU管理费 .**

现在通过一个呼叫链 乘以此数\:}#

* 命令服务解密请求@(150 @s){}
* 订单服务序列化用户服务请求@(150 @s)}{
* 用户服务解密请求@(150 @s){}
* 用户服务序列响应@(150 @s){}
* 命令服务解除序列化用户响应@(150 @s)}%
* 订单服务序列化
* # …#等等#

**{\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}你花在SerDe身上的** -QQ 且您使用 XML=,Q 协议缓冲, 反射为 @,QQ或低效的连载器@,+乘以#2-10_x.}

是, 您可以使用类似技术来减少这种效果 [“.NET”中的 JSON 源生成](https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/source-generation):

```csharp
[JsonSerializable(typeof(User))]
internal partial class UserJsonContext : JsonSerializerContext { }

// ~30-40% faster than reflection-based serialization
var json = JsonSerializer.Serialize(user, UserJsonContext.Default.User);
```

不过你还在做连环交易 . 你'刚刚把税额 略微便宜一点

#### 一个真实的示例 @: @serde 灾难

我曾在Kubernetes 容器中用此架构描述一个地址搜索系统 @(all@):#

```
ASP.NET API → Go Service (fan-out) → ASP.NET Search Service → Elasticsearch
```

Go Service 处理 fan-out 到多个数据源和汇总结果{.} –项请求都意味着跨越集装箱边界的多重序列跳跃@.

**典型地址搜索的分解@: @%**

* ASP.NET API}: 序列搜索请求 @ → JSON @ MPK3s)#
* 网路@:ASP.NET @→Go @MS K3Vories 按集束载荷=)
* Go Service: 取消请求@ (40sMS K2
* Go Service:Fan out {-}对多个后端的序列请求@(60s _×N后端=)}
* 网络@:QGo @→QASP.NET 搜索 @MS K3#vories%)
* 搜索服务@: @ 解除请求的顺序@ (90 @s @ MS K2}
* 搜索服务@:}构建 Elasticsearch 查詢,}序列化 @(120sMS K3}
* 网络@: @ 搜索 @ → @ Elasticsearch @ I( @ varies) @
* Elastisearch: 解除序列性查询MS K1 执行, 序列结果 * @( 事实搜索@~5ms{, 谢尔德 ~200s})
* 网络@: @ Elasticsearch @ →_ 搜索 @ I( @ varies @ MPK3
* 搜索服务@: @ 解除 ESC 响应@ (300 @s @ MS K2 域模型的地图@ MPK3_ 序列式 @ I(180} @ sQQZMK5}
* 网络@: @ 搜索 @ →Q Go @ MCK2 @ vories @ MPK3 @
* Go Service: 解除所有后端的响应@ (150s @ MS K2N{),}集, 串联 *(80ss□)}
* 网路@:QGo @→QASP#.NET @MS K3vories%)}(网络网路)
* ASP.NET API}: 解除最后回复的顺序

**用于“3-”后端风扇@-_Out @:}**

* 在ElasticSearch 开始之前的 SerDe 总计@: @\ ~2%s
* 集装箱之间的网络顶端@: @ @ @ ~2-3_%s
* 实际搜索@+ @ 商业逻辑 @ :} @ I~6 @ ms

**我们花在Serde身上的时间 几乎和实际搜索时间一样长**

成本是“Go”服务本身的“-”粉丝“-“Out”, **服务边界**“每个集装箱边境”是指序列式的“→”网络 `→' 取消航班 ‘.’

在一个独角兽做同样的粉丝\-}逻辑_:

* Same 弹性搜索查询
* 相同的汇总逻辑
* {\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}无对接的-=Serse SerDe (_Just方法调用
* 减总潜伏

此成本@:

* 具有对象复杂度的天平@ ( @ nested 物件 @ MS K1_ 收藏@ MPK2 多形态=)}
* 具有呼叫深度的复合物 @(#服务链 #)#
* 刻录每份请求的 CPU@ ( @ can @ MS K1 @ t 缓存@ MPK2
* 增加字符串 @ / @ byte 数列@ MS K2}的GC 压力
* **当您每秒做上百个请求时, 添加速度会加快**

在单体中=,}此成本为 0 .}该对象已经在内存@.}*

### 性能传说=:}通过传输 vs.}可缩放性

在这里,' 常见的销售投放: " Microservices 改善性能."

**这是向后@ . @**

微服务是 **较慢** 同样的计算资源@. @ Let'_%s 请精确地说明我们指的是什么 @:}

**投入流量** ( 要求每秒 CPU 核心@):

- **单极**-=YTET -伊甸园字幕组=- 翻译:
- **微观服务**: 下Q- SerDe subject *,网络升空*,集装箱管弦

**缩缩** @(_ 能够通过添加资源来处理更多总的要求@):}

- **单极**由垂直缩放的(Bigger机械有限公司 )
- **微观服务**: 水平- 添加更多的瓶颈服务实例

微服务让你 **独立缩放**. 如果您的库存服务需要@10x 资源, 但您的用户服务却需要 @'t, 您可以分别缩放@MS K4, 那#'值 **需要时**.

但它不是一种性能优化 **衡量战略**加上税单和税收

#### 现代单体可缩放

“"”和“Microservices size messions level better @"”的论点在“2010”中更有意义,当服务器有‘4-8’核心{\.#

现代服务器有“32-128Cores.” 一个单一的机器可以运行数千个同步操作

如果您的整块石碑是用现代同时执行模式建造的 @ ,, 它可以处理一个单一部署中的大型输送量@ MS K1 例如: @ I, [早期执行协调员](/blog/ephemeral-execution-library),可以吗?

```csharp
// Process thousands of concurrent operations in a monolith
services.AddEphemeralWorkCoordinator<TranslationRequest>(
    async (request, ct) => await TranslateAsync(request, ct),
    new EphemeralOptions { MaxConcurrency = Environment.ProcessorCount * 4 });

// Bounded, observable, efficient concurrent processing
// No network overhead, no SerDe, no container orchestration
// Can handle 10k+ req/sec on a single machine
```

这给了您@ : @ @

- **平行主义**“: ” 所有核心的工作同时进行。
- **可观察性**@ :_ 音轨待处理@ MS K1 active @ MPK2} 操作失败
- **后压**: 环形队列防止内存耗竭
- **零间接费用**@ :_ 没有序列化@ MS K1}没有网络 * , 没有分布式跟踪

当你 **do 做** 需要将比例缩放超过一台机器@, @ 您可以 @ :} @

1. 在负载平衡器 {(} 背后运行多个实例。 MSKO} 无静止水平缩放})
2. 使用发件箱模式进行同步工作分布
3. 由密钥 {(} 开关者 ID ,} 区域 @ MS K2} 等.)} 设置的分区

你仍然在运行一个全垒打 . -你刚刚安装过它多次

**要点**@ :_ Don'} t 分裂为微服务, 用于 properation@ ".} 当分割时 **具体组成部分的独立缩放** 业务间接费用说明 *.*

### 认知负载

缩微服务会减少复杂性 . 他们重新分配它

@"_simple service\ "}仍然需要上下文@:

* 谁叫它'?
* “"”正确“"”是指什么?
* 当它下降时会发生什么?
* 什么是'? 反弹计划吗?
* 什么是' 依附圖@?

人们低估了这一点 因为图表隐藏着它 .

### 版本和合同

每条边界都成为契约 .  
每份合约都成为#:

* 版本规则
* 兼容性保证
* 表表演变制约因素
* 你假装你没有做过 协调管理

你可以躲一阵子 和"一起部署一切

如果你把所有东西都一起部署... ...你建造了一座全垒打...

### 工具比值前

早期支出总是相同,

* 服务发现
* 秘密管理
* 分布追踪跟踪
* 中央集中采伐
* 计量和警报
* CD 模板
* 本地的 Dev 故事很痛苦 @'#
* 依赖性管理
* 一种不哭而无所事事的方法

这些船只没有产品价值 . *

大多数团队在证明产品应该具有复杂性之前 都这样做了

这是中心错误 : **您在缴纳手续税前,先缴登记费 '_#已经挣得价值**类似 [浪费时间、不交付对齐的日常站点](/blog/agile-standups-ceremony-tax)“,微服务可以成为仪式架构”“: 令人印象深刻,

这些成本合在一起, 使得本组织是否首先需要微服务更加复杂。

## 人类和团队

帮助人类群体安全改变软件的架构@. @%

不是为了给其他工程师留下深刻印象  
无法满足图表@. @%  
不是为了证明一个平台团队的正当性... ...你没有'也没有.

团队规模和部署集结比模式目录更加重要@.

* 如果一个团队拥有整个路线图“, ” , 一个石碑通常会更快更安全。 “. ”
* 如果您仍能理解系统末端 @- @to@ -_ end @ MS K2# 微服务将会降低清晰度 @ MPK3 @
* 如果您没有 ' @t 有稳定的所有权边界@,}微服务将会通过 APIs @-#来强制协调。 这是可用的最慢的协调机制=.}

**康韦涅茨-' 法律是't可选}. 它's物理=.**

您的架构将反映您的通信结构, 不论您喜不喜欢@. @ @ @

Microsservicesdon't 创建自主性 . 他们需要它\MS K2}

## 捍卫模块垄断

大多数系统应该以一元制开始 .,但不是草率的

AA **模块化单石** 是:

* 1个部署单位
* 一次性一次
* 调试一个地方
* 一种一致的状态观点
* 但有真正的内部边界

意思是:

* 具有明确依赖性的域模块
* 代码中清晰的拥有权
* 没有" "所有的东西都参考了一切"
* 在代码基内执行的合同

关键在于永远保持单一性 **在将边界移到远处之前,要先赚钱**.

一个模块化的单一石块迫使你学习技能微型服务 假装解答:

* 域建模@(real 边框 @,}不是文件夹边框_)
* 我们做了一个服务 ")
* 适用性
* 更改学科
* 知道你的系统实际上做了什么

**如果您能建立干净的模块化单元@ , @ 微服务胜出 @ MS K2 @ t保存您@ I. @ 他们# '} 会分发 messQZMK5 @**

### 古德单人设计@: 稍后的缩放模式

正确的石碑设计让您可以 **推迟微观服务决定** 不把自己锁在 .

#### 发件箱模式@: @Async 无分发

最好的例子之一是 **发箱模式** - 实现最终一致性和同步处理的方法 *内* 以干净的路径发送后@ . {一元% 1}

而不是:

```csharp
// Tightly coupled synchronous code
public async Task PlaceOrder(Order order)
{
    await _orderRepo.Save(order);
    await _emailService.SendConfirmation(order);  // Blocks on external service
    await _inventoryService.Reserve(order.Items); // Blocks on another service
}
```

你写了:

```csharp
// Outbox pattern: write events to a table
public async Task PlaceOrder(Order order)
{
    await using var transaction = await _db.Database.BeginTransactionAsync();
    
    // Save order
    await _orderRepo.Save(order);
    
    // Write events to outbox table (same transaction)
    _db.OutboxMessages.Add(new OutboxMessage
    {
        EventType = "OrderPlaced",
        Payload = JsonSerializer.Serialize(order),
        CreatedAt = DateTime.UtcNow
    });
    
    await _db.SaveChangesAsync();
    await transaction.CommitAsync();
    
    // Background worker picks up outbox events and publishes them
}
```

**这给了你什么 :**

* **交易一致性**@:事件和数据 共同承诺或根本不承诺
* **拆脱**:Email/instistical 逻辑运行 Async, donsMS K3t 区块顺序创建
* **可靠性**即便下游系统下降,事件仍会持续。
* **清洁抽取路径**Kafka@/ @RabbitMQ 不改变顺序逻辑,

缩略 [CEPOE 商业抽样项目](/blog/zero-pii-customer-intelligence-part2) 显示这种生产模式

```csharp
// Mostlylucid.SegmentCommerce/Services/Queue/PostgresOutbox.cs
public class PostgresOutbox
{
    public async Task PublishAsync<T>(string eventType, T payload)
    {
        var message = new OutboxMessage
        {
            EventType = eventType,
            Payload = JsonSerializer.Serialize(payload),
            CreatedAt = DateTime.UtcNow
        };
        
        _db.OutboxMessages.Add(message);
        // Caller commits transaction
    }
}

// Background service
public class OutboxProcessor : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            var pending = await _db.OutboxMessages
                .Where(m => !m.Processed)
                .OrderBy(m => m.CreatedAt)
                .Take(100)
                .ToListAsync();
                
            foreach (var message in pending)
            {
                await ProcessMessage(message);
                message.Processed = true;
            }
            
            await _db.SaveChangesAsync();
            await Task.Delay(1000, stoppingToken);
        }
    }
}
```

当您需要缩放“ :” 时, 此程序在今天的单一个应用程序中运行@ . @ {}

1. 将背景工人替换为信息公共汽车消费者
2. 将发件箱事件发布到 Kafka @ / @\ RabbitMQ, 而不是本地处理
3. **命令设置代码不更改@' @ t改变**

您在未缴纳分配税的情况下 建造了微型服务设施 - 已具备基础设施

#### 值得早期做的其他模式

* **CQRS ( 轻 )**: 单独读@/write 模型, 即使它们共享 DB
* **事件源源@( @ 选择性 @ ) @**仅用于审计的-关键实体
* **特别标志旗帜**: 十二月 解除部署
* **背景工作**: 唐' t 区块请求@, 进程同步c

所有这些都使得分发更加容易。

## 当微服务 实际产生感知

微小服务在现实的制约下就有意义了,

关键的问题是:我们是否应该使用微服务? **利润是否超过营业税?**

喜欢选择 [小型当地模型和边际LMS](/blog/small-models-not-budget-option)@,这是关于理解复杂性属于何方, 以及您能负担的失败模式@.#

### 好触发器

* **团队争议是可衡量的**团队每周互相阻拦
* **有必要进行独立部署**: 释放通道每个域的不同
* **比例分布不均**一个子系统需要 10x资源和隔离
* **与故障隔离相关的事项**其中一个部件不能拿下其余的
* **数据隔离是强制性的**:邊界是'T可流通的
* **Org 结构已经是多@ - @ team**拥有权的存在和稳定

### 坏触发器

* ",我们或许可以放大"
* @"Netflix做它#"
* -=YTET字幕组=- 翻译:
* ~ 它看起来不错~
* @"#我们的整块石头乱七八糟的 @MSC1}所以我们该用分割的方式来修补它

**如果你的理由包含字词 *中*, *最终最终*,或 *未来#-_*@, @ it@ '_%s maybe not a reason#.}也许不是一个原因**

## 技术现实: 什么是微观服务实际成本

让' @%s得到混凝土@ . @ here @ MS K2}当您将一个整块分割成服务时会有什么变化吗? @ I. @

### 呼叫链和延迟

**单人+:**

```csharp
public async Task<Order> PlaceOrder(OrderRequest request)
{
    var user = await _userService.GetUser(request.UserId);
    var inventory = await _inventoryService.CheckStock(request.Items);
    var price = _pricingService.Calculate(request.Items, user.Tier);
    
    var order = new Order { /* ... */ };
    await _orderRepository.Save(order);
    await _emailService.SendConfirmation(order);
    
    return order;
}
```

时间总长度=: ~50%s @(in}-}进程呼叫@+#2DB查询)

**微服务=:**

```csharp
public async Task<Order> PlaceOrder(OrderRequest request)
{
    // HTTP call to User Service (network + TLS + serialization)
    var user = await _httpClient.GetAsync<User>($"http://user-service/users/{request.UserId}");
    
    // HTTP call to Inventory Service
    var inventory = await _httpClient.PostAsync<StockResult>(
        "http://inventory-service/check", request.Items);
    
    // HTTP call to Pricing Service
    var price = await _httpClient.PostAsync<PriceResult>(
        "http://pricing-service/calculate", 
        new { items = request.Items, tier = user.Tier });
    
    // HTTP call to Order Service
    var order = await _httpClient.PostAsync<Order>(
        "http://order-service/orders", request);
    
    // Event published to message bus
    await _messageBus.Publish(new OrderPlaced { OrderId = order.Id });
    
    return order;
}
```

@~400#ms@(_even opsitial as mission per HTTP call in real environment *= +}*信息总线 发布 #~20#ms%s)#

**你得到了什么 :**

* 每个服务单位都可独立部署
* 库存和定价可以与命令分开划分
* 在电子邮件中失败 {'} t区块命令创建@ (_ async event*\ MS K2}

**你付了多少钱 :?**

* *~8*x 延时增加
* 4新的故障点 @(}任何服务都可以降低@/slow#)}
* 网络% , DNS, TLS 每通电话的间接费用
* **序列化@/_** *(* 见前一节*)*
* 需要重试逻辑@,断路器 @,超时
* 分布到调试失败的追踪

### 处理爆炸出错

**处理单词错误@ :**

```csharp
try
{
    var order = await PlaceOrder(request);
    return Ok(order);
}
catch (InsufficientStockException)
{
    return BadRequest(new { error = "Out of stock" });
}
catch (Exception ex)
{
    _logger.LogError(ex, "Order placement failed");
    return StatusCode(500);
}
```

**处理 Microservice 错误处理@: @%**

```csharp
try
{
    // Call User Service
    var user = await _httpClient.GetAsync<User>($"http://user-service/users/{request.UserId}");
}
catch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.NotFound)
{
    return NotFound(new { error = "User not found" });
}
catch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.ServiceUnavailable)
{
    // Retry with exponential backoff?
    // Circuit breaker opened?
    // Fail fast or degrade gracefully?
    _logger.LogWarning("User service unavailable, retrying...");
    await Task.Delay(TimeSpan.FromMilliseconds(100));
    // ... retry logic ...
}
catch (TaskCanceledException ex)
{
    // Timeout - was the request processed? Do we retry?
    _logger.LogError("User service timeout");
    return StatusCode(503, new { error = "Service temporarily unavailable" });
}

try
{
    var inventory = await _httpClient.PostAsync<StockResult>(
        "http://inventory-service/check", request.Items);
}
catch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.BadRequest)
{
    // Business error from remote service
    var errorDetails = await ex.Content.ReadAsAsync<ErrorResponse>();
    return BadRequest(new { error = errorDetails.Message });
}
catch (HttpRequestException ex)
{
    // Which service failed? Network issue? Service down?
    // Do we have a fallback? Cached data? Fail fast?
    _logger.LogError(ex, "Inventory service failed");
    // Maybe try a backup instance?
    // ... more retry logic ...
}

// And repeat for every service call...
```

每个网络呼叫都介绍:

* 超时超时设想
* 网络失败
* 服务不可用
* 部分故障@( @ request sent *\ ,}回复未收到 @)
* 重试扩音@ ( @ 您的重试可能会触发他们的重试@ I)} @
* 传播的交易恶梦

### 部署协调

**单体部署@: @%**

```bash
# Build
dotnet publish -c Release

# Run migrations
dotnet ef database update

# Deploy
docker push myapp:v1.2.3
kubectl set image deployment/myapp myapp=myapp:v1.2.3

# Rollback if needed
kubectl rollout undo deployment/myapp
```

**微服务部署+:**

您正在更改顺序结构 @ ._ 现在 `Order` 包括 `UserTier` 直接@( @% 由于性能失常 @ ).#

```bash
# 1. Deploy Pricing Service v2 (understands both old and new Order format)
kubectl set image deployment/pricing-service pricing-service=pricing:v2.0.0

# 2. Wait for rollout and monitor
kubectl rollout status deployment/pricing-service
# Check metrics - is v2 working with old order format?

# 3. Deploy Order Service v2 (starts sending new format)
kubectl set image deployment/order-service order-service=order:v2.0.0

# 4. Monitor for errors
# If Pricing v2 has a bug, you can't just rollback Order service
# You have to rollback both in reverse order

# 5. Deploy User Service v2 (stops including tier in response)
# But wait - old Order Service instances might still be running!
# Need zero-downtime rollout or maintain backward compat

# 6. Eventually clean up old code paths in Pricing Service v3
# (6 months later because you're scared to remove backward compat)
```

随着微服务=,}每处变化都跨越多种服务 ~.}合同的演变需要\:

* 后向兼容窗口
* 跨服务处的特色旗帜
* 协调推出
* 扩展测试矩阵@(Servicice A v1 @ @+服务 B v2,Av2#+服务B v□1,等}.)

但是这需要纪律 , 工具 MS K2 和体验 大多数球队在经历多年疼痛后才能赚钱

### 调试经验

**单词错误报告@: @%** @"_Order 配置失败,

```csharp
// Set breakpoint in PlaceOrder
// Step through each call
// User tier is null - ah, there's the bug
// Fix, test, deploy
```

**微服务错误报告@: @%** @"_Order 配置失败,

```bash
# 1. Check logs - which service failed?
kubectl logs -l app=order-service --tail=100

# 2. Oh, it's calling Pricing service. Check those logs
kubectl logs -l app=pricing-service --tail=100

# 3. Grep for correlation ID across all services
stern -l app=order-service,app=pricing-service,app=user-service \
  | grep "correlation-id-xyz"

# 4. Reconstruct the call chain from distributed traces
# Open Jaeger/Zipkin, find the trace
# User service returned 200 OK
# Pricing service returned 400 Bad Request
# Error: "user.tier is required"

# 5. Check User service - did it send tier?
# Look at schema version - ah, User v1.2 stopped sending tier
# When did that deploy? Was Pricing service updated?

# 6. Check API contracts
# Pricing expects tier, User stopped sending it
# Who approved this change?

# 7. Fix requires coordinating two teams
# Can't just deploy a fix - need contract negotiation
```

这就是现实 : **@ 5-_ minute fixes become moto MS K1}% team recountry 调查中的错误。**.

如果这听起来很极端的话... ...很好,....

## 如何安全地发展? :?

微服务是一扇门 - 门 . 对待它们像一个. *

安全通道看起来很无聊 :

### “1. 验证边界第一”

如果您能在单体内绘制可执行的依附性“(”内的边界, 您可以在“ '” 中安全提取“ I.” 。

将接缝移到本地,

### 2. 写前解读

读起来比较简单@: @%

* 较少的变量
* 减少一致性要求
* 减少恶梦

如果您需要分离, 请先移动读取模型@ . @

### 3. 同步前预置的 Async

同步服务呼叫创建了依赖连锁链@. @%

Async 消息创建@: @%

* 缓冲
* 复原力
* 分离可以活下来

以区分事件和事实为起点 @,}而不是切除终点@.

### 4. strangle,唐MS K2 t重写

没有大爆炸 .  
没有 "W'L 将正确重写@".#

切开边界 , 测量它 MS K1 拥有它 I, 继续前进\.

**如果您能解释为什么独立存在服务@ , @ 它应该# ' @ t**

## 外卖 : 微服务只支付 如果你了解交易的话

微服务不是起点 . 它们是一个结果

**应该赚到复杂性 .** 分配系统不是徽章 @-}它们是一种债务工具_.

折叠式对等法很简单

```
Microservices Value = (Team Autonomy + Independent Scaling + Failure Isolation)
                     - (Latency Tax + SerDe Tax + Operational Overhead + Coordination Cost)
```

对于大多数团队来说, “- ” 尤其是早期的“- 阶段”或者单子的“-”或“Team Products ” “MS K3 ” 右翼主宰着“. ” 你付出了巨大的代价来获取你所需要的利益。

但当你有:的时候

* 球队互相踩脚踏脚
* 以天数计量的部署队列
* 规模化需求大相径庭的子系统
* 数据隔离的监管要求

左派开始赢. 税收变得合理

### 决定框架

问这些问题的顺序

1. **球队能否继续拥有这个终点?**  
   {\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}请考虑分开

2. **球队被彼此阻塞 ' 释放周期**  
   微服务或许能帮助您 . @No:}协调工作#.

3. **我们是否有操作肌肉来运行分布式系统? ?**  
   {\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}不 不 : *

4. **我们能否追踪到", debug," 并部署多种服务 没有英雄的"MS K2"**  
   @→ @No#:}你还没准备好吗? .@是的,:*

5. **我们已经在代码中证明边界了**  
   @ → @ no: @ 修正您的整块结构@ MS K2 @ 是□ :} 提取更安全@ MPK4 @

如果您能有信心地过问 3Q@, @你没有准备好接受微服务 @-}(如果您不能做好微服务的准备)和"'\ZS fine=.# **无聊的建筑是一种竞争优势**

最成功的产品是作为一元制制造的,首先是:GitHub,SportifyMS K2Stack Overflow,Basecamp}.它们演变成分布式系统 只有当组织痛苦要求它做时 它们才会进化为分配式系统

您的工作是“ ' @ t” 来构建最令人印象深刻的架构@ MS K1 @ it'} 在最小化意外复杂性的同时提供值@ I. @

也没有客户因为你的系统使用Kafka.而支付额外费用。

有时这意味着微服务 . 通常是指, 意指井- 结构化的石碑和保持它的方式的纪律\. *