<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>微服务 on </title>
    <link>https://note.lican.site/tags/%E5%BE%AE%E6%9C%8D%E5%8A%A1/</link>
    <description>Recent content in 微服务 on </description>
    <generator>Hugo</generator>
    <language>en</language>
    <copyright>© lican.asia All rights reserved</copyright>
    <lastBuildDate>Tue, 06 Oct 2020 12:44:10 +0800</lastBuildDate>
    <atom:link href="https://note.lican.site/tags/%E5%BE%AE%E6%9C%8D%E5%8A%A1/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>带你快速了解：限流中的漏桶和令牌桶算法</title>
      <link>https://note.lican.site/posts/posts/microservice/leaky-token-buckets/</link>
      <pubDate>Tue, 06 Oct 2020 12:44:10 +0800</pubDate>
      <guid>https://note.lican.site/posts/posts/microservice/leaky-token-buckets/</guid>
      <description>&lt;p&gt;在前文 《限流熔断是什么，怎么做，不做行不行？》中针对 “限流” 动作，有提到流量控制其内部对应着两种常用的限流算法，分别是漏桶算法和令牌桶算法。因此会有的读者会好奇，这都是些啥？&lt;/p&gt;&#xA;&lt;p&gt;为了更进一步的了解 WHY，本文来快速探索一下，看看限流下的一些 “算法” 们到底有何作用，是为何成为流量控制的基石的？&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.eddycjy.com/815f7524b5367149cc9c6725ee28cd12.jpg&#34; alt=&#34;image&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;前言&#34;&gt;前言&lt;/h2&gt;&#xA;&lt;p&gt;理论上每一个对外/内提供功能的资源点，都需要进行一定的流量控制，否则在业务的持续迭代中，是有可能出现突发性流量的场景（就像年初所带来的一些行业突发转变，导致业务流量突然暴增）：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.eddycjy.com/c29272e53f9e125dbbfba133b3eea7c4.jpg&#34; alt=&#34;image&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;若没有进行限流，就会出现一些奇奇怪怪的问题点，实则就是系统无法承受这波流量，逐渐崩溃，走向系统假死。&lt;/p&gt;&#xA;&lt;h2 id=&#34;现实场景&#34;&gt;现实场景&lt;/h2&gt;&#xA;&lt;p&gt;最常见的现实场景就是日常随处可见的排插、插座，其内置的保险丝，也被称为电流保险丝，其主要是起过载保护作用，保险丝会在电流异常升高到一定的高度和热度的时候，自身熔断切断电流，从而起到保护电路安全运行的作用。&lt;/p&gt;&#xA;&lt;p&gt;因此真实世界中有许多与软件工程中的限流熔断的场景有异曲同工之处，也是为了控制量，超量就切断。你也可以想想现实生活中是否有遇到其他类似的例子呢？&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.eddycjy.com/23af65486fc991e1bd976c37626ccf18.jpg&#34; alt=&#34;image&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;漏桶算法leaky-bucket&#34;&gt;漏桶算法（Leaky Bucket）&lt;/h2&gt;&#xA;&lt;p&gt;漏桶算法（Leaky Bucket）是网络中流量整形（Traffic Shaping）或速率限制（Rate Limiting）时常用的一种算法，它的主要目的是控制数据注入到网络的速率，平滑网络上的突发流量。&lt;/p&gt;&#xA;&lt;p&gt;漏桶算法通过其算法调控了流量访问，使得突发流量可以被整形，去毛刺，变成一个相对缓和，以便为网络提供一个稳定的流量。&lt;/p&gt;&#xA;&lt;p&gt;漏桶算法的存储桶主要由三个参数定义，分别是：桶的容量、水从桶中流出的速率、桶的初始充满度。&lt;/p&gt;&#xA;&lt;p&gt;其核心理念就如字面意思：一个会漏水的桶。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.eddycjy.com/386bdd6a907a2130f5bfa74696817221.jpg&#34; alt=&#34;图片来自 geeksforgeeks&#34;&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;bursty-flow&#34;&gt;Bursty Flow&lt;/h3&gt;&#xA;&lt;p&gt;在上图中，水龙头代表着突发流量（Bursty Flow）。当网络中存在突发流量，且无任何调控时，就会出现像 Bursty Data 处类似的场景。主机以 12 Mbps 的速率发送数据，时间持续 2s，总计 24 Mbits 数据。随后主机暂停发送 5s，然后再以 2 Mbps 的速率发送数据 3s，最终总共发送了 6 Mbits 的数据。&lt;/p&gt;&#xA;&lt;p&gt;因此主机在 10s 内总共发送了 30 Mbits 的数据。但这里存在一个问题，就是数据的发送并不是平滑的，存在一个较大的波峰。若所有流量都是如此的传输方式，将会 “旱的旱死涝的涝死”，对系统并不是特别的友好。&lt;/p&gt;&#xA;&lt;h3 id=&#34;fixed-flow&#34;&gt;Fixed Flow&lt;/h3&gt;&#xA;&lt;p&gt;为了解决 Bursty Flow 场景的问题。漏桶（Leaky Bucket）出现了，漏桶具有固定的流出速率、固定的容量大小。&lt;/p&gt;&#xA;&lt;p&gt;在上图中，漏桶在相同的 10s 内以 3 Mbps 的速率持续发送数据来平滑流量。若水（流量）来的过猛，但水流（漏水）不够快时，其最终结果就是导致水直接溢出，呈现出来就是拒绝请求/排队等待的表现。另外当 Buckets 空时，是会出现一次性倒入达到 Bucket 容量限制的水的可能性，此时也可能会出现波峰。&lt;/p&gt;</description>
    </item>
    <item>
      <title>限流熔断是什么，怎么做，不做行不行？</title>
      <link>https://note.lican.site/posts/posts/microservice/flowcontrol-circuitbreaker/</link>
      <pubDate>Mon, 05 Oct 2020 13:24:16 +0800</pubDate>
      <guid>https://note.lican.site/posts/posts/microservice/flowcontrol-circuitbreaker/</guid>
      <description>&lt;p&gt;“在分布式应用中，最常见的问题是什么呢？”&lt;/p&gt;&#xA;&lt;p&gt;“一个分布式应用部署上去后，还要关注什么？”&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.eddycjy.com/8c42e87dd4f7f1c59431c6185f608699.png&#34; alt=&#34;image&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;“这服务的远程调用依赖似乎有点多&amp;hellip;”&lt;/p&gt;&#xA;&lt;h2 id=&#34;前言&#34;&gt;前言&lt;/h2&gt;&#xA;&lt;p&gt;在 &lt;a href=&#34;https://eddycjy.com/posts/microservice/linkage/&#34;&gt;《微服务的战争：级联故障和雪崩》&lt;/a&gt;中有提到，在一个分布式应用中，最常见，最有危险性之一的点就是级联故障所造成的雪崩，而其对应的解决方案为&lt;strong&gt;根据特定的规则/规律进行流量控制和熔断降级&lt;/strong&gt;，避免请求发生堆积，保护自身应用，也防止服务提供方进一步过载。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.eddycjy.com/79a7f8870edffd331432272cf5db2c46.jpg&#34; alt=&#34;image&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;简单来讲就是，要控制访问量的流量，要防各类调用的强/弱依赖，才能保护好应用程序的底线。&lt;/p&gt;&#xA;&lt;h2 id=&#34;诉求期望&#34;&gt;诉求，期望&lt;/h2&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;诉求：作为一个业务，肯定是希望自家的应用程序，能够全年无休，最低限度也要有个 4 个 9，一出突发性大流量，在资源贫乏的窗口期，就马上能够自动恢复。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;期望：万丈高楼平地起，我们需要对应用程序进行流量控制、熔断降级。确保在特定的规则下，系统能够进行容错，只处理自己力所能及的请求。若有更一步诉求，再自动扩缩容，提高系统资源上限。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;解决方案&#34;&gt;解决方案&lt;/h2&gt;&#xA;&lt;p&gt;要如何解决这个问题呢，可以关注到问题的核心点是 “系统没有任何的保护的情况下”，因此核心就是让系统，让你的应用程序有流量控制的保护。一般含以下几个方面：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;来自端控制：在业务/流量网关处内置流量控制、熔断降级的外部插件，起到端控制的效果。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;来自集群/节点控制：在统一框架中内建流量控制、熔断降级的处理逻辑，起到集群/节点控制的效果。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;来自 Mesh 控制：通过 ServiceMesh 来实现流量控制、熔断降级。侵入性小，能带来多种控制模式，但有利有弊。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;以上的多种方式均可与内部的治理平台打通，且流量控制、熔断降级是不止面试应用程序的，就看资源埋点上如何设计、注入。常见有如下几种角度：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;资源的调用关系：例如远程调用，像是面向 HTTP、SQL、Redis、RPC 等调用均，另外针对文件句柄控制也可以。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;运行指标：例如 QPS、线程池、系统负载等。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;流量控制&#34;&gt;流量控制&lt;/h2&gt;&#xA;&lt;p&gt;在资源不变的情况下，系统所能提供的处理能力是有限的。而系统所面对的请求所到来的时间和量级往往是随机且不可控的。因此就会存在可能出现突发性流量，而在系统没有任何的保护的情况下，系统就会在数分钟内无法提供正常服务，常见过程为先是出现调用延迟，接着持续出现饱和度上升，最终假死。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.eddycjy.com/6a58406bb7c90355c82c5cb50f417f9a.jpg&#34; alt=&#34;image&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;流量控制一般常见的有两种方式，分别是：基于 QPS、基于并发隔离。&lt;/p&gt;&#xA;&lt;h3 id=&#34;基于-qps&#34;&gt;基于 QPS&lt;/h3&gt;&#xA;&lt;p&gt;最常用的流量控制场景，就是基于 QPS 来做流控，在一定的时间窗口内按照特定的规则达到所设定的阈值则进行调控：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.eddycjy.com/58f0d6fe0043963f6e40c1d73c8e019e.jpg&#34; alt=&#34;image&#34;&gt;&lt;/p&gt;&#xA;&lt;h4 id=&#34;案例&#34;&gt;案例&lt;/h4&gt;&#xA;&lt;p&gt;在本文中借助 &lt;a href=&#34;https://github.com/alibaba/sentinel-golang&#34;&gt;sentinel-golang&lt;/a&gt; 来实现案例所需的诉求，代码如下：&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;import (&#xA;&#x9;...&#xA;&#x9;sentinel &amp;#34;github.com/alibaba/sentinel-golang/api&amp;#34;&#xA;&#x9;&amp;#34;github.com/alibaba/sentinel-golang/core/base&amp;#34;&#xA;&#x9;&amp;#34;github.com/alibaba/sentinel-golang/core/flow&amp;#34;&#xA;&#x9;&amp;#34;github.com/alibaba/sentinel-golang/util&amp;#34;&#xA;)&#xA;&#xA;func main() {&#xA;&#x9;_ = sentinel.InitDefault()&#xA;&#x9;_, _ = flow.LoadRules([]*flow.Rule{&#xA;&#x9;&#x9;{&#xA;&#x9;&#x9;&#x9;Resource:               &amp;#34;控制吃煎鱼的速度&amp;#34;,&#xA;&#x9;&#x9;&#x9;Threshold:              60,&#xA;&#x9;&#x9;&#x9;ControlBehavior:        flow.Reject,&#xA;&#x9;&#x9;},&#xA;&#x9;})&#xA;&#xA;&#x9;...&#xA;&#x9;e, b := sentinel.Entry(&amp;#34;控制吃煎鱼的速度&amp;#34;, sentinel.WithTrafficType(base.Inbound))&#xA;&#x9;if b != nil {&#xA;&#x9;    // Blocked&#xA;&#x9;} else {&#xA;&#x9;    // Passed&#xA;&#x9;    e.Exit()&#xA;&#x9;}&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;总的来讲，上述规则结果就是 1s 内允许通过 60 个请求，超出的请求的处理策略为直接拒绝（Reject）。&lt;/p&gt;</description>
    </item>
    <item>
      <title>想要4个9？本文告诉你监控告警如何做</title>
      <link>https://note.lican.site/posts/posts/microservice/monitor-alarm/</link>
      <pubDate>Sun, 13 Sep 2020 18:42:17 +0800</pubDate>
      <guid>https://note.lican.site/posts/posts/microservice/monitor-alarm/</guid>
      <description>&lt;p&gt;“你说说，没有仪表盘的车，你敢开吗？”&lt;/p&gt;&#xA;&lt;p&gt;“没有仪表盘的车开在路上，你怎么知道现在是什么情况？”&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.eddycjy.com/6e2774d84ddcdb2d73918e06575a07b7.jpeg&#34; alt=&#34;image&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;“客户说你这车又崩了，咋知道什么时候好的？​啥时候出的问题？”&lt;/p&gt;&#xA;&lt;h2 id=&#34;前言&#34;&gt;前言&lt;/h2&gt;&#xA;&lt;p&gt;将思考转换到现实的软件系统中，可想而知没有监控系统的情况下，也就是没有 ”仪表盘“ 的情况下实在是太可怕了。&lt;/p&gt;&#xA;&lt;p&gt;你的故障永远都是你的客户告诉你的，而&amp;hellip;在什么时候发生的，你也无法确定，只能通过客户的反馈倒推时间节点，最后从错误日志中得到相对完整的日志信息。&lt;/p&gt;&#xA;&lt;h2 id=&#34;问题&#34;&gt;问题&lt;/h2&gt;&#xA;&lt;p&gt;更要命的是你无法掌握主动权，错误日志有可能会有人漏记录，平均修复时间（MTTR）更不用想了，需要从 0.1 开始定位，先看 APP 是哪个模块报错，再猜测是哪个服务导致，再打开链路追踪系统，或是日志平台等。&lt;/p&gt;&#xA;&lt;p&gt;稍微复杂些的，排查来来往往基本都是半小时、一小时以上，那 4 个 9 肯定是达不到的了，以此几次 P0 几小时怕不是业务绩效也凉凉，因为故障修复的速度实在是太慢了。&lt;/p&gt;&#xA;&lt;p&gt;那归根到底，想破局怎么办，核心第一步就是要把监控告警的整个生态圈给建设好。&lt;/p&gt;&#xA;&lt;h2 id=&#34;监控定义&#34;&gt;监控定义&lt;/h2&gt;&#xA;&lt;p&gt;常说监控监控，监控的定义就是监测和控制，检测某些事物的变化，以便于进行控制。在常见的软件系统中，大多分为三大观察类别：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.eddycjy.com/b567a71921b7e54d703d9e47f491d6c0.jpg&#34; alt=&#34;image&#34;&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;业务逻辑：项目所对应的服务其承担的业务逻辑，通常需要对其进行度量。例如：每秒的下单数等。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;应用程序：应用程序。例如：统一的基础框架。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;硬件资源：服务器资源情况等。例如：Kubernetes 中的 Cadvisor 组件便会提供大量的资源指标。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;从软件系统来讲，监控的定义就是收集、处理、汇总，显示关于某个系统的实时量化数据，例如：请求的数量和类型，错误的数量和类型，以及各类调用/处理的耗时，应用服务的存活时间等。&lt;/p&gt;&#xA;&lt;h2 id=&#34;监控目标&#34;&gt;监控目标&lt;/h2&gt;&#xA;&lt;p&gt;知道了监控的定义，了解了监控的作用和具体的实施指标后。我们需要明确的知道，做监控的目标是什么：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.eddycjy.com/bab6275c4b7c73deec2d9f9919f967c7.jpg&#34; alt=&#34;image&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;从现实层面出发，做监控的初衷，就是希望能够及时的发现线上环境的各种各样奇奇怪怪的问题，为业务的正常运转保驾护航。因此整体分为上图四项：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;预测故障：故障还没出现，但存在异常。监控系统根据流量模型、数据分析、度量趋势来推算应用程序的异常趋势，推算可能出现故障的问题点。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;发现故障：故障已经出现，客户还没反馈到一线人员。监控系统根据真实的度量趋势来计算既有的告警规则，发现已经出现故障的问题点。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;定位故障：故障已经出现，需要监控系统协助快速定位问题，也就是根因定位（root cause）。此时是需要协调公司内生态圈的多个组件的，例如：链路追踪系统、日志平台、监控系统、治理平台（限流熔断等），根据监控系统所告警出来的问题作为起始锚点，对其进行有特定方向的分析，再形成 ”线索“ 报告，就可以大力的协助开发人员快速的定位问题，发现故障点。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;故障恢复：故障已经出现，但自动恢复了，又或是通过自动化自愈了。这种情况大多出现在告警规则的阈值配置的不够妥当，又或是第三方依赖恰好恢复了的场景。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;而更值得探讨的的是监控告警的后半段闭环，故障自愈，通过上述三点 “预测故障、发现故障、定位故障”，已经定位到故障了，就可以配合内部组件，实现自动化的 ”自愈“，减少人工介入，提高 MTTR。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.eddycjy.com/437e9d859ee86916f5d2d0bc409ab9f5.jpg&#34; alt=&#34;image&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;因此做监控系统的目标很明确，就是发现问题，解决问题，最好自愈，达到愉快休假，业务安心的目的。&lt;/p&gt;&#xA;&lt;h2 id=&#34;4-个黄金指标&#34;&gt;4 个黄金指标&lt;/h2&gt;&#xA;&lt;p&gt;有定义，有目标，那指导呢。实际上 “业务逻辑、应用程序、硬件资源” 已经成为了一个监控系统所要监控构建的首要目标，绝大部分的监控场景都可以归类进来。且针对这三大项，《Google SRE 运维解密》 也总结出了 4 个黄金指标，在业界广为流传和借鉴：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;延迟：服务处理某个请求所需要的时间。&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;区分成功和失败请求很重要，例如：某个由于数据库连接丢失或者其他后端问题造成的 HTTP 500 错误可能延迟很低。因此在计算整体延迟时，如果将 500 回复的延迟也计算在内，可能会产生误导性的结果。&lt;/li&gt;&#xA;&lt;li&gt;“慢” 错误要比 “快” 错误更糟糕。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;流量：使用系统中的某个高层次的指标针对系统负载需求所进行的度量。&lt;/p&gt;</description>
    </item>
    <item>
      <title>微服务的灾难：端到端测试的痛苦</title>
      <link>https://note.lican.site/posts/posts/microservice/tests/</link>
      <pubDate>Thu, 10 Sep 2020 19:54:59 +0800</pubDate>
      <guid>https://note.lican.site/posts/posts/microservice/tests/</guid>
      <description>&lt;p&gt;大家好，我是煎鱼。&lt;/p&gt;&#xA;&lt;p&gt;小咸鱼经过前文所提到的折磨人的 “微服务拆分、微服务环境” 问题后，终于顺顺利利的上到了测试环境进行测试。&lt;/p&gt;&#xA;&lt;p&gt;这时候开发、测试同学又闹新的头疼了，测了一轮下来。发现好好的。结果发现一上生产就有一些地方有问题，发现没测到。&lt;/p&gt;&#xA;&lt;p&gt;这到底是为什么呢？&lt;/p&gt;&#xA;&lt;h2 id=&#34;背景&#34;&gt;背景&lt;/h2&gt;&#xA;&lt;p&gt;在以往，小咸鱼他们团队都是传统的大单体应用。也就是一体化应用，包含了前端、后端等模块，具备天然的协调性：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;测试同学能够很方便的就直接测到前后端接口。&lt;/li&gt;&#xA;&lt;li&gt;测试能够直接对系统本身进行集成测试。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;但现在，做了微服务化（雏形）后，小咸鱼他们就翻车了，为什么呢？&lt;/p&gt;&#xA;&lt;p&gt;因为考虑到微服务，微服务就是向往单拎一个服务出来，都可以独立修改，独立发布。于是小咸鱼提交了一个迭代的几个服务变更，想着实现一把 “敏捷” 发布。&lt;/p&gt;&#xA;&lt;p&gt;结果一上线就炸了，一大堆的 BUG，光荣加班到晚上 12 点。&lt;/p&gt;&#xA;&lt;p&gt;这实质上是缺乏端到端测试的一个问题，单服务，无法明确系统正在正常运行。&lt;/p&gt;&#xA;&lt;h2 id=&#34;端到端测试&#34;&gt;端到端测试&lt;/h2&gt;&#xA;&lt;p&gt;在测试的质量保障上，我们要站在用户视角去验证这个系统，保障整体的系统可用性，而不是单纯的前端 BFF，又或是后端 Server 的某些接口能够正常运行。&lt;/p&gt;&#xA;&lt;p&gt;在定义上&lt;strong&gt;端到端测试（End-to-end Test）是一种用于测试整个应用程序的流程是否符合预期的测试技术&lt;/strong&gt;。测试同学会模拟用户真实的使用场景，通过用户界面测试应用程序。&lt;/p&gt;&#xA;&lt;p&gt;如下图：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.eddycjy.com/5ca5b971d8e25cf41c648401489d47b4.jpg&#34; alt=&#34;端到端测试&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;与小咸鱼团队那种单纯只测接口的方式不同，端到端测试是面向业务的。&lt;/p&gt;&#xA;&lt;p&gt;其目的是&lt;strong&gt;验证应用程序系统整体上是否符合业务诉求&lt;/strong&gt;，主要通过 GUI 测试，也会有人称其为集成测试、系统测试，黑盒测试。不少公司会将这几种混在一起。&lt;/p&gt;&#xA;&lt;p&gt;实则在细节定义上各有不同：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://files.mdnice.com/user/3610/820d7fbb-e3aa-4e99-8898-d69fa242887b.png&#34; alt=&#34;图来自网络&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;本文不是测试方向文章，因此不深究。&lt;/p&gt;&#xA;&lt;h2 id=&#34;问题症结&#34;&gt;问题症结&lt;/h2&gt;&#xA;&lt;p&gt;那么小咸鱼他们团队主要是缺乏端到端的这类集成测试的校验。直接在迭代中，把几个微服务一改，接口跑几下，以为就是合理通过的了。&lt;/p&gt;&#xA;&lt;p&gt;真实情况：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;一上到生产，发现压根不是这么回事。因为多个变更结合在一起，很有可能会导致系统原有的行为发生改变。&lt;/li&gt;&#xA;&lt;li&gt;即使是你单个服务接口没违背，也不一定能保证其他在同个时段上的服务没问题。&lt;/li&gt;&#xA;&lt;li&gt;在业内执行情况来看，业务迭代的非常快，接口自动化大多比较缺乏。又或是以请外包人员的方式来做，大多是面向存量补接口。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;我们可以知道单纯验证接口，不走端到端类别的集成测试，是非常风骚的。设身处地的想想如下场景：&lt;/p&gt;&#xA;&lt;p&gt;有没有见过一些开发，他在本地测好接口后，一和前端集成上到测试环境。测试人员，一点一个报错，正向流程压根跑不通。测试同学苦不堪言，开发同学一下身背数十 BUG，齐齐加班。&lt;/p&gt;&#xA;&lt;p&gt;但开发同学大呼我在本地的接口测试的完全没问题。归根结底，小咸鱼团队的问题，还是因为缺乏端到端测试，缺乏齐全的接口自动化用例导致的。&lt;/p&gt;&#xA;&lt;h2 id=&#34;解决思路&#34;&gt;解决思路&lt;/h2&gt;&#xA;&lt;p&gt;在每个迭代中，实际上每个团队都会专注于系统中所使用的所有服务中的某个服务。&lt;/p&gt;&#xA;&lt;p&gt;系统中存在的大量微服务和子系统的功能和较窄的测试空间，有可能会导致没有发现系统或服务中存在的隐患。&lt;/p&gt;&#xA;&lt;p&gt;这样测试，问题的出现，甚至是必然的。&lt;/p&gt;&#xA;&lt;p&gt;在解决思路上常见于：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;新增预发布环境，做类似端到端测试的集成测试，确保系统集成后会是可用的。&lt;/li&gt;&#xA;&lt;li&gt;尝试更高覆盖率的接口自动化测试，大多数公司会针对新的，做增量或存量的自动化测试用例的补全。&lt;/li&gt;&#xA;&lt;li&gt;借助线上、线下数据在 CI/CD 时进行自动化测试，实现更全面真实的测试用例。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;业内基本是数种思路齐头并进，最常见的是第一种方式。最有效，但开销也是最大的，并且会导致预发布环境的一定阻塞。&lt;/p&gt;&#xA;&lt;p&gt;随后第二第三种大多都会紧接着跟进，具体程度会根据公司的软硬实力（例如：行政手段、基础设施等）不同而做的深度不同。&lt;/p&gt;&#xA;&lt;p&gt;甚至前几天听小咸鱼说，面试时还听到不少公司延伸了外包岗位专门做一块的内容。&lt;/p&gt;&#xA;&lt;h2 id=&#34;总结&#34;&gt;总结&lt;/h2&gt;&#xA;&lt;p&gt;虽说这个问题并不是 “微服务” 架构所独有的。但是显然微服务化后放大了测试的深坑问题。&lt;/p&gt;&#xA;&lt;p&gt;很多公司的流程和措施都是为了保障一些东西，像小咸鱼团队这样，被网上布道师例举的优点遮蔽了双眼，后面又被迫把端到端测试加回来的不在少数。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;你们的团队又是如何高效解决这个问题的呢，欢迎在评论区留言和交流&lt;/strong&gt;！&lt;/p&gt;</description>
    </item>
    <item>
      <title>微服务的战争：选型？分布式链路追踪</title>
      <link>https://note.lican.site/posts/posts/microservice/tracing/</link>
      <pubDate>Thu, 10 Sep 2020 19:53:59 +0800</pubDate>
      <guid>https://note.lican.site/posts/posts/microservice/tracing/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;“微服务的战争” 是一个关于微服务设计思考的系列题材，主要是针对在微服务化后所出现的一些矛盾/冲突点，不涉及具体某一个知识点深入。如果你有任何问题或建议，欢迎随时交流。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;h2 id=&#34;背景&#34;&gt;背景&lt;/h2&gt;&#xA;&lt;p&gt;在经历 &lt;a href=&#34;https://eddycjy.com/posts/microservice/linkage/&#34;&gt;微服务的战争：级联故障和雪崩&lt;/a&gt; 的 P0 级别事件后，你小手一摊便葛优躺了。开始进行自我复盘，想起这次排查经历，由于现在什么基础设施都还没有，因此在接收到客户反馈后，你是通过错误日志进行问题检查的。&lt;/p&gt;&#xA;&lt;p&gt;但在级联错误中，错误日志产生的实在是太多了，不同的服务不同的链路几乎都挤在一起，修复时间都主要用在了翻日志上，翻了好几页才找到了相对有效的错误信息。&lt;/p&gt;&#xA;&lt;p&gt;如果下一次在出现类似的问题，可不得了，MTTR 太久了，4 个 9 很快就会用完。这时候你想到了业界里经常被提起的一个利器，那就是 “分布式链路追踪系统”。粗略来讲，能够看到各种应用的调用依赖：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.eddycjy.com/e233f218a90b7a00b94b7f533a98c0a2.png&#34; alt=&#34;image&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;其中最著名的是 &lt;a href=&#34;https://storage.googleapis.com/pub-tools-public-publication-data/pdf/36356.pdf&#34;&gt;Google Dapper&lt;/a&gt; 论文所介绍的 Dapper。源于 Google 为了解决可能由不同团队，不同语言，不同模块，部署在不同服务器，不同数据中心的所带来的软件复杂性（很难去分析，无法做定位），构建了一个的分布式跟踪系统：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.eddycjy.com/64214cb247989300859b98b61a844c2e.png&#34; alt=&#34;image&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;自此就开启了业界在分布式链路的启发/启蒙之路，很多现在出名的分布式链路追踪系统都是基于 Google Dapper 论文发展而来，基本原理和架构都大同小异。若对此有兴趣的可具体查看 &lt;a href=&#34;https://storage.googleapis.com/pub-tools-public-publication-data/pdf/36356.pdf&#34;&gt;Google Dapper&lt;/a&gt;，非常有意思。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.eddycjy.com/65bd2c9b931f057d7307dfaaa8d5c433.png&#34; alt=&#34;image&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;（Google Dapper 中存在跟踪树和 Span 的概念）&lt;/p&gt;&#xA;&lt;h2 id=&#34;选型有哪些&#34;&gt;选型？有哪些&lt;/h2&gt;&#xA;&lt;p&gt;想做链路追踪，那必然要挑选一款开源产品作为你的分布式链路追踪系统，不大可能再造一个全新的，先实现业务目的最重要。因此在网上一搜，发现如下大量产品：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Twitter：Zipkin。&lt;/li&gt;&#xA;&lt;li&gt;Uber：Jaeger。&lt;/li&gt;&#xA;&lt;li&gt;Elastic Stack：Elastic APM。&lt;/li&gt;&#xA;&lt;li&gt;Apache：SkyWalking（国内开源爱好者吴晟开源）。&lt;/li&gt;&#xA;&lt;li&gt;Naver：Pinpoint（韩国公司开发）。&lt;/li&gt;&#xA;&lt;li&gt;阿里：鹰眼。&lt;/li&gt;&#xA;&lt;li&gt;大众点评：Cat。&lt;/li&gt;&#xA;&lt;li&gt;京东：Hydra。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;随手一搜就发现这类产品特别的多，并且据闻各大公司都有自己的一套内部链路追踪系统，这下你可犯了大难。他们之间都是基于 Google Dapper 演进出来的，那本质上到底有什么区别，怎么延伸出这么多的新产品？&lt;/p&gt;&#xA;&lt;h3 id=&#34;jaeger&#34;&gt;Jaeger&lt;/h3&gt;&#xA;&lt;p&gt;首先看看由 Uber 开发的 Jaeger，Jaeger 目前由 Cloud Native Computing Foundation（CNCF）托管，是 CNCF 的第七个顶级项目（于 2019 年 10 月毕业）：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.eddycjy.com/1a672c2972602f1f154c1666c94e860a.png&#34; alt=&#34;image&#34;&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Jaeger Client：Jaeger 客户端，是 Jaeger 针对 OpenTracing API 的特定语言实现，可用于手动或通过与 OpenTracing 集成的各种现有开源框架（例如Flask，Dropwizard，gRPC等）来检测应用程序以进行分布式跟踪。&lt;/p&gt;</description>
    </item>
    <item>
      <title>微服务的战争：级联故障和雪崩</title>
      <link>https://note.lican.site/posts/posts/microservice/linkage/</link>
      <pubDate>Tue, 25 Aug 2020 21:08:39 +0800</pubDate>
      <guid>https://note.lican.site/posts/posts/microservice/linkage/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;“微服务的战争” 是一个关于微服务设计思考的系列题材，主要是针对在微服务化后所出现的一些矛盾/冲突点，不涉及具体某一个知识点深入。如果你有任何问题或建议，欢迎随时交流。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;在 &lt;a href=&#34;https://eddycjy.com/posts/microservice/standardization/&#34;&gt;微服务的战争：统一且标准化&lt;/a&gt; 中，经过好几周与不同业务组不同事业部的跨部门讨论后，终于把初始的标准化方案给定下来了，大家欢快的使用起了内部的统一框架，疯狂的创建起了新服务，没隔多久服务调用链就变成了下图：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.eddycjy.com/97128d96a1a4b8ba1f765bf30134f529.jpg&#34; alt=&#34;image&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;服务间存在多次内部调用，服务 A =》服务 B =》服务 C =》服务D，而 服务 E =》 服务 B，服务 F =》服务 E，也就是存在着多个流量入口，且依赖相同的服务。&lt;/p&gt;&#xA;&lt;h2 id=&#34;背景&#34;&gt;背景&lt;/h2&gt;&#xA;&lt;p&gt;服务与服务中，总存在业务服务，公共服务，基础服务等类型。但在某一个夜晚，突然发现 BFF 调用后端服务开始逐渐不正常，客户给你截图反馈问题，你发现有点问题：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.eddycjy.com/844d0d5a730a4c692d7d96912e1d710c.jpg&#34; alt=&#34;image&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;单从表现来看，你发现是 BFF 调用服务 A 极度缓慢，也不知道怎么了&amp;hellip;正当以为是服务 A 出问题，想着万能重启一下时。你在日志平台和链路追踪系统一看，发现了大量的错误日志和缓慢，让你略微震惊，一时间不知道从何下手。&lt;/p&gt;&#xA;&lt;p&gt;这可怎么办？&lt;/p&gt;&#xA;&lt;h2 id=&#34;级联故障和雪崩&#34;&gt;级联故障和雪崩&lt;/h2&gt;&#xA;&lt;p&gt;实际上这是一次很经典的级联故障，最终导致系统雪崩的情景再现。单从上述拓扑来看，问题点之一在于服务 B：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.eddycjy.com/51b18e7c80833fbe1dc13b3a3290940b.jpg&#34; alt=&#34;image&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;服务 B 本身作为服务 A 和服务 F 的两个流量入口必经之处，想必至少是一个公共服务，但他也依赖了其他多个服务。因此若服务 C 和服务 D 其中一个有问题，在没有熔断措施的情况下，就出现级联故障，系统逐渐崩盘，最后雪崩：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.eddycjy.com/2e7b0d94c32f3bd8f3f7168046671d2b.jpg&#34; alt=&#34;image&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;服务 D 所依赖的外部接口出现了故障，而他并没有做任何的控制，因此扩散到了所有调用到他的服务，自然也就包含服务 B，因此最终出现系统雪崩。&lt;/p&gt;&#xA;&lt;p&gt;这种最经典的是出现在默认 Go http client 调用没有设置 Timeout，从而只要出现一次故障，就足矣让记住这类 “坑”，毕竟崩的 ”慢“，错误日志还多。&lt;/p&gt;&#xA;&lt;h2 id=&#34;解决方法&#34;&gt;解决方法&lt;/h2&gt;&#xA;&lt;p&gt;常见的方式是&lt;strong&gt;根据特定的规则/规律进行熔断和降级&lt;/strong&gt;，避免请求发生堆积：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;超时时间控制。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;慢调用比例。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;错误比例。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;自适应（例如：负载情况等）。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;当然，这也只是壮士断腕，后续措施还包含监控告警，通知对应的开发人员来处理。且需提前对被降级的模块进行业务逻辑进行处理等等，这样才能够比较柔和且快速地度过这一次危机。&lt;/p&gt;&#xA;&lt;h2 id=&#34;总结&#34;&gt;总结&lt;/h2&gt;&#xA;&lt;p&gt;在分布式应用中，级联故障和雪崩是非常常见的，一些开发同学在模块设计时可能并没有意识到这块的问题，在微服务化后会一个不留神就碰到，因为其调用链变得特别的长且多。因此建议配套设施和限流熔断措施都应该及时跟上，否则面对一大堆的错误日志还是很无奈的。&lt;/p&gt;</description>
    </item>
    <item>
      <title>微服务的战争：统一且标准化</title>
      <link>https://note.lican.site/posts/posts/microservice/standardization/</link>
      <pubDate>Sat, 22 Aug 2020 21:56:14 +0800</pubDate>
      <guid>https://note.lican.site/posts/posts/microservice/standardization/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;“微服务的战争” 是一个关于微服务设计思考的系列题材，主要是针对在微服务化后所出现的一些矛盾/冲突点，不涉及具体某一个知识点深入。如果你有任何问题或建议，欢迎随时交流。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.eddycjy.com/b70c37b40768191e5a6812096703a63f.jpg&#34; alt=&#34;image&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;开天辟地&#34;&gt;开天辟地&lt;/h2&gt;&#xA;&lt;p&gt;在远古开天辟地时，大单体转换成微服务化后，服务的数量越来越多。每起一个新的服务，就得把项目的目录结构，基础代码重新整理一遍，并且很有可能都是从最初的 template 上 ctrl+c，ctrl+v 复制出来的产物，如下：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.eddycjy.com/7b4642c2bb7af1e5656be047bc269fb6.jpg&#34; alt=&#34;image&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;但是基于 template 的模式，很快就会遇到各种各样的新问题：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.eddycjy.com/3c91559190480a348aeacd609199c2bb.jpg&#34; alt=&#34;image&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;随着跨事业部/业务组的使用增多，你根本不知道框架的 template 是什么时间节点被复制粘贴出去的，也不知道所对应的 commit-id 是什么，更不知道先前的 BUG 修复了没，也不知道有没有其他开发人员私下改过被复制走的 template。&lt;/p&gt;&#xA;&lt;p&gt;简单来讲，就是不具备可维护性，相对独立，BUG 可能一样，但却没有版本可规管。这时候，就可以选择做一个内部基础框架和对应的内部工具（已经有用户市场了），形成一个脚手架闭环：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.eddycjy.com/3787e41616779a91a3a052467b3acdee.jpg&#34; alt=&#34;image&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;通过基础工具+基础接口的方式，就可以解决项目A、B、C&amp;hellip;的基础框架版本管理和公共维护的问题，且在遇到框架 BUG 时，只需要直接 upgrade 就好了。而在框架维护者层面，还能通过注册机制知道目前基础框架的使用情况（例如：版本分布），便于后续的迭代和规划。&lt;/p&gt;&#xA;&lt;p&gt;同时若内部微服务依赖复杂，可以将脚手架直接 “升级”，再做多一层基础平台，通过 CI/CD 平台等关联创建应用，选择应用类型等基本信息，然后关联创建对应的应用模板、构建工具、网关、数据库、接口平台、初始化自动化用例等：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.eddycjy.com/0997fb71080b8f35fe0ccd68acaebc94.jpg&#34; alt=&#34;image&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;至此，就可以通过结合基础平台（例如：CI/CD）实现流程上的标准化控制，成为一个提效好帮手。&lt;/p&gt;&#xA;&lt;h2 id=&#34;大众创新&#34;&gt;大众创新&lt;/h2&gt;&#xA;&lt;p&gt;但，一切都有 “开天辟地” 那么顺利吗。实际上并不，在很多的公司中，大多数是在不同的时间阶段在不同的团队同时进行了多个开天辟地。&lt;/p&gt;&#xA;&lt;p&gt;更具现化来讲，就是在一家公司内，不同的团队里做出了多种基础工具和基础框架。更要命的是，他们几家的规范可能还不大一样。例如：框架在 gRPC 错误码的规范处理上的差异：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;业务错误码放在 grpc.status.details 中。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;业务错误码放在 grpc-status 中。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;业务错误码放在 grpc-message 中。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;又或是 HTTP 状态码的差异：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;HTTP Status Code 为金标准，不在主体定义业务错误码。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;HTTP Status Code 都为 200 OK（除宕机导致的 500，503 等），业务错误码由主体另外定义。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;粗略一看，单单在应用错误码/状态码这一件事情上，就能够玩出花样。而这件事又会导致各种问题，例如在监控平台上，因为不同团队所定义的状态码规范不一样，就会导致连基本的监控可用性都会有问题。&lt;/p&gt;&#xA;&lt;p&gt;像是有的小伙伴会把业务错误码放在 grpc-status 属性中，而在标准 gRPC 的规范中 grpc-status 是和 HTTP Status Code 一样有特定状态码映射的。这时候就会让监控告警系统十分难做，通用的告警规则到底是以哪份状态码为准？&lt;/p&gt;</description>
    </item>
    <item>
      <title>微服务的战争：按什么维度拆分服务</title>
      <link>https://note.lican.site/posts/posts/microservice/dismantle/</link>
      <pubDate>Wed, 19 Aug 2020 20:56:55 +0800</pubDate>
      <guid>https://note.lican.site/posts/posts/microservice/dismantle/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;“微服务的战争” 是一个关于微服务设计思考的系列题材，主要是针对在微服务化后所出现的一些矛盾/冲突点，不涉及具体某一个知识点深入。如果你有任何问题或建议，欢迎随时交流。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;微服务，这三个字正在席卷着目前的互联网软件行业，尤其在近几年云原生迸发后，似乎人人都对微服务有了更广泛的使用和理解，张口就是各种各样的问号，有着强大的好奇心。&lt;/p&gt;&#xA;&lt;p&gt;无独有偶，我有一个朋友鲤鱼在内部微服务的早期（每个业务组起步）就经常遇到下述的对话：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;张三&lt;/strong&gt;：为什么要拆现在的代码？&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;鲤鱼&lt;/strong&gt;：因为 ！@&lt;em&gt;）&amp;amp;&amp;amp;#@&lt;/em&gt;！）&amp;amp;#！&amp;amp;）@！&amp;amp;！ 的原因。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;张三&lt;/strong&gt;：那即将要做的 “微服务” 是按照什么维度去拆分的服务？&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;鲤鱼&lt;/strong&gt;：常见的一般根据 ！@#*@！#&amp;amp;！（@&amp;amp;！@）#@ 的方式来拆分。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;张三&lt;/strong&gt;：照你这么说好像也不大对，我看每个业务组拆分的维度似乎都不大一样？&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;鲤鱼&lt;/strong&gt;：嗯，每个业务组还有自己的见解，不会完全相同。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;张三&lt;/strong&gt;：。。。所以微服务的拆分维度到底是什么？&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;为什么想拆&#34;&gt;为什么想拆&lt;/h2&gt;&#xA;&lt;p&gt;为什么张三会有这个疑问呢，实际上是因为研发内部希望从原先的大单体，大仓库向微服务体系拆分转换，其原先大单体仓库结构，类 Monorepo：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.eddycjy.com/b61faf600a2648ecce258abfa7d57ce8.jpg&#34; alt=&#34;image&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;但类 Monorepo 又有不少的问题，像是：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;单个 Repo 体积过大&lt;/strong&gt;：导致 Git 无法直接拉取。当你设置完再拉取时，在网速慢时还能去泡杯咖啡，并且在开发机性能不佳的情况下，IDE 会比较卡，代码运行起来也慢。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;单个 Repo 存在公共函数/SDK&lt;/strong&gt;：在代码仓库中，必然存在公共依赖。因此在解决代码冲突时，若遗留了冲突符，且在动态语言中，不涉及便运行正常。但其实在上线后却又影响到其他业务，可真是糟糕透顶，分分钟被迫抱着事故。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;单个 Repo 模块职责/边界不清&lt;/strong&gt;：在实际的软件开发中，涉及数十个业务组同时在一个大 Repo 下进行开发，没有强控边界的情况下，往往会逐渐模糊，即使在设计时管得住自己，你也不一定能 100% 防止别人模糊你的边界。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;单个 Repo 包含了所有的源码&lt;/strong&gt;：出现公司源代码泄露时，会导致整个 Repo 外泄，相当的刺激和具有教育意义。因为虽然开放和协同了，不属于你们组的业务代码你也有权限查看了。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;当然，Monorepo 是否又完全不可行呢？实际上国外 Google，Facebook，Twitter 等公司都有在使用 Monorepo，并取得了一定的收益。&lt;/p&gt;&#xA;&lt;p&gt;其实做 Monorepo 是需要相应的大量工具支撑，若单纯只是一个 Repo 塞多个模块，基本都做不好，甚至引火烧身。还不如早早拆开，至少能确保各业务线服务的相对独立性。&lt;/p&gt;&#xA;&lt;h2 id=&#34;拆成什么样&#34;&gt;拆成什么样&lt;/h2&gt;&#xA;&lt;p&gt;张三在明白了拆的原因后，就出现了第二个问题，那就是 “微服务” 要按照什么样的维度去拆分服务？&lt;/p&gt;&#xA;&lt;p&gt;张三公司内部对于这块的知识处于模糊不清的阶段，因此需要进行深入了解，便于后续的团队共识和方法论建立，理所当然，十万个为什么也就出现了。&lt;/p&gt;&#xA;&lt;h3 id=&#34;大单体变独立服务&#34;&gt;大单体变独立服务&lt;/h3&gt;&#xA;&lt;p&gt;最常见的拆分的方式是按照业务模块进行服务的拆解，像是前文所提到的业务模块，在设计上边界非常清晰，这种情况直接拆成各个服务就可以了：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://image.eddycjy.com/9fe68c7e07a732686240243376da5fcb.jpg&#34; alt=&#34;image&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;而在拆分后，又会遇到一个新的问题，也就是张三问第三个问题 “每个业务组拆分的维度似乎都不大一样？”。&lt;/p&gt;&#xA;&lt;p&gt;因为在实际的执行过程中，严谨一些会由 SM 与 RD 一同开会探讨/规范初版的服务划分，而在持续的快速的迭代中，往往新服务的拆分都是由一线 RD 亲自操刀。&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
