<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.2">Jekyll</generator><link href="https://jervyshi.me/feed.xml" rel="self" type="application/atom+xml" /><link href="https://jervyshi.me/" rel="alternate" type="text/html" /><updated>2022-11-23T02:43:35+00:00</updated><id>https://jervyshi.me/feed.xml</id><title type="html">JervyShi`s Blog</title><subtitle>Staff engineer, Using Java and Go. Now focus on Service Mesh development.</subtitle><author><name>JervyShi</name></author><entry><title type="html">蚂蚁集团 Service Mesh 进展回顾与展望</title><link href="https://jervyshi.me/review-and-prospect-of-service-mesh-progress-in-antgroup/" rel="alternate" type="text/html" title="蚂蚁集团 Service Mesh 进展回顾与展望" /><published>2022-05-17T00:00:00+00:00</published><updated>2022-05-17T00:00:00+00:00</updated><id>https://jervyshi.me/review-and-prospect-of-service-mesh-progress-in-antgroup</id><content type="html" xml:base="https://jervyshi.me/review-and-prospect-of-service-mesh-progress-in-antgroup/">&lt;h2 id=&quot;一引言&quot;&gt;一、引言&lt;/h2&gt;

&lt;p&gt;继 2019 年的 《&lt;a href=&quot;https://jervyshi.me/service-mesh-landing-practice-and-challenges-in-antfin/&quot;&gt;蚂蚁金服 Service Mesh 落地实践与挑战&lt;/a&gt;》之后，蚂蚁集团在 Service Mesh 方向已经继续探索演进近 3 年，这 3 年里有哪些新的变化，以及对未来的思考是什么，值此 SOFAStack 开源 4 周年之际，欢迎大家一起进入《蚂蚁集团 Service Mesh 进展回顾与展望》章节探讨交流。&lt;/p&gt;

&lt;p&gt;本次交流将以如下次序展开：&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io//assets/images/1652758504322-f5e9c9d7-d6ec-45bb-8590-772849c7b20a.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;二蚂蚁集团-service-mesh-发展史&quot;&gt;二、蚂蚁集团 Service Mesh 发展史&lt;/h2&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io//assets/images/1652758504429-b3368bc7-6df3-4c6a-a3c6-9bf8323bc9bf.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;2018 年 3 月份蚂蚁集团的 Service Mesh 起步，MOSN 数据面诞生，起步就坚持走核心开源，内部能力走扩展的道路。&lt;/li&gt;
  &lt;li&gt;2019 年 6.18 我们在三大合并部署应用上接入了 MOSN 并且顺利支撑了 6.18 大促。&lt;/li&gt;
  &lt;li&gt;2019 年双 11 蚂蚁所有大促应用平稳的度过双大促。&lt;/li&gt;
  &lt;li&gt;2020 年 MOSN 对内沉稳发展把接入应用覆盖率提升至 90%，对外商业化开始展露头角。蚂蚁集团全站 90% 标准应用完成 Mesh 化接入。在商业版本中，SOFAStack“双模微服务”架构也在江西农信、中信银行等众多大型金融机构成功落地实践。&lt;/li&gt;
  &lt;li&gt;2021 年随着 Mesh 化的逐步成熟，多语言场景的逐步丰富，Mesh 化的对中间件协议的直接支撑带来的扩展性问题也逐步凸显，Dapr 的应用运行时概念也逐步崛起，这一年我们开源了 Layotto，期望通过对应用运行时 API 的统一来解决应用和后端中间件具体实现耦合的问题，进一步解耦应用和基础设施，解决应用在多云运行时的厂商绑定问题。&lt;/li&gt;
  &lt;li&gt;2022 年随着 Mesh 化落地的基础设施能力逐步完善，我们开始考虑 Mesh 化如果给业务带来更多价值，在 Mesh 1.0 时代，我们把中间件相关的能力尽可能做了下沉，提升了基础设施的迭代效率，在 Mesh 2.0 时代，我们期望能有一种机制可以让业务侧相对通用的能力，也可以做到按需下沉，并且具备一定的隔离性，避免下沉的能力影响 Mesh 数据代理主链路。这部分将在看未来部分做一些介绍。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;图示的方式简诉一下 Service Mesh 架构演进的几个阶段：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;SOA 时代，中间件的客户端均直接集成在业务进程内：&lt;/li&gt;
&lt;/ol&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io//assets/images/1652758504332-0f553974-0153-458e-b830-bccdbe018ca2.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Mesh 化阶段一：中间件能力下沉，应用和基础设施实现部分解耦：&lt;/li&gt;
&lt;/ol&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io//assets/images/1652758504261-4763cdec-2b3c-49f6-acd3-ea305e984335.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;应用运行时阶段：将应用和具体基础设施的类型解耦，仅依赖标准 API 编程：&lt;/li&gt;
&lt;/ol&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io//assets/images/1652758504319-72804307-117c-431e-9ad8-fb3828195c97.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;h2 id=&quot;三东西向流量规模化挑战&quot;&gt;三、东西向流量规模化挑战&lt;/h2&gt;

&lt;p&gt;Mesh 化后的数据面 MOSN 承载了应用间非常核心的东西向通信链路，目前在蚂蚁集团内部覆盖应用数千，覆盖容器数十W+，海量的规模带来了如长连接膨胀、服务发现数据量巨大、服务治理困难等问题。接下来我们来聊一聊我们在演进的过程中遇到并解决掉的一些经典问题。&lt;/p&gt;

&lt;h3 id=&quot;31-长连接膨胀问题&quot;&gt;3.1 长连接膨胀问题&lt;/h3&gt;

&lt;p&gt;在海量规模的应用背后存在着复杂的调用关系，部分基础性服务被大部分应用所依赖，由于调用方全连服务提供方的机制存在，一个基础性服务的单 Pod 需要日常承载近 10W 长连接，单机 QPS 一般还是有上限的，我们以 1000 QPS 的 Pod 举例，10w 长连接的场景下，每条长连接上的 QPS 是非常低的，假设所有连接的请求均等，平均每条长连接每 100s 仅有一次请求产生。&lt;/p&gt;

&lt;p&gt;为了保证长连接的可用性，SOFA RPC 的通信协议 Bolt 有定义心跳包，默认心跳包是 15s 一次，那么一条长连接上的请求分布大概如下图所示：&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io//assets/images/1652758504912-73aa62d2-7c07-4723-8c29-620192065ead.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;在上诉场景中，一条长连接上，心跳包的请求数量远大于业务请求的数量，MOSN 在日常运行中，用于维护长连接可用句柄持有内存的开销，还有心跳包发送的 CPU 开销，在海量规模集群下不可忽视。&lt;/p&gt;

&lt;p&gt;基于以上问题，我们找到了两个解法：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;在保证连接可用的前提下减少心跳频率&lt;/li&gt;
  &lt;li&gt;在保证负载均衡的前提下降低应用间的连接数&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;311-心跳退避&quot;&gt;3.1.1 心跳退避&lt;/h4&gt;

&lt;p&gt;由于心跳的主要作用是尽可能早的发现长连接是否已不可用，通常我们认为经过 3 次心跳超时即可判定一条长连接不可用，在一条长连接的生命周期里，不可用的场景占比是非常低的，如果我们把长连接的检测周期拉长一倍就可以减少50%的心跳 CPU 损耗。为了保障检测的及时性，当出现心跳异常（如心跳超时等）场景时，再通过降低心跳周期来提高长连接不可用时的判定效率，基于以上思路我们设计了 MOSN 里的长连接心跳退避策略：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;当长连接上无业务请求且心跳正常响应时，逐步将心跳周期拉长 15s -&amp;gt; 90s&lt;/li&gt;
&lt;/ol&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io//assets/images/1652758505136-96b8bf3d-8ce5-4f68-a486-5389c8046711.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;当长连接上出现请求失败或心跳超时的场景时，将心跳周期重置回 15s&lt;/li&gt;
&lt;/ol&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io//assets/images/1652758505368-a0f7ba00-025f-441e-89d4-45670a43e42c.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;当长连接上存在正常业务请求时，降级本次心跳周期内的心跳请求&lt;/li&gt;
&lt;/ol&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io//assets/images/1652758505453-1203ad34-eba8-4252-bc2b-abb63f2e2fee.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;通过以上心跳退避的手段，MOSN 的常态心跳 CPU 消耗降低至原来的 25%。&lt;/p&gt;

&lt;h4 id=&quot;312-服务列表分片&quot;&gt;3.1.2 服务列表分片&lt;/h4&gt;

&lt;p&gt;从心跳退避的优化可以看出，在海量长连接的场景下，单长连接上的请求频率是很低的，那么维护这么多长连接除了对负载均衡比较友好之外，其他的收益并不大，那么我们还有另外一个优化方向，就是减少客户端和服务端之间建立的长连接数量。&lt;/p&gt;

&lt;p&gt;MOSN 使用一致性哈希的策略对服务端机器进行分组：在客户端的内存中，首先将全量的服务端机器列表加入到一致性哈希环中，然后基于配置计算预期分片情况下的机器列表数 N，随后根据客户端机器 IP，从一致性哈希环中获取 N 个机器列表作为本机器的分片列表。每个客户端计算的哈希环都是一样的，不同的机器 IP 使得最终选择的机器分片列表是不同的。实现了不同客户端机器持有不同的服务端集群分片的效果。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io//assets/images/1652758505474-85386683-7310-48fb-bc8e-5782ac04a3d4.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;通过对服务列表的分片优化，客户端向服务端建立的长连接数量急剧减小，在 6w 长连接且采用 50% 的负载均衡分片的场景下：单机 CPU 降低约 0.4 Core，内存降低约 500M。&lt;/p&gt;

&lt;h3 id=&quot;32-海量服务发现问题&quot;&gt;3.2 海量服务发现问题&lt;/h3&gt;

&lt;p&gt;MOSN 的服务发现能力没有使用 Pilot，而是在内部直接和 SOFARegistry（服务注册中心） 对接，使用这种架构的原因之一就是 RPC 的接口级服务发现，节点的 Pub、Sub 量巨大，海量应用的频繁运维产生的节点变更推送对 Pilot 的性能和及时性挑战都很大，社区有使用 Pilot 在稍大规模下做 CDS 下发的过程中也发现非常多的性能问题并提交 PR 解决，但对于蚂蚁集团一个机房就有 200W Pub，2000W Sub 的规模下，Pilot 是完全无法承载的。SOFARegistry 的架构是存储和连接层分离，存储为内存分片存储，连接层也可以无限水平扩容，在内部海量节点变更下也能实现秒级变更推送。&lt;/p&gt;

&lt;p&gt;虽然 SOFARegistry 的推送能力没什么问题，不过海量节点变更后产生的推送数据，会导致 MOSN 内有大量的 Cluster 重构，列表下发后到 Cluster 构建成功的过程中，会有大量的临时内存产生，以及 CPU 计算消耗。这些尖刺型内存申请和 CPU 占用，是可能直接影响请求代理链路稳定性的。为了解决这个问题，我们也考虑过两个优化方向：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;SOFARegistry 和 MOSN 之间把全量推送改造为增量推送&lt;/li&gt;
  &lt;li&gt;服务发现模型从接口级切换为应用级&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;其中第一点能带来的效果是每次列表推送变化为原推送规模的 1/N，N 取决于应用变更时的分组数。第二点能带来的变化是更加明显的，我们假设一个应用会发布 20个接口，100个应用的 Pod 产生的服务发现数据是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;20*100=2000&lt;/code&gt; 条数据，接口粒度服务发现的数据总量会随着应用接口数量的增长数倍于应用节点数的规模持续增长；而应用级服务发现可以把节点总量控制在应用 Pod 数这个级别。&lt;/p&gt;

&lt;h4 id=&quot;321-应用级服务发现演进&quot;&gt;3.2.1 应用级服务发现演进&lt;/h4&gt;

&lt;p&gt;接口级服务发现示例（相同节点中多个服务中重复出现）：&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io//assets/images/1652758506184-312b86a0-f717-464d-9471-33929e016254.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;应用级服务发现示例（结构化表示应用、服务、地址列表间的关系）：&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io//assets/images/1652758506274-b58b079b-ccc1-40d0-91a8-4224ca980cc8.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;通过对应用和接口关联信息的结构化改变，服务发现的节点数量可以下降一到两个数量级。&lt;/p&gt;

&lt;p&gt;接口级服务发现演进到应用级服务发现对于 RPC 框架来讲是一个巨大的变化，社区中有 Dubbo 3.0 实现了应用级服务发现，但这种跨大版本的升级兼容性考量很多，对于在奔跑的火车上换轮子这件事情，在框架层演进是比较困难的。由于蚂蚁集团内部的 Service Mesh 已经覆盖 90% 的标准应用，所以在服务发现演进方面我们可以做的更加激进，结合 MOSN + SOFARegistry 6.0，我们实现了接口级服务发现和应用级服务发现的兼容性以及平滑切换的方案，通过 MOSN 版本的迭代升级，目前已经完成接口级到应用级服务发现的切换。&lt;/p&gt;

&lt;p&gt;通过上述改进，生产集群的服务发现数据 Pub 数据量下降 90%，Sub 数据量下降 80%，且整个过程对应用完全无感，这也是 Mesh 化业务和基础设施解耦后带来的实际便利体现。&lt;/p&gt;

&lt;h4 id=&quot;322-mosn-cluster-构造优化&quot;&gt;3.2.2 MOSN Cluster 构造优化&lt;/h4&gt;

&lt;p&gt;通过应用级服务发现解决数据量变更过大的问题之后，我们还需要解决下在列表变更场景下产生的 CPU 消耗和临时内存申请尖刺问题，在这个问题中通过对内存申请的分析，Registry Client 在收到服务端推送的列表信息之后需要经历反序列化，构造 MOSN 需要的 Cluster 模型并更新 Cluster 内容，其中比较重的就是构建 Cluster 过程中的 Subset 构建。通过使用对象池，并且尽量减少 byte[] 到 String 的拷贝，降低了内存分配，另外通过 Bitmap 优化 Subset 的实现，让整个 Cluster 的构造更加高效且低内存申请。&lt;/p&gt;

&lt;p&gt;经过上述优化，在超大集群应用运维时，订阅方列表变更临时内存申请降低于原消耗的 30%，列表变更期间 CPU 使用量降低为原消耗的 24%。&lt;/p&gt;

&lt;h3 id=&quot;33-服务治理智能化演进&quot;&gt;3.3 服务治理智能化演进&lt;/h3&gt;

&lt;p&gt;MOSN 把请求链路下沉之后，我们在服务治理方面做了非常多的尝试，包括像客户端精细化引流、单机压测引流、业务链路隔离、应用级别的跨单元容灾、单机故障剔除、各种限流能力等，篇幅关系我这里仅介绍下我们在限流场景下做的智能化探索。&lt;/p&gt;

&lt;p&gt;开源社区的 Sentinel 项目在限流方向做了一个非常好的实践，MOSN 在做限流早期就和 Sentinel 团队沟通，希望能基于 Sentinel 的 Golang 版本 SDK 来做扩展，站在巨人的肩膀上，我们做了更多的尝试。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io//assets/images/1652758506322-e62b64b6-6add-43a3-8ec0-31c94723bd87.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;基于 Sentinel 可插拔的 Slot Chain 机制，我们在内部扩展了很多限流模块的实现，如自适应限流 Slot、集群限流 Slot、熔断 Slot、日志统计 Slot 等。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io//assets/images/1652758506434-9728af1d-72ca-4d73-8b31-1042b1686364.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;在 MOSN 做限流能力之前，Java 进程内也是存在限流组件的，业务常用的是单机限流，一般会有一个精确的限流值，这个值需要经过反复的压测，才能得到单机的最大可健康承载的 TPS，这个值会随着业务应用本身的不断迭代，功能增加，链路变的更复杂而逐步变化，所以每年大促前，都会准备多轮全链路压测，来确保每个系统都能在满足总 TPS 的情况下对自身应用所应该配置的限流值有一个精确的预估。&lt;/p&gt;

&lt;p&gt;为了解决限流配置难的问题，我们尝试在 MOSN 内实现了自适应限流，根据对容器当前的接口并发、CPU、Load1 信息采集上报，再结合最近几个滑动窗口中，每个接口的请求量变化，可以自动识别是什么接口的并发量增加导致了 CPU 资源占用的提升，当负载超过一定的基线之后，限流组件可以自动识别出哪些接口应该被限流以避免资源使用超过健康水位。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io//assets/images/1652758506754-86ffeaf5-a44e-46df-8be3-42a76193b2ad.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;在实际的生产环境中，自适应限流可以迅速精准的定位异常来源，并秒级介入，迅速止血，同时也可以识别流量类型，优先降低压测流量来让生产流量尽可能成功。大促前再也不需要每个应用 Owner 去给自己应用的每个接口配置限流值，大幅度提升研发幸福感。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io//assets/images/1652758507194-28b592d7-47eb-4a97-a829-f815523dc987.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;四南北向流量打通&quot;&gt;四、南北向流量打通&lt;/h2&gt;

&lt;p&gt;MOSN 作为 Service Mesh 的数据面主要在东西向流量上发力，除了东西向流量之外，还有南北向流量被多种网关分而治之。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io//assets/images/1652758508034-26ad5b69-15bf-4bdd-8643-908c90584da4.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;蚂蚁集团下有许多不同的公司主体，分别服务于不同的业务场景，各主体有与之对应的站点来部署应用对外提供服务，南北向流量最常见的是互联网流量入口，这个角色在蚂蚁集团由 Spanner 承载。除了互联网流量入口之外，多个主体公司间也可能存在信息交互，在同一个集团内的多公司主体如果信息交互需要绕一道公网，稳定性会大打折扣，同时带宽费用也会更贵。为了解决跨主体的高效互通问题，我们通过 SOFAGW 搭建起了多主体间的桥梁，让跨主体的应用间通信和同主体内的 RPC 通信一样简单，同时还具备链路加密、鉴权、可审计等能力，保障多主体间调用合规。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io//assets/images/1652758507902-9bf69b1b-dfd8-44ce-9ee9-22d8442e7f53.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;SOFAGW 基于 MOSN 2.0 架构打造，既能使用 Golang 做高效研发，同时也能享受 Envoy 在 Http2 等协议处理上带来的超高性能。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io//assets/images/1652758508226-198d983d-6a6b-47c2-9f99-661c26858d9e.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;简单介绍一下 MOSN 2.0 架构，Envoy 提供了可扩展的 Filter 机制，来让用户可以在协议处理链路中插入自己的逻辑，MOSN 通过实现一层基于 CGO 的 Filter 扩展层，将 Envoy 的 Filter 机制进行了升级，我们可以用 Golang 来写 Filter 然后嵌入 Envoy 被 CGO 的 Filter 调用。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io//assets/images/1652758508198-288f8de3-740f-4975-86e2-274fd59a6a60.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;SOFAGW 在 MOSN 2.0 之上构建了自己的网关代理模型，通过 SOFA 的 Golang 客户端和控制面交互获取配置信息、服务发现信息等，然后重组成 Envoy 的 Cluster 模型通过 Admin API 插入 Envoy 实例中。通过 Golang 的 Filter 扩展机制，SOFAGW 实现了蚂蚁集团内部的 LDC 服务路由、压测流量识别、限流、身份认证、流量复制、调用审计等能力。由于 Envoy 的 Http2 协议处理性能相比纯 Golang GRPC 实现高出 2～4倍，SOFAGW 选择将 Triple （Http2 on GRPC）协议处理交给 Envoy 来处理，将 Bolt （SOFA RPC 私有协议）协议的处理依然交给 MOSN 来处理。&lt;/p&gt;

&lt;p&gt;通过上述架构，SOFAGW 实现了蚂蚁集团内部的全主体可信互通，在高性能和快速迭代开发间也取得了不错的平衡。&lt;/p&gt;

&lt;h2 id=&quot;五应用运行时探索&quot;&gt;五、应用运行时探索&lt;/h2&gt;

&lt;p&gt;随着 Service Mesh 化的探索进入深水区，我们把很多能力沉淀到 Mesh 的数据面之后，也感受到每种协议直接下沉的便利性与局限性，便利在于应用完全不用改造就可以平滑接入，局限性是每种私有协议均需要独立对接，且使用了 A 协议的应用，并不能直接在 B 协议上运行。在多云的环境下，我们希望可以做到让应用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Write Once，Run on any Cloud！&lt;/code&gt;想要实现这一愿景，我们需要将应用与基础设施间进一步解耦，让应用不直接感知底层的具体实现，而是使用分布式语义 API 来编写程序。这种思想在社区已经有 Dapr 作为先行者在探索：&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io//assets/images/1652758508317-b61c58e8-fb10-472d-91bf-c6a2ea60aeba.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;（上图来自 Dapr 官方文档）&lt;/p&gt;

&lt;p&gt;Dapr 提供了分布式架构下的各种原子 API，如服务调用、状态管理、发布订阅、可观测、安全等，并且实现了不同分布式原语在不同云上的对接实现组件。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io//assets/images/1652758509350-d42634c2-021c-4df8-8216-5fbfc0fd00e9.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;（上图来自 Dapr 官方文档）&lt;/p&gt;

&lt;p&gt;Dapr 相当于是在 Service Mesh 之上提供给应用更加无侵入的分布式原语，2021 年中，我们基于 MOSN 开源了应用运行时 Layotto，Layotto 相当于是 Application Runtime 和 Service Mesh 的合集：&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io//assets/images/1652758509359-ef68ee18-954d-4c76-825e-3cd3cf0f11ac.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;（上图修改自 Dapr 官方文档）&lt;/p&gt;

&lt;p&gt;我们通过 Layotto 抽象出应用运行时 API 将内部的 Service Mesh 演进至如下架构：&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io//assets/images/1652758509468-cb09ecc0-24f1-4a2d-b426-dca3ec47994b.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;当然应用运行时是一个新的概念，如果这一层 API 抽象做不到足够中立，那么依然需要面临使用方需要 N 选 1 的局面，所以我们也在和 Dapr 社区一起制定 Application Runtime API 的标准，组织 Dapr Sig API Group 用于推进 API 的标准化，也期望能有更多感兴趣的同学一同加入。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io//assets/images/1652758509626-107774b6-980b-4aa8-bb15-f05739e773b8.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;期待未来大家的应用都可以 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Write once, Run on any Cloud！&lt;/code&gt;。&lt;/p&gt;

&lt;h2 id=&quot;六mesh-20-探索&quot;&gt;六、Mesh 2.0 探索&lt;/h2&gt;

&lt;p&gt;2022 年我们继续向前探索，基于 MOSN 2.0 我们有了高性能的网络底座、易于扩展的 Mesh 数据面，基于 Layotto 我们有了无厂商绑定的应用运行时。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io//assets/images/1652758509653-8caf90f3-8ed1-487c-8065-05e0116aad30.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;下一步我们期望基于 eBPF 实现 Mesh 数据面的进一步下沉，从 Pod 粒度下沉到 Node 粒度，同时服务于更多场景，如 Function、Serverless，另外基于 MOSN 2.0 的良好扩展能力，我们希望能进一步尝试将业务应用相对通用的能力也可以沉淀下来，作为 Mesh 数据面的自定义插件来为更多应用提供服务，帮助业务实现相对通用的业务能力也可以快速迭代升级。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io//assets/images/1652758510352-7f4ce350-8371-401a-bf54-50de9dea8b18.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;相信在不远的未来，Mesh 2.0 可以在蚂蚁集团内部服务众多通用场景，也能给社区带来一些新的可能。以上是本次分享的所有内容，希望大家能从对蚂蚁集团 Service Mesh 的发展过程的交流中有所收获。&lt;/p&gt;</content><author><name>JervyShi</name></author><category term="service-mesh" /><category term="service-mesh" /><category term="golang" /><summary type="html">一、引言 继 2019 年的 《蚂蚁金服 Service Mesh 落地实践与挑战》之后，蚂蚁集团在 Service Mesh 方向已经继续探索演进近 3 年，这 3 年里有哪些新的变化，以及对未来的思考是什么，值此 SOFAStack 开源 4 周年之际，欢迎大家一起进入《蚂蚁集团 Service Mesh 进展回顾与展望》章节探讨交流。 本次交流将以如下次序展开： 二、蚂蚁集团 Service Mesh 发展史 2018 年 3 月份蚂蚁集团的 Service Mesh 起步，MOSN 数据面诞生，起步就坚持走核心开源，内部能力走扩展的道路。 2019 年 6.18 我们在三大合并部署应用上接入了 MOSN 并且顺利支撑了 6.18 大促。 2019 年双 11 蚂蚁所有大促应用平稳的度过双大促。 2020 年 MOSN 对内沉稳发展把接入应用覆盖率提升至 90%，对外商业化开始展露头角。蚂蚁集团全站 90% 标准应用完成 Mesh 化接入。在商业版本中，SOFAStack“双模微服务”架构也在江西农信、中信银行等众多大型金融机构成功落地实践。 2021 年随着 Mesh 化的逐步成熟，多语言场景的逐步丰富，Mesh 化的对中间件协议的直接支撑带来的扩展性问题也逐步凸显，Dapr 的应用运行时概念也逐步崛起，这一年我们开源了 Layotto，期望通过对应用运行时 API 的统一来解决应用和后端中间件具体实现耦合的问题，进一步解耦应用和基础设施，解决应用在多云运行时的厂商绑定问题。 2022 年随着 Mesh 化落地的基础设施能力逐步完善，我们开始考虑 Mesh 化如果给业务带来更多价值，在 Mesh 1.0 时代，我们把中间件相关的能力尽可能做了下沉，提升了基础设施的迭代效率，在 Mesh 2.0 时代，我们期望能有一种机制可以让业务侧相对通用的能力，也可以做到按需下沉，并且具备一定的隔离性，避免下沉的能力影响 Mesh 数据代理主链路。这部分将在看未来部分做一些介绍。 图示的方式简诉一下 Service Mesh 架构演进的几个阶段： SOA 时代，中间件的客户端均直接集成在业务进程内： Mesh 化阶段一：中间件能力下沉，应用和基础设施实现部分解耦： 应用运行时阶段：将应用和具体基础设施的类型解耦，仅依赖标准 API 编程： 三、东西向流量规模化挑战 Mesh 化后的数据面 MOSN 承载了应用间非常核心的东西向通信链路，目前在蚂蚁集团内部覆盖应用数千，覆盖容器数十W+，海量的规模带来了如长连接膨胀、服务发现数据量巨大、服务治理困难等问题。接下来我们来聊一聊我们在演进的过程中遇到并解决掉的一些经典问题。 3.1 长连接膨胀问题 在海量规模的应用背后存在着复杂的调用关系，部分基础性服务被大部分应用所依赖，由于调用方全连服务提供方的机制存在，一个基础性服务的单 Pod 需要日常承载近 10W 长连接，单机 QPS 一般还是有上限的，我们以 1000 QPS 的 Pod 举例，10w 长连接的场景下，每条长连接上的 QPS 是非常低的，假设所有连接的请求均等，平均每条长连接每 100s 仅有一次请求产生。 为了保证长连接的可用性，SOFA RPC 的通信协议 Bolt 有定义心跳包，默认心跳包是 15s 一次，那么一条长连接上的请求分布大概如下图所示： 在上诉场景中，一条长连接上，心跳包的请求数量远大于业务请求的数量，MOSN 在日常运行中，用于维护长连接可用句柄持有内存的开销，还有心跳包发送的 CPU 开销，在海量规模集群下不可忽视。 基于以上问题，我们找到了两个解法： 在保证连接可用的前提下减少心跳频率 在保证负载均衡的前提下降低应用间的连接数 3.1.1 心跳退避 由于心跳的主要作用是尽可能早的发现长连接是否已不可用，通常我们认为经过 3 次心跳超时即可判定一条长连接不可用，在一条长连接的生命周期里，不可用的场景占比是非常低的，如果我们把长连接的检测周期拉长一倍就可以减少50%的心跳 CPU 损耗。为了保障检测的及时性，当出现心跳异常（如心跳超时等）场景时，再通过降低心跳周期来提高长连接不可用时的判定效率，基于以上思路我们设计了 MOSN 里的长连接心跳退避策略： 当长连接上无业务请求且心跳正常响应时，逐步将心跳周期拉长 15s -&amp;gt; 90s 当长连接上出现请求失败或心跳超时的场景时，将心跳周期重置回 15s 当长连接上存在正常业务请求时，降级本次心跳周期内的心跳请求 通过以上心跳退避的手段，MOSN 的常态心跳 CPU 消耗降低至原来的 25%。 3.1.2 服务列表分片 从心跳退避的优化可以看出，在海量长连接的场景下，单长连接上的请求频率是很低的，那么维护这么多长连接除了对负载均衡比较友好之外，其他的收益并不大，那么我们还有另外一个优化方向，就是减少客户端和服务端之间建立的长连接数量。 MOSN 使用一致性哈希的策略对服务端机器进行分组：在客户端的内存中，首先将全量的服务端机器列表加入到一致性哈希环中，然后基于配置计算预期分片情况下的机器列表数 N，随后根据客户端机器 IP，从一致性哈希环中获取 N 个机器列表作为本机器的分片列表。每个客户端计算的哈希环都是一样的，不同的机器 IP 使得最终选择的机器分片列表是不同的。实现了不同客户端机器持有不同的服务端集群分片的效果。 通过对服务列表的分片优化，客户端向服务端建立的长连接数量急剧减小，在 6w 长连接且采用 50% 的负载均衡分片的场景下：单机 CPU 降低约 0.4 Core，内存降低约 500M。 3.2 海量服务发现问题 MOSN 的服务发现能力没有使用 Pilot，而是在内部直接和 SOFARegistry（服务注册中心） 对接，使用这种架构的原因之一就是 RPC 的接口级服务发现，节点的 Pub、Sub 量巨大，海量应用的频繁运维产生的节点变更推送对 Pilot 的性能和及时性挑战都很大，社区有使用 Pilot 在稍大规模下做 CDS 下发的过程中也发现非常多的性能问题并提交 PR 解决，但对于蚂蚁集团一个机房就有 200W Pub，2000W Sub 的规模下，Pilot 是完全无法承载的。SOFARegistry 的架构是存储和连接层分离，存储为内存分片存储，连接层也可以无限水平扩容，在内部海量节点变更下也能实现秒级变更推送。 虽然 SOFARegistry 的推送能力没什么问题，不过海量节点变更后产生的推送数据，会导致 MOSN 内有大量的 Cluster 重构，列表下发后到 Cluster 构建成功的过程中，会有大量的临时内存产生，以及 CPU 计算消耗。这些尖刺型内存申请和 CPU 占用，是可能直接影响请求代理链路稳定性的。为了解决这个问题，我们也考虑过两个优化方向： SOFARegistry 和 MOSN 之间把全量推送改造为增量推送 服务发现模型从接口级切换为应用级 其中第一点能带来的效果是每次列表推送变化为原推送规模的 1/N，N 取决于应用变更时的分组数。第二点能带来的变化是更加明显的，我们假设一个应用会发布 20个接口，100个应用的 Pod 产生的服务发现数据是 20*100=2000 条数据，接口粒度服务发现的数据总量会随着应用接口数量的增长数倍于应用节点数的规模持续增长；而应用级服务发现可以把节点总量控制在应用 Pod 数这个级别。 3.2.1 应用级服务发现演进 接口级服务发现示例（相同节点中多个服务中重复出现）： 应用级服务发现示例（结构化表示应用、服务、地址列表间的关系）： 通过对应用和接口关联信息的结构化改变，服务发现的节点数量可以下降一到两个数量级。 接口级服务发现演进到应用级服务发现对于 RPC 框架来讲是一个巨大的变化，社区中有 Dubbo 3.0 实现了应用级服务发现，但这种跨大版本的升级兼容性考量很多，对于在奔跑的火车上换轮子这件事情，在框架层演进是比较困难的。由于蚂蚁集团内部的 Service Mesh 已经覆盖 90% 的标准应用，所以在服务发现演进方面我们可以做的更加激进，结合 MOSN + SOFARegistry 6.0，我们实现了接口级服务发现和应用级服务发现的兼容性以及平滑切换的方案，通过 MOSN 版本的迭代升级，目前已经完成接口级到应用级服务发现的切换。 通过上述改进，生产集群的服务发现数据 Pub 数据量下降 90%，Sub 数据量下降 80%，且整个过程对应用完全无感，这也是 Mesh 化业务和基础设施解耦后带来的实际便利体现。 3.2.2 MOSN Cluster 构造优化 通过应用级服务发现解决数据量变更过大的问题之后，我们还需要解决下在列表变更场景下产生的 CPU 消耗和临时内存申请尖刺问题，在这个问题中通过对内存申请的分析，Registry Client 在收到服务端推送的列表信息之后需要经历反序列化，构造 MOSN 需要的 Cluster 模型并更新 Cluster 内容，其中比较重的就是构建 Cluster 过程中的 Subset 构建。通过使用对象池，并且尽量减少 byte[] 到 String 的拷贝，降低了内存分配，另外通过 Bitmap 优化 Subset 的实现，让整个 Cluster 的构造更加高效且低内存申请。 经过上述优化，在超大集群应用运维时，订阅方列表变更临时内存申请降低于原消耗的 30%，列表变更期间 CPU 使用量降低为原消耗的 24%。 3.3 服务治理智能化演进 MOSN 把请求链路下沉之后，我们在服务治理方面做了非常多的尝试，包括像客户端精细化引流、单机压测引流、业务链路隔离、应用级别的跨单元容灾、单机故障剔除、各种限流能力等，篇幅关系我这里仅介绍下我们在限流场景下做的智能化探索。 开源社区的 Sentinel 项目在限流方向做了一个非常好的实践，MOSN 在做限流早期就和 Sentinel 团队沟通，希望能基于 Sentinel 的 Golang 版本 SDK 来做扩展，站在巨人的肩膀上，我们做了更多的尝试。 基于 Sentinel 可插拔的 Slot Chain 机制，我们在内部扩展了很多限流模块的实现，如自适应限流 Slot、集群限流 Slot、熔断 Slot、日志统计 Slot 等。 在 MOSN 做限流能力之前，Java 进程内也是存在限流组件的，业务常用的是单机限流，一般会有一个精确的限流值，这个值需要经过反复的压测，才能得到单机的最大可健康承载的 TPS，这个值会随着业务应用本身的不断迭代，功能增加，链路变的更复杂而逐步变化，所以每年大促前，都会准备多轮全链路压测，来确保每个系统都能在满足总 TPS 的情况下对自身应用所应该配置的限流值有一个精确的预估。 为了解决限流配置难的问题，我们尝试在 MOSN 内实现了自适应限流，根据对容器当前的接口并发、CPU、Load1 信息采集上报，再结合最近几个滑动窗口中，每个接口的请求量变化，可以自动识别是什么接口的并发量增加导致了 CPU 资源占用的提升，当负载超过一定的基线之后，限流组件可以自动识别出哪些接口应该被限流以避免资源使用超过健康水位。 在实际的生产环境中，自适应限流可以迅速精准的定位异常来源，并秒级介入，迅速止血，同时也可以识别流量类型，优先降低压测流量来让生产流量尽可能成功。大促前再也不需要每个应用 Owner 去给自己应用的每个接口配置限流值，大幅度提升研发幸福感。 四、南北向流量打通 MOSN 作为 Service Mesh 的数据面主要在东西向流量上发力，除了东西向流量之外，还有南北向流量被多种网关分而治之。 蚂蚁集团下有许多不同的公司主体，分别服务于不同的业务场景，各主体有与之对应的站点来部署应用对外提供服务，南北向流量最常见的是互联网流量入口，这个角色在蚂蚁集团由 Spanner 承载。除了互联网流量入口之外，多个主体公司间也可能存在信息交互，在同一个集团内的多公司主体如果信息交互需要绕一道公网，稳定性会大打折扣，同时带宽费用也会更贵。为了解决跨主体的高效互通问题，我们通过 SOFAGW 搭建起了多主体间的桥梁，让跨主体的应用间通信和同主体内的 RPC 通信一样简单，同时还具备链路加密、鉴权、可审计等能力，保障多主体间调用合规。 SOFAGW 基于 MOSN 2.0 架构打造，既能使用 Golang 做高效研发，同时也能享受 Envoy 在 Http2 等协议处理上带来的超高性能。 简单介绍一下 MOSN 2.0 架构，Envoy 提供了可扩展的 Filter 机制，来让用户可以在协议处理链路中插入自己的逻辑，MOSN 通过实现一层基于 CGO 的 Filter 扩展层，将 Envoy 的 Filter 机制进行了升级，我们可以用 Golang 来写 Filter 然后嵌入 Envoy 被 CGO 的 Filter 调用。 SOFAGW 在 MOSN 2.0 之上构建了自己的网关代理模型，通过 SOFA 的 Golang 客户端和控制面交互获取配置信息、服务发现信息等，然后重组成 Envoy 的 Cluster 模型通过 Admin API 插入 Envoy 实例中。通过 Golang 的 Filter 扩展机制，SOFAGW 实现了蚂蚁集团内部的 LDC 服务路由、压测流量识别、限流、身份认证、流量复制、调用审计等能力。由于 Envoy 的 Http2 协议处理性能相比纯 Golang GRPC 实现高出 2～4倍，SOFAGW 选择将 Triple （Http2 on GRPC）协议处理交给 Envoy 来处理，将 Bolt （SOFA RPC 私有协议）协议的处理依然交给 MOSN 来处理。 通过上述架构，SOFAGW 实现了蚂蚁集团内部的全主体可信互通，在高性能和快速迭代开发间也取得了不错的平衡。 五、应用运行时探索 随着 Service Mesh 化的探索进入深水区，我们把很多能力沉淀到 Mesh 的数据面之后，也感受到每种协议直接下沉的便利性与局限性，便利在于应用完全不用改造就可以平滑接入，局限性是每种私有协议均需要独立对接，且使用了 A 协议的应用，并不能直接在 B 协议上运行。在多云的环境下，我们希望可以做到让应用 Write Once，Run on any Cloud！想要实现这一愿景，我们需要将应用与基础设施间进一步解耦，让应用不直接感知底层的具体实现，而是使用分布式语义 API 来编写程序。这种思想在社区已经有 Dapr 作为先行者在探索： （上图来自 Dapr 官方文档） Dapr 提供了分布式架构下的各种原子 API，如服务调用、状态管理、发布订阅、可观测、安全等，并且实现了不同分布式原语在不同云上的对接实现组件。 （上图来自 Dapr 官方文档） Dapr 相当于是在 Service Mesh 之上提供给应用更加无侵入的分布式原语，2021 年中，我们基于 MOSN 开源了应用运行时 Layotto，Layotto 相当于是 Application Runtime 和 Service Mesh 的合集： （上图修改自 Dapr 官方文档） 我们通过 Layotto 抽象出应用运行时 API 将内部的 Service Mesh 演进至如下架构： 当然应用运行时是一个新的概念，如果这一层 API 抽象做不到足够中立，那么依然需要面临使用方需要 N 选 1 的局面，所以我们也在和 Dapr 社区一起制定 Application Runtime API 的标准，组织 Dapr Sig API Group 用于推进 API 的标准化，也期望能有更多感兴趣的同学一同加入。 期待未来大家的应用都可以 Write once, Run on any Cloud！。 六、Mesh 2.0 探索 2022 年我们继续向前探索，基于 MOSN 2.0 我们有了高性能的网络底座、易于扩展的 Mesh 数据面，基于 Layotto 我们有了无厂商绑定的应用运行时。 下一步我们期望基于 eBPF 实现 Mesh 数据面的进一步下沉，从 Pod 粒度下沉到 Node 粒度，同时服务于更多场景，如 Function、Serverless，另外基于 MOSN 2.0 的良好扩展能力，我们希望能进一步尝试将业务应用相对通用的能力也可以沉淀下来，作为 Mesh 数据面的自定义插件来为更多应用提供服务，帮助业务实现相对通用的业务能力也可以快速迭代升级。 相信在不远的未来，Mesh 2.0 可以在蚂蚁集团内部服务众多通用场景，也能给社区带来一些新的可能。以上是本次分享的所有内容，希望大家能从对蚂蚁集团 Service Mesh 的发展过程的交流中有所收获。</summary></entry><entry><title type="html">家庭网络折腾记</title><link href="https://jervyshi.me/home-network-toss/" rel="alternate" type="text/html" title="家庭网络折腾记" /><published>2021-07-31T00:00:00+00:00</published><updated>2021-07-31T00:00:00+00:00</updated><id>https://jervyshi.me/home-network-toss</id><content type="html" xml:base="https://jervyshi.me/home-network-toss/">&lt;h2 id=&quot;0x00-缘起&quot;&gt;0x00 缘起&lt;/h2&gt;

&lt;p&gt;写这篇文章主要还是想回顾下入住 3 年半，随着诉求的逐步升级，整个家庭网络也经历过多次迭代，不过由于装修时的埋线限制，很多想法不好实现，只能在当前的场景下寻求最优解，如果再有一次从毛坯重来的机会，肯定可以做的更好，就把自己这些折腾的过程记录一下。&lt;/p&gt;

&lt;h2 id=&quot;0x01-户型&quot;&gt;0x01 户型&lt;/h2&gt;

&lt;p&gt;先介绍下背景，便于理解后续的展开，户型南北通透，大致方位布局如下：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/1627723195153-2ecd0186-276b-4bd8-82a5-b7c78a36b196.png&quot; alt=&quot;户型布局&quot; /&gt;&lt;/p&gt;

&lt;p&gt;弱电箱在书房，客厅拉了两根网线，主卧、次卧、书房各一根。&lt;/p&gt;

&lt;h2 id=&quot;0x02-网络拓扑-v1&quot;&gt;0x02 网络拓扑 V1&lt;/h2&gt;

&lt;p&gt;刚入住的时候，拉了电信宽带，弱电箱光猫直接两根网线接至客厅，一个给无线路由，一个给 IPTV，两个设备都居中放在客厅电视柜处，简单粗暴。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/1627713707033-d1ae1b0d-4bf3-4bdd-bf17-cae2d8a3eb03.png&quot; alt=&quot;家庭网络 V1.0.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;这个阶段大部分设备都围绕客厅路由器为主，包括 Xbox One S，Nintendo Switch、Synology NAS 都围绕在路由器周围，活动范围主要也是主卧和客厅，所以一切都还不错。各种智能吸顶灯、净水器、空气净化器等均以 2.4G 无线与主路由交互，弱电箱交换机都没有放，因为没有用其他网线的诉求。&lt;/p&gt;

&lt;p&gt;主路由 ASUS AC88U 刷了 &lt;a href=&quot;https://firmware.koolshare.cn/&quot;&gt;Koolshare 改版的梅林固件&lt;/a&gt;，具备了基本的科学上网能力，借助 DDNS 能力也具备了在线管理路由器的能力，不过也没啥设备好管的。&lt;/p&gt;

&lt;h2 id=&quot;0x03-网络拓扑-v2&quot;&gt;0x03 网络拓扑 V2&lt;/h2&gt;

&lt;p&gt;随着时间的推移，有了宝宝，家里老人来带孩子，次卧就逐步启用了，这个时候主路由的信号瓶颈逐步凸显，次卧和次卫信号质量不佳，老人夜里想看看视频什么的体验就比较差，加上小区里竟然遇到过到家门口玄关偷鞋的贼一栋楼扫下来提走了几兜子的鞋，门口强电处放个摄像头就成了刚需，苦于没线可拉只能采用无线方案，但毕竟处于室外，摄像头很难稳定连接到主路由。&lt;/p&gt;

&lt;p&gt;为了解决这个问题，闲鱼收了一个 AC68U，组了个 Mesh 网络，扩大了同 SSID 的无线覆盖面，AC68U 直接埋在了弱电箱里，此时拓扑变为：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/1627715989319-ef89f804-a911-46f2-91ea-150d7095a7b5.png&quot; alt=&quot;家庭网络 V2.0.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;主路由换为 AC68U 之后，科学上网的效果就不是太好了，本身性能就不高再加上大量加解密计算，对于我已经升级到千兆的宽带来说，还是有点扛不起大旗。工作搞 Service Mesh 的同时，在家也搞个 Mesh 网络，我跟 Mesh 还挺有缘 😀。&lt;/p&gt;

&lt;h2 id=&quot;0x04-网络拓扑-v3&quot;&gt;0x04 网络拓扑 V3&lt;/h2&gt;

&lt;p&gt;为了增加可玩性，在 V2 的基础上把主路由换成了软路由 R2S，当时 R2S 的价格还在合理区间，目前性价比已不高。固件是 404 大佬改过的 &lt;a href=&quot;https://github.com/QiuSimons/R2S-R4S-X86-OpenWrt&quot;&gt;OpenWRT&lt;/a&gt;。过程中又入坑了洋垃圾，低成本攒了一个12核24线程64G内存的服务器，服务器噪声还是有的，在电源并没有选服务器模组电源的情况下，日常 40dB 左右噪音还可以接收，但这么大个的东西还是只能放书房最合适，书房的网线终于排上了用场，这时拓扑已变为：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/1627718148061-64716ca5-e239-4d69-bfaa-96ecbd38a344.png&quot; alt=&quot;家庭网络 V3.0.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;AC88U 和 AC68U 在这个拓扑下是只做无线 AP 使用同时也组成 Mesh 网络，关闭 DHCP 能力，R2S 做主路由负责拨号、科学上网、端口转发、广告屏蔽、内网穿透（Zerotier）等能力入口。&lt;/p&gt;

&lt;p&gt;服务器装了 ESXI 并按照 CentOS 和 Win10 虚拟机，Win10 可以通过内网穿透加 RDP 随意穿回内网，CentOS 装了 Kubernetes 做一个自己的测试机，可玩性极高。&lt;/p&gt;

&lt;p&gt;另外再推荐下&lt;a href=&quot;https://twitter.com/waylybaye&quot;&gt;八爷&lt;/a&gt;的 ServerCat，电信的公网 IP 加上仅密钥登录，手机管理家庭设备，使用频率虽不高，但是胜在能装 X 啊。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/1627719424077-6aa61cd3-4dd2-44ab-8791-f55a3cb67c40.jpeg&quot; alt=&quot;IMG_2789.JPG&quot; /&gt;&lt;/p&gt;

&lt;p&gt;缺点是 R2S 做主路由不适合经常折腾，否则刷机之后全家上不了网，分分钟就要面对全家的质问，这个 SLA 保障不好影响家庭和谐。更好的方式是软路由做旁路由，受限于我当前的设备及网线情况，这种折腾方式暂时不适用我的情况。&lt;/p&gt;

&lt;h2 id=&quot;0x05-总结一下&quot;&gt;0x05 总结一下&lt;/h2&gt;

&lt;p&gt;装修比较早，网线埋的超五类，升级困难，再来一次就准备直接拉光纤了，局域网设备极限速度大幅提升，成本也不会增加很多。弱电箱到客厅建议至少拉上三条网线避免想把主路由放客厅的时候不好来回就比较尴尬。有科学上网诉求建议还是上个软路由，可玩性和速度好很多。当然你要是能读到这里大概率也会根据自己的情况构建适合自己的网络拓扑，毕竟我博客没科学上网也访问不了。&lt;/p&gt;

&lt;p&gt;折腾无止境，这也只是阶段性的拓扑，接下来说不定也就换旁路由模式来玩。&lt;/p&gt;

&lt;p&gt;如果你对洋垃圾感兴趣这里有我的配置单供参考，基础配置来自&lt;a href=&quot;https://www.youtube.com/watch?v=UpNTTsoI24Y&amp;amp;list=PL4Bi3PNHpZKxSIyXx3wvy1yqqigxtlS0u&quot;&gt;账户未命名&lt;/a&gt;，我做了部分修改：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;部件&lt;/th&gt;
      &lt;th&gt;型号&lt;/th&gt;
      &lt;th&gt;价格参考&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;CPU&lt;/td&gt;
      &lt;td&gt;E5 2658AV3&lt;/td&gt;
      &lt;td&gt;399&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;散热&lt;/td&gt;
      &lt;td&gt;捷豹超微款E5 2011 CPU散热器【正方形扣具】&lt;/td&gt;
      &lt;td&gt;159&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;主板&lt;/td&gt;
      &lt;td&gt;华硕Z10PA-U8/10G-2S&lt;/td&gt;
      &lt;td&gt;1300&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;内存&lt;/td&gt;
      &lt;td&gt;三星ECC内存 16Gx4 （DDR4 2133）&lt;/td&gt;
      &lt;td&gt;1060&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;机箱/电源&lt;/td&gt;
      &lt;td&gt;超微 CSE-743TQ-865B-SQ 8盘位塔式服务器机箱EATX主板工作站机箱 + 超微 PWS-865-PQ 865W 塔式工作站电源&lt;/td&gt;
      &lt;td&gt;1100&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;硬盘&lt;/td&gt;
      &lt;td&gt;金胜维（KingSpec）M.2 SATA 2242 SSD固态硬盘 1TB SATA协议 2242 NGFF/M.2&lt;/td&gt;
      &lt;td&gt;650&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;前面板&lt;/td&gt;
      &lt;td&gt;TOOLFREE MRA752 2.5寸+3.5寸SATA光驱位硬盘盒抽取盒+USB3.0 Hub&lt;/td&gt;
      &lt;td&gt;180&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;</content><author><name>JervyShi</name></author><category term="life" /><category term="network" /><category term="toss" /><category term="life" /><summary type="html">0x00 缘起 写这篇文章主要还是想回顾下入住 3 年半，随着诉求的逐步升级，整个家庭网络也经历过多次迭代，不过由于装修时的埋线限制，很多想法不好实现，只能在当前的场景下寻求最优解，如果再有一次从毛坯重来的机会，肯定可以做的更好，就把自己这些折腾的过程记录一下。 0x01 户型 先介绍下背景，便于理解后续的展开，户型南北通透，大致方位布局如下： 弱电箱在书房，客厅拉了两根网线，主卧、次卧、书房各一根。 0x02 网络拓扑 V1</summary></entry><entry><title type="html">再见 2020</title><link href="https://jervyshi.me/bye-2020/" rel="alternate" type="text/html" title="再见 2020" /><published>2021-02-11T00:00:00+00:00</published><updated>2021-02-11T00:00:00+00:00</updated><id>https://jervyshi.me/bye-2020</id><content type="html" xml:base="https://jervyshi.me/bye-2020/">&lt;p&gt;为什么是再见 2020 呢，其实是想写的总结从公历结尾拖到了农历结尾，就算结束农历的 2020 吧，再不写就真跨年了~&lt;/p&gt;

&lt;h2 id=&quot;博客回归&quot;&gt;博客回归&lt;/h2&gt;

&lt;p&gt;曾经用过 jervyshi.me 做博客域名，奈何因为不怎么看邮件忘记了域名续费，尝试过竞价买回，奈何出到 $600+ 对方都没回应，想想也没这么值钱便放弃了，然后 blog 就一直处于不可访问状态，另外也确实没什么想写的，就在各处去掉了个人介绍中的个人主页地址。前几个月翻了翻发现还有个 jervyshi.com 没被注册，索性就换个域名好了。只是一直也没闲下来打理，域名又放着了，临近过年，趁着请假在家的几天，还是给这个 2020 收个尾，又折腾了下，把 blog 搞回来了，顺便升级了下 jekyll 版本，把 github 一直提示我的 kramdown 的安全问题给修了（也就升级个版本对吧……）。为了不让这么个小站显的那么的空洞，把 2019 年对外演讲的两篇稿子挪了过来，之前是发在《金融级分布式架构》公众号与 &lt;a href=&quot;https://www.sofastack.tech/&quot;&gt;SOFAStack&lt;/a&gt; 博客中，部分文字来自&lt;a href=&quot;https://twitter.com/Littletree_xc&quot;&gt;花肉&lt;/a&gt;和潘潘，十分感谢。&lt;/p&gt;

&lt;h2 id=&quot;那些事儿&quot;&gt;那些事儿&lt;/h2&gt;

&lt;h3 id=&quot;新冠&quot;&gt;新冠&lt;/h3&gt;

&lt;p&gt;2020 的开头就是那糟心的新冠来袭，整个春节窝在家里，这是第一个没有回老家过年的春节。大门不出二门不迈的日子糟心的感觉就不说了，说说得到了什么。可能从儿子出生之后，还没有这么多时间能一直陪着家人，这一两个月精进了不少厨艺，还在自己在家里蒸了馒头做主食，所谓生活气息也就如此吧。&lt;/p&gt;

&lt;h3 id=&quot;远程办公&quot;&gt;远程办公&lt;/h3&gt;

&lt;p&gt;开工之后体会了下什么叫做远程办公，大概就是所有的沟通都必须视频会议完成，午饭晚饭都在开会中度过，钉钉和阿里郎可是同时接听不同会议，省去了上下班路上的时间，有效工作时长没有减少反而有增加，据说事后人效统计远程办公效率高于非远程办公，也是奇迹~不过我还是喜欢能和人面对面的感觉，更有真实感。&lt;/p&gt;

&lt;h3 id=&quot;晋升&quot;&gt;晋升&lt;/h3&gt;

&lt;p&gt;年中得益于 Service Mesh 在内部的顺利落地，晋升也水到渠成，晋升后也老板送了一本《上任第一年：从业务骨干向优秀管理这转型》给我，就这样开始了管理转型。&lt;/p&gt;

&lt;h3 id=&quot;成长&quot;&gt;成长&lt;/h3&gt;

&lt;p&gt;后半年基本在焦虑中度过，各种转型不适，心态，时间管理，关注事到关注人，庆幸&lt;a href=&quot;https://nobodyiam.com/&quot;&gt;宋顺&lt;/a&gt;老板一直给建议和开导，逐渐从焦虑转向宁静，也庆幸团队中的小伙伴都十分靠谱，大家都还是在各自领域有不少收获，也拿到不错的结果。感谢每一个帮助过我的人。&lt;/p&gt;

&lt;h3 id=&quot;上市&quot;&gt;上市&lt;/h3&gt;

&lt;p&gt;过山车般的心情，不想多讲，人生总要经历些大起大落才能成长，疯狂之后的平静才是最正常的状态。&lt;/p&gt;

&lt;h3 id=&quot;家庭&quot;&gt;家庭&lt;/h3&gt;

&lt;p&gt;晋升前一直和老婆说，晋升后我抽更多的时间陪你和孩子，事实打脸来的那么快，我还是没多少时间能抽出来。儿子也两岁了，做的比以前好的是周末可以给更多高质量的陪伴。孩子小的时候成长是飞速的，总是能在某事某刻给你新的惊喜。当然，苦恼也是少不了的，半夜不睡、感冒发烧、小脾气也是能感觉到各种酸爽。&lt;/p&gt;

&lt;h3 id=&quot;健身&quot;&gt;健身&lt;/h3&gt;

&lt;p&gt;身体差这个事情也持续了很多年了，新冠期间还感冒发烧跑发热门诊多次的感觉着实不爽，一次在部门里都出了名促进了团队的运动风也不知是可悲还是可笑。总之从四月份开始在家 Keep 健身，到六月份乐刻请了私教上了 40 来节课增肌，到后来自己偶尔坚持练，身体确实好了很多。不过增肌的时候没怎么控制住饮食，和肌肉一起涨起来的是脂肪，也算涨了 5kg，肌肉和脂肪占比就无所谓了，总之身体更健康也养成了一些需要持续坚持的健身习惯，希望明年不要落下。&lt;/p&gt;

&lt;h3 id=&quot;英语&quot;&gt;英语&lt;/h3&gt;

&lt;p&gt;为什么学英语，说起来初衷也挺简单的，不希望以后儿子学英语的时候自己一口渣渣的口语被儿子鄙视，所以从五月份开始买了流利说英语两年的课程，每周坚持 5 天以上，每次 30 分钟以上，已经持续坚持到现在未成中断，每天打卡截止时间是第二天 2:00 ，这也造成了我长期 2:00 睡的作息，Deadline 是第一生产力么，不管怎样，还是要坚持不中断。要说提升有多少吧，也不见得，至少发音标准了一些吧。&lt;/p&gt;

&lt;h2 id=&quot;收个尾吧&quot;&gt;收个尾吧&lt;/h2&gt;

&lt;p&gt;一年的时间转瞬即逝，新的一年给自己立几个 flag：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;坚持健身，一周至少 2 次。&lt;/li&gt;
  &lt;li&gt;坚持每日半小时英语学习。&lt;/li&gt;
  &lt;li&gt;Blog 更新五篇以上，内容不限。&lt;/li&gt;
  &lt;li&gt;至少读 3 本书，类型不限。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;等 2021 结尾再来回顾一下，看看能打脸几次。&lt;/p&gt;</content><author><name>JervyShi</name></author><category term="essay" /><category term="essay" /><summary type="html">为什么是再见 2020 呢，其实是想写的总结从公历结尾拖到了农历结尾，就算结束农历的 2020 吧，再不写就真跨年了~ 博客回归 曾经用过 jervyshi.me 做博客域名，奈何因为不怎么看邮件忘记了域名续费，尝试过竞价买回，奈何出到 $600+ 对方都没回应，想想也没这么值钱便放弃了，然后 blog 就一直处于不可访问状态，另外也确实没什么想写的，就在各处去掉了个人介绍中的个人主页地址。前几个月翻了翻发现还有个 jervyshi.com 没被注册，索性就换个域名好了。只是一直也没闲下来打理，域名又放着了，临近过年，趁着请假在家的几天，还是给这个 2020 收个尾，又折腾了下，把 blog 搞回来了，顺便升级了下 jekyll 版本，把 github 一直提示我的 kramdown 的安全问题给修了（也就升级个版本对吧……）。为了不让这么个小站显的那么的空洞，把 2019 年对外演讲的两篇稿子挪了过来，之前是发在《金融级分布式架构》公众号与 SOFAStack 博客中，部分文字来自花肉和潘潘，十分感谢。 那些事儿 新冠 2020 的开头就是那糟心的新冠来袭，整个春节窝在家里，这是第一个没有回老家过年的春节。大门不出二门不迈的日子糟心的感觉就不说了，说说得到了什么。可能从儿子出生之后，还没有这么多时间能一直陪着家人，这一两个月精进了不少厨艺，还在自己在家里蒸了馒头做主食，所谓生活气息也就如此吧。 远程办公 开工之后体会了下什么叫做远程办公，大概就是所有的沟通都必须视频会议完成，午饭晚饭都在开会中度过，钉钉和阿里郎可是同时接听不同会议，省去了上下班路上的时间，有效工作时长没有减少反而有增加，据说事后人效统计远程办公效率高于非远程办公，也是奇迹~不过我还是喜欢能和人面对面的感觉，更有真实感。 晋升 年中得益于 Service Mesh 在内部的顺利落地，晋升也水到渠成，晋升后也老板送了一本《上任第一年：从业务骨干向优秀管理这转型》给我，就这样开始了管理转型。 成长 后半年基本在焦虑中度过，各种转型不适，心态，时间管理，关注事到关注人，庆幸宋顺老板一直给建议和开导，逐渐从焦虑转向宁静，也庆幸团队中的小伙伴都十分靠谱，大家都还是在各自领域有不少收获，也拿到不错的结果。感谢每一个帮助过我的人。 上市 过山车般的心情，不想多讲，人生总要经历些大起大落才能成长，疯狂之后的平静才是最正常的状态。 家庭 晋升前一直和老婆说，晋升后我抽更多的时间陪你和孩子，事实打脸来的那么快，我还是没多少时间能抽出来。儿子也两岁了，做的比以前好的是周末可以给更多高质量的陪伴。孩子小的时候成长是飞速的，总是能在某事某刻给你新的惊喜。当然，苦恼也是少不了的，半夜不睡、感冒发烧、小脾气也是能感觉到各种酸爽。 健身 身体差这个事情也持续了很多年了，新冠期间还感冒发烧跑发热门诊多次的感觉着实不爽，一次在部门里都出了名促进了团队的运动风也不知是可悲还是可笑。总之从四月份开始在家 Keep 健身，到六月份乐刻请了私教上了 40 来节课增肌，到后来自己偶尔坚持练，身体确实好了很多。不过增肌的时候没怎么控制住饮食，和肌肉一起涨起来的是脂肪，也算涨了 5kg，肌肉和脂肪占比就无所谓了，总之身体更健康也养成了一些需要持续坚持的健身习惯，希望明年不要落下。 英语 为什么学英语，说起来初衷也挺简单的，不希望以后儿子学英语的时候自己一口渣渣的口语被儿子鄙视，所以从五月份开始买了流利说英语两年的课程，每周坚持 5 天以上，每次 30 分钟以上，已经持续坚持到现在未成中断，每天打卡截止时间是第二天 2:00 ，这也造成了我长期 2:00 睡的作息，Deadline 是第一生产力么，不管怎样，还是要坚持不中断。要说提升有多少吧，也不见得，至少发音标准了一些吧。 收个尾吧 一年的时间转瞬即逝，新的一年给自己立几个 flag： 坚持健身，一周至少 2 次。 坚持每日半小时英语学习。 Blog 更新五篇以上，内容不限。 至少读 3 本书，类型不限。 等 2021 结尾再来回顾一下，看看能打脸几次。</summary></entry><entry><title type="html">蚂蚁金服 Service Mesh 双十一实战</title><link href="https://jervyshi.me/service-mesh-practice-antfinal-shopping-festival-big-exam/" rel="alternate" type="text/html" title="蚂蚁金服 Service Mesh 双十一实战" /><published>2019-11-19T00:00:00+00:00</published><updated>2019-11-19T00:00:00+00:00</updated><id>https://jervyshi.me/service-mesh-practice-antfinal-shopping-festival-big-exam</id><content type="html" xml:base="https://jervyshi.me/service-mesh-practice-antfinal-shopping-festival-big-exam/">&lt;blockquote&gt;
  &lt;p&gt;2019 年的双十一是蚂蚁金服的重要时刻，大规模落地了 Service Mesh 并顺利保障双十一平稳渡过。我们第一时间与这次的落地负责人进行了交流。&lt;/p&gt;

  &lt;p&gt;采访的开头：
花肉：“这次大规模上了 Service Mesh ，双十一值班感觉是什么？”
卓与：“Service Mesh 真的稳。”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/1574056558287-796b7ea3-a30d-4ff8-b020-c41ae8bb1dbb.jpeg&quot; alt=&quot;卓与 TOP100 北京峰会分享现场图&quot; /&gt;&lt;/p&gt;

&lt;p&gt;图为卓与 TOP100 北京峰会分享现场图&lt;/p&gt;

&lt;h2 id=&quot;落地负责人介绍&quot;&gt;落地负责人介绍&lt;/h2&gt;

&lt;p&gt;Service Mesh 是蚂蚁金服下一代架构的核心，今年蚂蚁金服大规模的 Service Mesh 落地，我有幸带领并面对了这个挑战，并非常平稳的通过了双十一的大考。&lt;/p&gt;

&lt;p&gt;我个人主要专注在微服务领域，在服务注册与服务框架方向深耕多年，主导过第五代服务注册中心（SOFARegistry）设计与实施，在微服务的架构演进中持续探索新方向，并在蚂蚁金服第五代架构演进中负责内部 Service Mesh 方向的架构设计与落地。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;SOFAStack：&lt;a href=&quot;https://github.com/sofastack&quot;&gt;https://github.com/sofastack&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;SOFAMosn：&lt;a href=&quot;https://github.com/sofastack/sofa-mosn&quot;&gt;https://github.com/sofastack/sofa-mosn&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;service-mesh-在蚂蚁金服&quot;&gt;Service Mesh 在蚂蚁金服&lt;/h2&gt;

&lt;p&gt;蚂蚁金服很早开始关注 Service Mesh，并在 2018 年发起 ServiceMesher 社区，目前已有 4000+ 开发者在社区活跃。在技术应用层面，Service Mesh 的场景已经渡过探索期，今年已经全面进入深水区探索。&lt;/p&gt;

&lt;p&gt;2019 年的双十一是我们的重要时刻，我们进行了大规模的落地，可能是目前业界最大规模的实践。作为技术人能面对世界级的流量挑战，是非常紧张和兴奋的。当 Service Mesh 遇到双十一又会迸发出怎样的火花？蚂蚁金服的 LDC 架构继续演进的过程中，Service Mesh 要承载起哪方面的责任？我们借助四个“双十一考题”一一为大家揭晓。&lt;/p&gt;

&lt;h2 id=&quot;service-mesh-背景知识&quot;&gt;Service Mesh 背景知识&lt;/h2&gt;

&lt;p&gt;Service Mesh 这个概念社区已经火了很久，相关的背景知识从我们的公众号内可以找到非常多的文章，我在这里不做过于冗余的介绍，仅把几个核心概念统一，便于后续理解。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/1574056558293-58c065c9-c3f2-4d0b-ab23-72566052344e.png&quot; alt=&quot;图1. Service Mesh 开源架构来自 [https://istio.io/](https://istio.io/)&quot; /&gt;&lt;/p&gt;

&lt;p&gt;图1. Service Mesh 开源架构来自 &lt;a href=&quot;https://istio.io/&quot;&gt;https://istio.io/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Istio 的架构图上清晰的描述了 Service Mesh 最核心的两个概念：数据面与控制面。数据面负责做网络代理，在服务请求的链路上做一层拦截与转发，可以在链路中做服务路由、链路加密、服务鉴权等，控制面负责做服务发现、服务路由管理、请求度量（放在控制面颇受争议）等。&lt;/p&gt;

&lt;p&gt;Service Mesh 带来的好处不再赘述，我们来看下蚂蚁金服的数据面和控制面产品，如下图：&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/1574056558297-1ee1945c-3903-4695-add9-76d5d9febf34.png&quot; alt=&quot;图2. 蚂蚁金服 Service Mesh 示意架构&quot; /&gt;&lt;/p&gt;

&lt;p&gt;图2. 蚂蚁金服 Service Mesh 示意架构&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;数据面：SOFAMosn。&lt;/strong&gt;蚂蚁金服使用 Golang 研发的高性能网络代理，作为 Service Mesh 的数据面，承载了蚂蚁金服双十一海量的核心应用流量。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;控制面：SOFAMesh。&lt;/strong&gt;Istio 改造版，落地过程中精简为 Pilot 和 Citadel，Mixer 直接集成在数据面中避免多一跳的开销。&lt;/p&gt;

&lt;h2 id=&quot;2019-service-mesh-双十一大考揭秘&quot;&gt;2019 Service Mesh 双十一大考揭秘&lt;/h2&gt;

&lt;p&gt;双十一 SOFAMosn 与 SOFAMesh 经历海量规模大考，顺利保障双十一平稳渡过。今年双十一蚂蚁金服的百十多个核心应用全面接入 SOFAMosn，生产 Mesh 化容器几十万台，双十一峰值 SOFAMosn 承载数据规模数千万 QPS，SOFAMosn 转发平均处理耗时 0.2ms。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/1574056558305-41757a40-9b46-46a7-8967-d2de6dae78a8.png&quot; alt=&quot;图3. 双十一落地数据&quot; /&gt;&lt;/p&gt;

&lt;p&gt;图3. 双十一落地数据&lt;/p&gt;

&lt;p&gt;在如此大规模的接入场景下，我们面对的是极端复杂的场景，同时需要多方全力合作，更要保障数据面的性能稳定性满足大促诉求，整个过程极具挑战。下面我们将从几个方面来分享下我们在这个历程中遇到的问题及解决方案。&lt;/p&gt;

&lt;h2 id=&quot;双十一考题&quot;&gt;双十一考题&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;如何让 Service Mesh 发挥最大的业务价值？&lt;/li&gt;
  &lt;li&gt;如何达成几十万容器接入 SOFAMosn 的目标？&lt;/li&gt;
  &lt;li&gt;如何处理几十万容器 SOFAMosn 的版本升级问题？&lt;/li&gt;
  &lt;li&gt;如何保障 Service Mesh 的性能与稳定性达标？&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;落地架构&quot;&gt;落地架构&lt;/h2&gt;

&lt;p&gt;为了更加方便的理解以上问题的解决与后续介绍中可能涉及的术语等，我们先来看下 Service Mesh 落地的主要架构：&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/1574056558302-93bd5a33-ce66-46ed-9162-fd75d4fb27d1.png&quot; alt=&quot;图4. Service Mesh 落地架构&quot; /&gt;&lt;/p&gt;

&lt;p&gt;图4. Service Mesh 落地架构&lt;/p&gt;

&lt;p&gt;以上架构图中主要分几部分：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;数据面：借助 Kubernetes 中的 Pod 模型，SOFAMosn 以独立镜像和 App 镜像共同编排在同一个 Pod 内，共享相同的 Network Namespace、CPU、Memory，接入 SOFAMosn 后所有的 App RPC 流量、消息流量均不在直接对外，而是直接和 SOFAMosn 交互，由 SOFAMosn 直接对接服务注册中心做服务发现，对接 Pilot 做配置下发，对接 MQ Server 做消息收发等；&lt;/li&gt;
  &lt;li&gt;控制面：由 Pilot、Citadel 和服务注册中心等组件组成，负责服务地址下发、服务路由下发、证书下发等；&lt;/li&gt;
  &lt;li&gt;底层支撑：Sidecar 的接入与升级等均依赖 Kubernetes 能力，通过 webhook 做 Sidecar 的注入，通过 Operator 做 Sidecar 的版本升级等，相关运维动作均离不开底层的支撑；&lt;/li&gt;
  &lt;li&gt;产品层：结合底层提供的原子能力做运维能力封装，监控对接，采集 Sidecar 暴露的 Metrics 数据做监控与预警，流量调控，安全等产品化能力；&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;蚂蚁金服的答卷&quot;&gt;蚂蚁金服的答卷&lt;/h2&gt;

&lt;h3 id=&quot;1-如何让-service-mesh-发挥最大的业务价值&quot;&gt;1. 如何让 Service Mesh 发挥最大的业务价值？&lt;/h3&gt;

&lt;p&gt;作为一个技术人，我们非常坚持不要为了技术革新本身去做技术革新，&lt;strong&gt;一定要让技术帮助业务，用技术驱动业务&lt;/strong&gt;。这几年随着大家消费习惯以及网络行为的改变，双十一面对的业务场景远比想象中复杂。举个例子大家感受下，大家有没有发现你的女友或者老婆每天对着李佳琦的淘宝直播购物，主播们不断的、实时的红包、上新等等，带来了远比秒杀更复杂的业务场景和体量。大促的模式也更加丰富，不同场景下的大促涉及的应用是不同的，每一类应用在应对独特的洪峰时都需要有足够的资源。&lt;/p&gt;

&lt;p&gt;假如运营同学在不同时间点设计了两种活动，两种活动分别会对应两类不同的应用，如果这两类应用都在大促前准备充足的资源自然是轻松渡过大促峰值，但大促洪峰时间短暂，大量的资源投入有很长一段时间都处于空闲状态，这自然不符合技术人的追求。&lt;/p&gt;

&lt;p&gt;那么如何在不增加资源的场景下渡过各种大促呢？&lt;/p&gt;

&lt;p&gt;核心问题就是如何在足够短的时间内做到大规模资源腾挪，让一批机器资源可以在不同时间点承载起不同的大促洪峰。&lt;/p&gt;

&lt;p&gt;面对这样的挑战，我们会有怎样的解法呢？&lt;/p&gt;

&lt;p&gt;Service Mesh 618 大促落地试点时，我们有介绍到为什么要做这个事情，核心价值是业务与基础设施解耦，双方可以并行发展，快速往前走。那么并行发展究竟能为业务带来哪些实际的价值？除了降低基础组件的升级难度之外，我们还在资源调度方向做了以下探索：&lt;/p&gt;

&lt;h4 id=&quot;11-腾挪调度&quot;&gt;1.1 腾挪调度&lt;/h4&gt;

&lt;p&gt;说到资源调度，最简单的自然是直接做资源腾挪，比如大促A峰值过后，大促A对应的应用通过缩容把资源释放出来，大促B对应的应用再去申请资源做扩容，这种方式非常简单，难点在于当资源规模非常庞大时，缩容扩容的效率极低，应用需要把资源申请出来并启动应用，耗时很长，假如多个大促之间的时间间隔很短，腾挪需要的耗时极有可能超过大促时间间隔，这种调度方案已不能满足双十一多种大促的诉求。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/1574056558298-65f6f60b-b019-4e1c-abca-6757f39732ba.png&quot; alt=&quot;图5. 腾挪调度&quot; /&gt;&lt;/p&gt;

&lt;p&gt;图5. 腾挪调度&lt;/p&gt;

&lt;h4 id=&quot;12-分时调度&quot;&gt;1.2 分时调度&lt;/h4&gt;

&lt;p&gt;腾挪调度最大的问题是应用需要冷启动，冷启动本身的耗时，加上冷启动后预热需要的耗时，对整个腾挪时间影响极大。假如应用不需要启动就能完成资源腾挪，整个调度速度将会加快很多。基于应用不需要重新启动即可完成资源腾挪的思路，我们提出了分时调度的方案：分时调度会通过超卖的机制申请出足够的容器。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/1574056558307-7fe7df2e-8f88-40fa-97fb-06eb63a732c6.png&quot; alt=&quot;图6. 分时调度&quot; /&gt;&lt;/p&gt;

&lt;p&gt;图6. 分时调度&lt;/p&gt;

&lt;p&gt;我们把资源池中的应用容器分为两种状态（4C8G 规格为例）：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;运行态：&lt;/strong&gt;运行态的应用处于全速运行的状态（资源可使用到 4C8G），它们可以使用充足的资源全速运行，承载 100% 的流量；&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;保活态：&lt;/strong&gt;保活态的应用处于低速运行的状态（资源可使用到 1C2G），它们仅可使用受限的资源低速运行，承载 1% 的流量，剩余 99% 的流量由 SOFAMosn 转发给运行态节点；&lt;/li&gt;
&lt;/ul&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/1574056558347-836c91a2-9b43-4f35-be54-ec2547b230c9.png&quot; alt=&quot;图7. 保活态流量转发&quot; /&gt;&lt;/p&gt;

&lt;p&gt;图7. 保活态流量转发&lt;/p&gt;

&lt;p&gt;保活态和运行态可以快速切换，切换时仅需要做 JVM 内存 Swap 以及基于 SOFAMosn 的流量比例切换，即可快速做到大促A到大促B间资源的快速切换。&lt;/p&gt;

&lt;p&gt;SOFAMosn 流量比例切换的能力是分时调度中非常核心的一部分，有了这份流量转发，Java 内存 Swap 后才可以降低流量以保持各种连接活性，如应用与 DB 间的连接活性等。通过分时调度的技术手段，我们达成了双十一多种大促不加机器的目标，这个目标达成后能节省的成本是极大的，这也是 Service Mesh 化后将能带来的重要业务价值。&lt;/p&gt;

&lt;p&gt;每个公司落地 Service Mesh 的路径不尽相同，这里给出的建议依然是不要为了技术革新本身去做技术革新，多挖掘 Service Mesh 化后能给当前业务带来的实际价值，并以此价值为抓手设定目标，逐步落地。&lt;/p&gt;

&lt;h3 id=&quot;2-如何达成几十万容器接入-sofamosn-的目标&quot;&gt;2. 如何达成几十万容器接入 SOFAMosn 的目标？&lt;/h3&gt;

&lt;p&gt;说到数据面的接入，了解社区方案的同学应该会联想到 Istio 的 Sidecar Injector。Istio 通过在 Kubernetes 中集成 Sidecar Injector 来注入 Envoy。标准的 Kubernetes 更新行为也是 Pod 的重建，创建新 Pod 销毁旧 Pod，更新过程中 IP 会改变等。&lt;/p&gt;

&lt;p&gt;在蚂蚁金服的场景下，或者说在国内较多公司使用 Kubernetes 做内部运维体系升级时，都会走先替换底层资源调度再替换上层 Paas 产品的路子，因为已有的 Paas 是客观存在的，Paas 的能力也非一朝一夕可以直接云原生化的，那么先用 Kubernetes 替换掉底层的资源调度的路子就变的顺理成章了。这条路子上还涉及非 Kubernetes 体系和 Kubernetes 体系的兼容性，如保持 IP 地址不变的 Pod 更新能力，有了这些能力对上层 Paas 来讲，运维体系和运维传统 VM 的场景类似，只是发布部署可以由上传 zip 包解压发布变成镜像化发布，同时在更多高阶场景可以借助 Operator 实现更加面向终态的运维模式。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/1574056558328-84761913-5c31-46df-90e6-3b41b5cffeca.png&quot; alt=&quot;图4. Service Mesh 落地架构&quot; /&gt;&lt;/p&gt;

&lt;p&gt;我们上面介绍 图4. Service Mesh 落地架构 时，有看到 SOFAMosn 和应用 App 编排在同一个 Pod 内，那么一个应用要接入 SOFAMosn 首先要先完成镜像化，可以被 Kubernetes 管理起来，然后是 SOFAMosn 的注入，注入后还需要可原地更新（InPlace Update）。&lt;/p&gt;

&lt;h4 id=&quot;21-替换接入&quot;&gt;2.1 替换接入&lt;/h4&gt;

&lt;p&gt;在我们落地的初期，SOFAMosn 的接入方式主要是替换接入。替换接入就是指定某个应用做 SOFAMosn 接入时，我们会通过创建新 Pod，然后在创建的同时注入 SOFAMosn，新 Pod 创建完成后缩容旧容器。为什么说是缩容旧容器而不是说缩容旧 Pod，是因为接入早期，我们内部的调度系统 Sigma（蚂蚁金服版 Kubernetes）还处于底层逐步替换的过程中，有部分容器还是非 Kubernetes 管理的状态，这部分容器没有 Pod 的概念。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/1574056558322-504de535-ab29-45d2-849f-0edefa3f2abd.png&quot; alt=&quot;图8. 替换接入&quot; /&gt;&lt;/p&gt;

&lt;p&gt;图8. 替换接入&lt;/p&gt;

&lt;p&gt;替换接入最大的问题就是需要充足的资源 Buffer，否则新的 Pod 调度不出来，接入进度便会受阻，而且整个接入周期加上资源申请，以及资源申请出后附带的一系列周边配套系统的数据初始化等，周期较长、依赖较多，所以这个能力是很难在短时间内满足我们几十万容器的接入进度目标的。&lt;/p&gt;

&lt;h4 id=&quot;22-原地接入&quot;&gt;2.2 原地接入&lt;/h4&gt;

&lt;p&gt;基于替换接入的已知问题，我们尝试结合资源调度层的改造，将接入方案做了大幅简化，并提供了原地接入能力。原地接入会首先把不在 Kubernetes 集群中管理的容器原地替换为由 Kubernetes 集群管理的 Pod，然后通过 Pod Upgrade 时直接新增 Sidecar 的方式将 SOFAMosn 注入 Pod，省去了扩容的资源 Buffer 开销，将整个接入过程变的简单顺滑。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/1574056558359-b940f241-6ebd-4062-a767-6f6d0b8e8286.png&quot; alt=&quot;图9. 原地接入&quot; /&gt;&lt;/p&gt;

&lt;p&gt;图9. 原地接入&lt;/p&gt;

&lt;p&gt;原地接入打破了仅在创建 Pod 时注入的原则，带来了更高的复杂度。如原 Pod 拥有 4C8G 的资源，注入 SOFAMosn 后不能新增资源占用，如果新增了资源占用那么这部分资源就不受容量管控系统管理，所以我们将 App Container 和 SOFAMosn Container 的资源做了共享，SOFAMosn 和 APP 公用 4C 的 CPU 额度，抢占比相同。内存方面 SOFAMosn 可用内存 Limit 为 App 的 1/4，对于 8G 内存来讲，SOFAMosn 可见 2G，应用依然可见 8G，当应用使用内存超过 6G 时，由 OOM-Killer 优先 kill SOFAMosn 来保障应用可继续申请到内存资源。&lt;/p&gt;

&lt;p&gt;以上 CPU 抢占比和 Mem limit 比例均为实际压测调整比例，最初我们尝试过 SOFAMosn CPU 占比为应用的 1/4，Mem 为应用的 1/16，这在小流量的应用下可正常工作，但是遇到核心应用，连接数上万的场景下，内存和 CPU 都比较吃紧，特别是 CPU 争抢能力弱于应用的场景下，会导致 RT 变长，间接影响应用。在实际运行的稳定性保障上通过各种参数调整和验证，最后得出 SOFAMosn 与 APP 1:1 共享 CPU，Mem limit 限制为应用 Mem 1/4 的比例。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/1574056558337-10999629-f3a1-4332-aa5d-dac5685a0906.png&quot; alt=&quot;图10. 空中加油&quot; /&gt;&lt;/p&gt;

&lt;p&gt;图10. 空中加油&lt;/p&gt;

&lt;p&gt;通过原地注入的能力，我们实现了更加平滑的接入方式，极大加速了海量容器接入 SOFAMosn 的进程。&lt;/p&gt;

&lt;h3 id=&quot;3-如何处理几十万容器-sofamosn-的版本升级问题&quot;&gt;3. 如何处理几十万容器 SOFAMosn 的版本升级问题？&lt;/h3&gt;

&lt;p&gt;海量容器接入 SOFAMosn 之后，一个更大的挑战是如何快速的升级 SOFAMosn 版本。我们一直强调 Service Mesh 带来的核心价值是业务与基础设施层的解耦，让双方可以更加快捷的向前走，但假如没有快速升级的能力，那么这个快速往前走便成了一句空话，而且任何软件都可能引入 Bug，我们也需要一个快速的机制在 Bug 修复时可以更加快速的升级或回滚。SOFAMosn 的升级能力也从有感升级进阶到无感升级。&lt;/p&gt;

&lt;h4 id=&quot;31-有感升级&quot;&gt;3.1 有感升级&lt;/h4&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/1574056558337-00a17560-8ae0-4acf-9fd3-cdc169b31111.png&quot; alt=&quot;图11. 有感升级&quot; /&gt;&lt;/p&gt;

&lt;p&gt;图11. 有感升级&lt;/p&gt;

&lt;p&gt;有感升级是一次 Pod 的 InPlace Update，这个升级过程中，会关闭此 Pod 的流量，然后做容器 Upgrade，容器 Upgrade 的时候，应用和 SOFAMosn 均会做更新、启动，并在升级完成后打开流量。这个过程的耗时主要取决于应用启动耗时，如一些庞大的应用启动耗时可能达 2~5分钟之久，所以升级周期也会被拉长，并且应用能感知到流量的开关。所以这种方式我们称之为有感升级，这种方式的优点是升级过程中无流量，稳定性更高。&lt;/p&gt;

&lt;h4 id=&quot;32-无感升级&quot;&gt;3.2 无感升级&lt;/h4&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/1574056558351-fa702c0e-126a-43c2-88c2-2a8e65ad8c4e.png&quot; alt=&quot;图12. 无感升级&quot; /&gt;&lt;/p&gt;

&lt;p&gt;图12. 无感升级&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;无感升级我们又称之为平滑升级，整个升级过程中不会暂停流量，SOFAMosn 的版本直接通过热更新技术，动态接管旧版本的流量，并完成升级，整个过程中 APP Container 无感知，所以可以称为无感升级。这种升级方式减少了应用重启的耗时，整个升级时长消耗主要在新旧 SOFAMosn 版本之间的连接迁移，关于无感升级的实现细节，可以参考我 2019 年上半年在 GIAC 上的分享：[《蚂蚁金服 Service Mesh 落地实践与挑战&lt;/td&gt;
      &lt;td&gt;GIAC 实录》](https://mp.weixin.qq.com/s/lo23CB0Ibp2VEkBT_VgPsg)&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h4 id=&quot;33-无人值守&quot;&gt;3.3 无人值守&lt;/h4&gt;

&lt;p&gt;有了快速升级的能力，还需要有在升级过程中的风险拦截，这样才能放心大胆的做版本升级。基于无人值守的理念，我们在 SOFAMosn 的升级前后基于 Metrics 度量指标判断升级前后的流量变化、成功率变化以及业务指标的变化等，实现及时的变更风险识别与阻断，通过这种方式真正做到了放心大胆的快速升级。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/1574056558350-0bb7168a-e244-4932-ac3c-b1b5c75e3904.png&quot; alt=&quot;图13. 无人值守&quot; /&gt;&lt;/p&gt;

&lt;p&gt;图13. 无人值守&lt;/p&gt;

&lt;h3 id=&quot;4-如何保障-service-mesh-的性能与稳定性达标&quot;&gt;4. 如何保障 Service Mesh 的性能与稳定性达标？&lt;/h3&gt;

&lt;p&gt;SOFAMosn 在双十一的表现稳定，峰值千万级 QPS 经过 SOFAMosn，SOFAMosn 内部处理消耗平均 RT 低于 0.2ms。我们在性能和稳定性上经过多重优化改进才最终能达成以上成果，这其中离不开生产的持续压测、打磨，以下是我们在性能和稳定性方面的一些改进点，仅供参考：&lt;/p&gt;

&lt;h4 id=&quot;41-性能优化&quot;&gt;4.1 性能优化&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;CPU 优化&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Golang writev 优化：多个包拼装一次写，降低 syscall 调用。我们在 go 1.9 的时候发现 writev 有内存泄露的bug，内部使用的目前是 patch 了 writev bugfix 的 go 1.12。writev bugfix 已经集成在 go 1.13 中。&lt;/p&gt;

&lt;p&gt;详情见我们当时给go 提交的PR： &lt;a href=&quot;https://github.com/golang/go/pull/32138&quot;&gt;https://github.com/golang/go/pull/32138&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;内存优化&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;内存复用：报文直接解析可能会产生大量临时对象，SOFAMosn 通过直接复用报文字节的方式，将必要的信息直接通过 unsafe.Pointer 指向报文的指定位置来避免临时对象的产生。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;延迟优化&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;协议升级：快速读取 header：TR 协议请求头和 Body 均为 hessian 序列化，性能损耗较大。而 Bolt 协议中 Header 是一个扁平化map，解析性能损耗小。升级应用走 Bolt 协议来提升性能。&lt;/p&gt;

&lt;p&gt;路由缓存：内部路由的复杂性（一笔请求经常需要走多种路由策略最终确定路由结果目标），通过对相同条件的路由结果做秒级缓存，我们成功将某核心链路的全链路 RT 降低 7%。&lt;/p&gt;

&lt;h4 id=&quot;42-稳定性建设&quot;&gt;4.2 稳定性建设&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;Pod 级别 CPU Mem 限额配置，Sidecar 与 APP 共享 CPU Mem；&lt;/li&gt;
  &lt;li&gt;运维周边建设：
    &lt;ul&gt;
      &lt;li&gt;原地注入；&lt;/li&gt;
      &lt;li&gt;平滑升级；&lt;/li&gt;
      &lt;li&gt;Sidecar 重启；&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;监控建设：
    &lt;ul&gt;
      &lt;li&gt;系统指标：CPU、Mem、TCP、Disk IO；&lt;/li&gt;
      &lt;li&gt;Go 指标：Processor、Goroutines、Memstats、GC；&lt;/li&gt;
      &lt;li&gt;RPC 指标：QPS、RT、连接数；&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;旁路增强：
    &lt;ul&gt;
      &lt;li&gt;服务注册中心性能提升；&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;回顾&quot;&gt;回顾&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;如何让 Service Mesh 发挥最大的业务价值？&lt;strong&gt;保证效率增加成本不变&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;如何达成几十万容器接入 SOFAMosn 的目标？&lt;strong&gt;降低接入成本&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;如何处理几十万容器 SOFAMosn 的版本升级问题？&lt;strong&gt;降低应用感知&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;如何保障 Service Mesh 的性能与稳定性达标？&lt;strong&gt;性能与稳定性层层优化&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;通过对以上问题的深入解读，大家可以了解到蚂蚁金服的 Service Mesh 为何可以稳定支撑双十一，也期望能为大家落地 Service Mesh 带来一些不一样的思考。更多 Service Mesh 相关内容敬请关注我们的公众号“金融级分布式架构”来了解更多。&lt;/p&gt;</content><author><name>JervyShi</name></author><category term="service-mesh" /><category term="service-mesh" /><category term="golang" /><summary type="html">2019 年的双十一是蚂蚁金服的重要时刻，大规模落地了 Service Mesh 并顺利保障双十一平稳渡过。我们第一时间与这次的落地负责人进行了交流。 采访的开头： 花肉：“这次大规模上了 Service Mesh ，双十一值班感觉是什么？” 卓与：“Service Mesh 真的稳。” 图为卓与 TOP100 北京峰会分享现场图 落地负责人介绍 Service Mesh 是蚂蚁金服下一代架构的核心，今年蚂蚁金服大规模的 Service Mesh 落地，我有幸带领并面对了这个挑战，并非常平稳的通过了双十一的大考。 我个人主要专注在微服务领域，在服务注册与服务框架方向深耕多年，主导过第五代服务注册中心（SOFARegistry）设计与实施，在微服务的架构演进中持续探索新方向，并在蚂蚁金服第五代架构演进中负责内部 Service Mesh 方向的架构设计与落地。 SOFAStack：https://github.com/sofastack SOFAMosn：https://github.com/sofastack/sofa-mosn Service Mesh 在蚂蚁金服 蚂蚁金服很早开始关注 Service Mesh，并在 2018 年发起 ServiceMesher 社区，目前已有 4000+ 开发者在社区活跃。在技术应用层面，Service Mesh 的场景已经渡过探索期，今年已经全面进入深水区探索。 2019 年的双十一是我们的重要时刻，我们进行了大规模的落地，可能是目前业界最大规模的实践。作为技术人能面对世界级的流量挑战，是非常紧张和兴奋的。当 Service Mesh 遇到双十一又会迸发出怎样的火花？蚂蚁金服的 LDC 架构继续演进的过程中，Service Mesh 要承载起哪方面的责任？我们借助四个“双十一考题”一一为大家揭晓。 Service Mesh 背景知识 Service Mesh 这个概念社区已经火了很久，相关的背景知识从我们的公众号内可以找到非常多的文章，我在这里不做过于冗余的介绍，仅把几个核心概念统一，便于后续理解。 图1. Service Mesh 开源架构来自 https://istio.io/ Istio 的架构图上清晰的描述了 Service Mesh 最核心的两个概念：数据面与控制面。数据面负责做网络代理，在服务请求的链路上做一层拦截与转发，可以在链路中做服务路由、链路加密、服务鉴权等，控制面负责做服务发现、服务路由管理、请求度量（放在控制面颇受争议）等。 Service Mesh 带来的好处不再赘述，我们来看下蚂蚁金服的数据面和控制面产品，如下图： 图2. 蚂蚁金服 Service Mesh 示意架构 数据面：SOFAMosn。蚂蚁金服使用 Golang 研发的高性能网络代理，作为 Service Mesh 的数据面，承载了蚂蚁金服双十一海量的核心应用流量。 控制面：SOFAMesh。Istio 改造版，落地过程中精简为 Pilot 和 Citadel，Mixer 直接集成在数据面中避免多一跳的开销。 2019 Service Mesh 双十一大考揭秘 双十一 SOFAMosn 与 SOFAMesh 经历海量规模大考，顺利保障双十一平稳渡过。今年双十一蚂蚁金服的百十多个核心应用全面接入 SOFAMosn，生产 Mesh 化容器几十万台，双十一峰值 SOFAMosn 承载数据规模数千万 QPS，SOFAMosn 转发平均处理耗时 0.2ms。 图3. 双十一落地数据 在如此大规模的接入场景下，我们面对的是极端复杂的场景，同时需要多方全力合作，更要保障数据面的性能稳定性满足大促诉求，整个过程极具挑战。下面我们将从几个方面来分享下我们在这个历程中遇到的问题及解决方案。 双十一考题 如何让 Service Mesh 发挥最大的业务价值？ 如何达成几十万容器接入 SOFAMosn 的目标？ 如何处理几十万容器 SOFAMosn 的版本升级问题？ 如何保障 Service Mesh 的性能与稳定性达标？ 落地架构 为了更加方便的理解以上问题的解决与后续介绍中可能涉及的术语等，我们先来看下 Service Mesh 落地的主要架构： 图4. Service Mesh 落地架构 以上架构图中主要分几部分： 数据面：借助 Kubernetes 中的 Pod 模型，SOFAMosn 以独立镜像和 App 镜像共同编排在同一个 Pod 内，共享相同的 Network Namespace、CPU、Memory，接入 SOFAMosn 后所有的 App RPC 流量、消息流量均不在直接对外，而是直接和 SOFAMosn 交互，由 SOFAMosn 直接对接服务注册中心做服务发现，对接 Pilot 做配置下发，对接 MQ Server 做消息收发等； 控制面：由 Pilot、Citadel 和服务注册中心等组件组成，负责服务地址下发、服务路由下发、证书下发等； 底层支撑：Sidecar 的接入与升级等均依赖 Kubernetes 能力，通过 webhook 做 Sidecar 的注入，通过 Operator 做 Sidecar 的版本升级等，相关运维动作均离不开底层的支撑； 产品层：结合底层提供的原子能力做运维能力封装，监控对接，采集 Sidecar 暴露的 Metrics 数据做监控与预警，流量调控，安全等产品化能力； 蚂蚁金服的答卷 1. 如何让 Service Mesh 发挥最大的业务价值？ 作为一个技术人，我们非常坚持不要为了技术革新本身去做技术革新，一定要让技术帮助业务，用技术驱动业务。这几年随着大家消费习惯以及网络行为的改变，双十一面对的业务场景远比想象中复杂。举个例子大家感受下，大家有没有发现你的女友或者老婆每天对着李佳琦的淘宝直播购物，主播们不断的、实时的红包、上新等等，带来了远比秒杀更复杂的业务场景和体量。大促的模式也更加丰富，不同场景下的大促涉及的应用是不同的，每一类应用在应对独特的洪峰时都需要有足够的资源。 假如运营同学在不同时间点设计了两种活动，两种活动分别会对应两类不同的应用，如果这两类应用都在大促前准备充足的资源自然是轻松渡过大促峰值，但大促洪峰时间短暂，大量的资源投入有很长一段时间都处于空闲状态，这自然不符合技术人的追求。 那么如何在不增加资源的场景下渡过各种大促呢？ 核心问题就是如何在足够短的时间内做到大规模资源腾挪，让一批机器资源可以在不同时间点承载起不同的大促洪峰。 面对这样的挑战，我们会有怎样的解法呢？ Service Mesh 618 大促落地试点时，我们有介绍到为什么要做这个事情，核心价值是业务与基础设施解耦，双方可以并行发展，快速往前走。那么并行发展究竟能为业务带来哪些实际的价值？除了降低基础组件的升级难度之外，我们还在资源调度方向做了以下探索： 1.1 腾挪调度 说到资源调度，最简单的自然是直接做资源腾挪，比如大促A峰值过后，大促A对应的应用通过缩容把资源释放出来，大促B对应的应用再去申请资源做扩容，这种方式非常简单，难点在于当资源规模非常庞大时，缩容扩容的效率极低，应用需要把资源申请出来并启动应用，耗时很长，假如多个大促之间的时间间隔很短，腾挪需要的耗时极有可能超过大促时间间隔，这种调度方案已不能满足双十一多种大促的诉求。 图5. 腾挪调度 1.2 分时调度 腾挪调度最大的问题是应用需要冷启动，冷启动本身的耗时，加上冷启动后预热需要的耗时，对整个腾挪时间影响极大。假如应用不需要启动就能完成资源腾挪，整个调度速度将会加快很多。基于应用不需要重新启动即可完成资源腾挪的思路，我们提出了分时调度的方案：分时调度会通过超卖的机制申请出足够的容器。 图6. 分时调度 我们把资源池中的应用容器分为两种状态（4C8G 规格为例）： 运行态：运行态的应用处于全速运行的状态（资源可使用到 4C8G），它们可以使用充足的资源全速运行，承载 100% 的流量； 保活态：保活态的应用处于低速运行的状态（资源可使用到 1C2G），它们仅可使用受限的资源低速运行，承载 1% 的流量，剩余 99% 的流量由 SOFAMosn 转发给运行态节点； 图7. 保活态流量转发 保活态和运行态可以快速切换，切换时仅需要做 JVM 内存 Swap 以及基于 SOFAMosn 的流量比例切换，即可快速做到大促A到大促B间资源的快速切换。 SOFAMosn 流量比例切换的能力是分时调度中非常核心的一部分，有了这份流量转发，Java 内存 Swap 后才可以降低流量以保持各种连接活性，如应用与 DB 间的连接活性等。通过分时调度的技术手段，我们达成了双十一多种大促不加机器的目标，这个目标达成后能节省的成本是极大的，这也是 Service Mesh 化后将能带来的重要业务价值。 每个公司落地 Service Mesh 的路径不尽相同，这里给出的建议依然是不要为了技术革新本身去做技术革新，多挖掘 Service Mesh 化后能给当前业务带来的实际价值，并以此价值为抓手设定目标，逐步落地。 2. 如何达成几十万容器接入 SOFAMosn 的目标？ 说到数据面的接入，了解社区方案的同学应该会联想到 Istio 的 Sidecar Injector。Istio 通过在 Kubernetes 中集成 Sidecar Injector 来注入 Envoy。标准的 Kubernetes 更新行为也是 Pod 的重建，创建新 Pod 销毁旧 Pod，更新过程中 IP 会改变等。 在蚂蚁金服的场景下，或者说在国内较多公司使用 Kubernetes 做内部运维体系升级时，都会走先替换底层资源调度再替换上层 Paas 产品的路子，因为已有的 Paas 是客观存在的，Paas 的能力也非一朝一夕可以直接云原生化的，那么先用 Kubernetes 替换掉底层的资源调度的路子就变的顺理成章了。这条路子上还涉及非 Kubernetes 体系和 Kubernetes 体系的兼容性，如保持 IP 地址不变的 Pod 更新能力，有了这些能力对上层 Paas 来讲，运维体系和运维传统 VM 的场景类似，只是发布部署可以由上传 zip 包解压发布变成镜像化发布，同时在更多高阶场景可以借助 Operator 实现更加面向终态的运维模式。 我们上面介绍 图4. Service Mesh 落地架构 时，有看到 SOFAMosn 和应用 App 编排在同一个 Pod 内，那么一个应用要接入 SOFAMosn 首先要先完成镜像化，可以被 Kubernetes 管理起来，然后是 SOFAMosn 的注入，注入后还需要可原地更新（InPlace Update）。 2.1 替换接入 在我们落地的初期，SOFAMosn 的接入方式主要是替换接入。替换接入就是指定某个应用做 SOFAMosn 接入时，我们会通过创建新 Pod，然后在创建的同时注入 SOFAMosn，新 Pod 创建完成后缩容旧容器。为什么说是缩容旧容器而不是说缩容旧 Pod，是因为接入早期，我们内部的调度系统 Sigma（蚂蚁金服版 Kubernetes）还处于底层逐步替换的过程中，有部分容器还是非 Kubernetes 管理的状态，这部分容器没有 Pod 的概念。 图8. 替换接入 替换接入最大的问题就是需要充足的资源 Buffer，否则新的 Pod 调度不出来，接入进度便会受阻，而且整个接入周期加上资源申请，以及资源申请出后附带的一系列周边配套系统的数据初始化等，周期较长、依赖较多，所以这个能力是很难在短时间内满足我们几十万容器的接入进度目标的。 2.2 原地接入 基于替换接入的已知问题，我们尝试结合资源调度层的改造，将接入方案做了大幅简化，并提供了原地接入能力。原地接入会首先把不在 Kubernetes 集群中管理的容器原地替换为由 Kubernetes 集群管理的 Pod，然后通过 Pod Upgrade 时直接新增 Sidecar 的方式将 SOFAMosn 注入 Pod，省去了扩容的资源 Buffer 开销，将整个接入过程变的简单顺滑。 图9. 原地接入 原地接入打破了仅在创建 Pod 时注入的原则，带来了更高的复杂度。如原 Pod 拥有 4C8G 的资源，注入 SOFAMosn 后不能新增资源占用，如果新增了资源占用那么这部分资源就不受容量管控系统管理，所以我们将 App Container 和 SOFAMosn Container 的资源做了共享，SOFAMosn 和 APP 公用 4C 的 CPU 额度，抢占比相同。内存方面 SOFAMosn 可用内存 Limit 为 App 的 1/4，对于 8G 内存来讲，SOFAMosn 可见 2G，应用依然可见 8G，当应用使用内存超过 6G 时，由 OOM-Killer 优先 kill SOFAMosn 来保障应用可继续申请到内存资源。 以上 CPU 抢占比和 Mem limit 比例均为实际压测调整比例，最初我们尝试过 SOFAMosn CPU 占比为应用的 1/4，Mem 为应用的 1/16，这在小流量的应用下可正常工作，但是遇到核心应用，连接数上万的场景下，内存和 CPU 都比较吃紧，特别是 CPU 争抢能力弱于应用的场景下，会导致 RT 变长，间接影响应用。在实际运行的稳定性保障上通过各种参数调整和验证，最后得出 SOFAMosn 与 APP 1:1 共享 CPU，Mem limit 限制为应用 Mem 1/4 的比例。 图10. 空中加油 通过原地注入的能力，我们实现了更加平滑的接入方式，极大加速了海量容器接入 SOFAMosn 的进程。 3. 如何处理几十万容器 SOFAMosn 的版本升级问题？ 海量容器接入 SOFAMosn 之后，一个更大的挑战是如何快速的升级 SOFAMosn 版本。我们一直强调 Service Mesh 带来的核心价值是业务与基础设施层的解耦，让双方可以更加快捷的向前走，但假如没有快速升级的能力，那么这个快速往前走便成了一句空话，而且任何软件都可能引入 Bug，我们也需要一个快速的机制在 Bug 修复时可以更加快速的升级或回滚。SOFAMosn 的升级能力也从有感升级进阶到无感升级。 3.1 有感升级 图11. 有感升级 有感升级是一次 Pod 的 InPlace Update，这个升级过程中，会关闭此 Pod 的流量，然后做容器 Upgrade，容器 Upgrade 的时候，应用和 SOFAMosn 均会做更新、启动，并在升级完成后打开流量。这个过程的耗时主要取决于应用启动耗时，如一些庞大的应用启动耗时可能达 2~5分钟之久，所以升级周期也会被拉长，并且应用能感知到流量的开关。所以这种方式我们称之为有感升级，这种方式的优点是升级过程中无流量，稳定性更高。 3.2 无感升级 图12. 无感升级 无感升级我们又称之为平滑升级，整个升级过程中不会暂停流量，SOFAMosn 的版本直接通过热更新技术，动态接管旧版本的流量，并完成升级，整个过程中 APP Container 无感知，所以可以称为无感升级。这种升级方式减少了应用重启的耗时，整个升级时长消耗主要在新旧 SOFAMosn 版本之间的连接迁移，关于无感升级的实现细节，可以参考我 2019 年上半年在 GIAC 上的分享：[《蚂蚁金服 Service Mesh 落地实践与挑战 GIAC 实录》](https://mp.weixin.qq.com/s/lo23CB0Ibp2VEkBT_VgPsg) 3.3 无人值守 有了快速升级的能力，还需要有在升级过程中的风险拦截，这样才能放心大胆的做版本升级。基于无人值守的理念，我们在 SOFAMosn 的升级前后基于 Metrics 度量指标判断升级前后的流量变化、成功率变化以及业务指标的变化等，实现及时的变更风险识别与阻断，通过这种方式真正做到了放心大胆的快速升级。 图13. 无人值守 4. 如何保障 Service Mesh 的性能与稳定性达标？ SOFAMosn 在双十一的表现稳定，峰值千万级 QPS 经过 SOFAMosn，SOFAMosn 内部处理消耗平均 RT 低于 0.2ms。我们在性能和稳定性上经过多重优化改进才最终能达成以上成果，这其中离不开生产的持续压测、打磨，以下是我们在性能和稳定性方面的一些改进点，仅供参考： 4.1 性能优化 CPU 优化 Golang writev 优化：多个包拼装一次写，降低 syscall 调用。我们在 go 1.9 的时候发现 writev 有内存泄露的bug，内部使用的目前是 patch 了 writev bugfix 的 go 1.12。writev bugfix 已经集成在 go 1.13 中。 详情见我们当时给go 提交的PR： https://github.com/golang/go/pull/32138 内存优化 内存复用：报文直接解析可能会产生大量临时对象，SOFAMosn 通过直接复用报文字节的方式，将必要的信息直接通过 unsafe.Pointer 指向报文的指定位置来避免临时对象的产生。 延迟优化 协议升级：快速读取 header：TR 协议请求头和 Body 均为 hessian 序列化，性能损耗较大。而 Bolt 协议中 Header 是一个扁平化map，解析性能损耗小。升级应用走 Bolt 协议来提升性能。 路由缓存：内部路由的复杂性（一笔请求经常需要走多种路由策略最终确定路由结果目标），通过对相同条件的路由结果做秒级缓存，我们成功将某核心链路的全链路 RT 降低 7%。 4.2 稳定性建设 Pod 级别 CPU Mem 限额配置，Sidecar 与 APP 共享 CPU Mem； 运维周边建设： 原地注入； 平滑升级； Sidecar 重启； 监控建设： 系统指标：CPU、Mem、TCP、Disk IO； Go 指标：Processor、Goroutines、Memstats、GC； RPC 指标：QPS、RT、连接数； 旁路增强： 服务注册中心性能提升； 回顾 如何让 Service Mesh 发挥最大的业务价值？保证效率增加成本不变 如何达成几十万容器接入 SOFAMosn 的目标？降低接入成本 如何处理几十万容器 SOFAMosn 的版本升级问题？降低应用感知 如何保障 Service Mesh 的性能与稳定性达标？性能与稳定性层层优化 通过对以上问题的深入解读，大家可以了解到蚂蚁金服的 Service Mesh 为何可以稳定支撑双十一，也期望能为大家落地 Service Mesh 带来一些不一样的思考。更多 Service Mesh 相关内容敬请关注我们的公众号“金融级分布式架构”来了解更多。</summary></entry><entry><title type="html">蚂蚁金服 Service Mesh 落地实践与挑战</title><link href="https://jervyshi.me/service-mesh-landing-practice-and-challenges-in-antfin/" rel="alternate" type="text/html" title="蚂蚁金服 Service Mesh 落地实践与挑战" /><published>2019-06-24T00:00:00+00:00</published><updated>2019-06-24T00:00:00+00:00</updated><id>https://jervyshi.me/service-mesh-landing-practice-and-challenges-in-antfin</id><content type="html" xml:base="https://jervyshi.me/service-mesh-landing-practice-and-challenges-in-antfin/">&lt;p&gt;本文整理自 GIAC（GLOBAL INTERNET ARCHITECTURE CONFERENCE）全球互联网架构大会，&lt;a href=&quot;http://giac-history.msup.com.cn/2019/schedule/course?id=13816&quot;&gt;蚂蚁金服 Service Mesh 落地实践与挑战&lt;/a&gt;分享。分享基于 Service Mesh 的理念，结合蚂蚁金服内部实际场景，将中间件、数据层、安全层等能力从应用中剥离出来后下沉至独立的 Sidecar SOFAMosn 中，结合 Kubernetes 运维体系，提供应用无感知的情况下升级基础设施层能力的案例。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/640.webp&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;本次分享将从以如下次序展开进行：&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/1.png&quot; alt=&quot;图1. 分享大纲&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;蚂蚁金服当前的服务化现状&quot;&gt;蚂蚁金服当前的服务化现状&lt;/h2&gt;
&lt;p&gt;在看蚂蚁金服的服务化架构之前我们先从一个简单的服务化调用示例说起，下图是 SOFARPC 基本原理：&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/2.png&quot; alt=&quot;图2. SOFARPC 基本原理&quot; /&gt;&lt;/p&gt;

&lt;p&gt;我们从上图可以看出，构建一个服务化框架需要有服务注册中心，有服务定义，调用方和服务提供方使用相同的服务定义来互相通讯。通过服务注册中心，调用方可以直接订阅到服务提供方的地址，采用点对点的方式直接发起请求。客户端内可实现服务发现、路由寻址、负载均衡、限流熔断等能力来增强服务通讯能力。通过我们开源的 SOFARPC、SOFARegistry、SOFABoot，用户已经可以直接构建起微服务体系，助力业务发展。&lt;/p&gt;

&lt;p&gt;蚂蚁金服发展至今，双 11 系统需要应对的交易洪峰逐年递增：&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/3.png&quot; alt=&quot;图3. 历年双 11 交易额与峰值数据&quot; /&gt;&lt;/p&gt;

&lt;p&gt;每秒 26.5 万笔交易是 2017 年双 11 的峰值数据，这个数据背后有非常复杂的架构支持，LDC 单元化架构是蚂蚁金服沉淀多年的核心架构，依靠这个架构实现每年峰值交易量飞速增长下系统依然能平滑渡过。我们来简要看下 LDC 架构：&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/4.png&quot; alt=&quot;图4. LDC 架构示例&quot; /&gt;&lt;/p&gt;

&lt;p&gt;上图摘自 金融级分布式架构 中的 素描单元化 一文，这里不详细展开。LDC 的单元化架构给应用的服务化带来更多的规范与抽象，服务路由中需要考虑单元间的调用，跨机房调用等更多场景。这里主要希望表达的是 LDC 架构给 RPC 调用带来更高的复杂度。&lt;/p&gt;

&lt;h2 id=&quot;服务化痛点&quot;&gt;服务化痛点&lt;/h2&gt;

&lt;h3 id=&quot;中间件版本升级&quot;&gt;中间件版本升级&lt;/h3&gt;

&lt;p&gt;在上面介绍背景时，有介绍到目前 LDC 架构下服务调用的复杂度，这些复杂度目前是直接体现在应用的代码中。对于业务同学来讲，一个应用的关注重点是如何实现业务逻辑，至于高可用、容灾等能力更多是整体架构层面会考虑的点。应用内通过引入 RPC 的 jar 包即可获得 LDC 架构下服务调用各种能力的支撑，带来便利的同时也可以看到这种模式的缺点：&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/5.png&quot; alt=&quot;图5. APP 业务与 SDK 组成部分&quot; /&gt;&lt;/p&gt;

&lt;p&gt;应用内除业务逻辑之外，由中间件的 SDK 引入大量外部依赖，来完成服务发现、路由寻址、负载均衡、限流熔断、序列化、通讯等能力，每个组件的引入都可能带来稳定性风险，以及更高的升级成本。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/6.png&quot; alt=&quot;图6. SDK 内不同能力对应的依赖&quot; /&gt;&lt;/p&gt;

&lt;p&gt;根据目前 SOFARPC 在内部的版本举例，服务发现依赖 SOFARegistry 的客户端做 IDC 内的服务发现，依赖 Antvip 做跨 IDC 的服务发现，ZoneClient 集成 LDC 架构的单元化信息，路由寻址需要根据请求的入参计算目前 Zone 然后确定调用目标，限流熔断依赖 Guardian 组件，通讯协议与序列化协议相对稳定，变更较少。仅为了完成服务调用，应用需要额外引入 7+ 客户端包。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/7.png&quot; alt=&quot;图7. SDK 升级数量&quot; /&gt;&lt;/p&gt;

&lt;p&gt;每年双 11 需要涉及到架构调整时：比如支持弹性架构，需要做很多中间件客户端的版本升级来支撑更优的架构，对于业务同学来讲，这些升级是很耗费精力的，拿 200 个核心应用举例，每个应用升级中间件版本经过研发、测试、再到部署预发、灰度、生产等环境需要 5个人日的话，200 个核心应用中间件升级需要耗费 1000 人日，如果这部分时间可以节省出来，每年架构升级可以节约大量人力资源。&lt;/p&gt;

&lt;h2 id=&quot;跨语言通讯&quot;&gt;跨语言通讯&lt;/h2&gt;

&lt;p&gt;蚂蚁金服发展至今，内部业务百花齐放，搜索推荐、人工智能、安全等各种业务使用到的技术栈非常多样化，跨语言的服务通讯能力也十分重要。早在几年前，Java 之外规模最大的就是 NodeJS 应用，为了让 Java 和 NodeJS 应用之间可以复用蚂蚁金服内部的各种中间件和基础设施，前端团队使用 NodeJS 逐步重写了各种中间件客户端，让整个 NodeJS 和 Java 体系可以完美互通。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/8.png&quot; alt=&quot;图8. Java 与 NodeJS 互调&quot; /&gt;&lt;/p&gt;

&lt;p&gt;中间件 SDK 跨语言重写与维护成本极高，随着语言种类的增多，跨语言通讯的诉求也越来越多。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/9.png&quot; alt=&quot;图9. 多语言场景&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Java, NodeJS, Go, Python, C++ 等，5+ 语言，中间件 SDK 全部重写成本极高。这些问题不得不激励我们寻找更优的解法。&lt;/p&gt;

&lt;h2 id=&quot;解决痛点&quot;&gt;解决痛点&lt;/h2&gt;

&lt;h3 id=&quot;sdk-能力下沉&quot;&gt;SDK 能力下沉&lt;/h3&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/10.png&quot; alt=&quot;图10. SDK 瘦身并下沉能力至 Sidecar&quot; /&gt;&lt;/p&gt;

&lt;p&gt;依然以上述 RPC SDK 举例，SDK 中的能力我们可以根据稳定性与不可剥离等特性来看，哪些是可以从应用中抽出来的，尽量把 SDK 做薄，做的足够稳定无需变更，那么升级成本将不复存在。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/11.png&quot; alt=&quot;图11. SDK 与 Sidecar 对应的依赖&quot; /&gt;&lt;/p&gt;

&lt;p&gt;RPC SDK 中的服务发现、路由寻址、限流熔断等特性，是更易于变更的，我们将这部分能力下沉至独立的 Sidecar 中，可以复用这部分能力，让多语言的 SDK 只实现最基本的序列化与通讯协议，而这些能力是很轻量且易于实现的。这里的 Sidecar 我们是希望它作为独立进程存在，和业务应用的进程剥离，并和业务应用的升级解耦开来，实现业务和基础设施并行发展，互不干扰的愿景。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/12.png&quot; alt=&quot;图12. RPC 消息与数据源能力下沉&quot; /&gt;&lt;/p&gt;

&lt;p&gt;除了 RPC 通讯，我们还可以下沉消息、数据源等能力至 Sidecar 中，业务应用可以越来越薄，SDK 实现成本也降低到可接受的程度，基础设施层与业务剥离，双方均可独立演进。&lt;/p&gt;

&lt;h2 id=&quot;落地架构&quot;&gt;落地架构&lt;/h2&gt;

&lt;h3 id=&quot;整体架构&quot;&gt;整体架构&lt;/h3&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/13.png&quot; alt=&quot;图13. Mesh 落地架构&quot; /&gt;&lt;/p&gt;

&lt;p&gt;不同于开源的 Istio 体系，蚂蚁金服内部版 Service Mesh 落地优先考虑数据面的实现与落地，控制面在逐步建设中，整体的架构上看，我们使用数据面直接和内部的各种中间件服务端对接，来完成 RPC、消息等能力的下沉，给业务应用减负。由上图可以看出，我们将不同的 Sidecar 与业务应用编排在同一个 Pod 中，App 与 SOFAMosn 直接通讯，SOFAMosn 来负责目标接口的服务发现、路由寻址，并且由 SOFAMosn 内置的安全模块来做应用间调用的加密鉴权。通过 DBMesh 的 Sidecar 来实现数据层的下沉，App 不在需要与多个数据源建立连接，只需要连接本 Pod 内的 DBMesh 即可完成数据层调用，数据库的用户名、密码、分库分表规则等均不再需要关心。&lt;/p&gt;

&lt;p&gt;图中名词解析：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;ConfigServer：配置中心，负责各种元数据配置、动态开关等&lt;/li&gt;
  &lt;li&gt;Registry：服务注册中心，负责 IDC 内服务发现&lt;/li&gt;
  &lt;li&gt;AntVip：类 DNS 解析的产品，可通过域名解析一组目标地址，用于跨 IDC 服务发现&lt;/li&gt;
  &lt;li&gt;MQ：消息中心服务端，用于收发消息&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;落地数据&quot;&gt;落地数据&lt;/h3&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/14.png&quot; alt=&quot;图14. 落地 CPU 数据&quot; /&gt;&lt;/p&gt;

&lt;p&gt;目前这套架构已经在支付核心链路中做试点，618 大促 Mesh 化应用对比无 Mesh 化应用 CPU 损耗增长 1.7%，单笔交易整体耗时增长 5ms。CPU 增长是由于多出一个进程，请求增加一条之后，RT 会有稳定的小幅增长，但这些成本相比于整体架构带来的红利，微乎其微，并且针对整个数据面的持续优化是有望逐步减少资源占用，提升资源利用率。&lt;/p&gt;

&lt;h3 id=&quot;降低打扰度&quot;&gt;降低打扰度&lt;/h3&gt;
&lt;p&gt;中间件能力下沉在架构上看是可行的，实际落地如何做到无打扰的在奔跑的火车上换轮子，低打扰是一个非常重要的考量点。借助于 Kubernetes 的优秀实践，将业务容器与 Sidecar 容器编排在同一个 Pod 中是比较合理的架构，Sidecar 与业务容器互不干扰，互相升级均可做到双方无感。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/15.png&quot; alt=&quot;图15. 落地方式&quot; /&gt;&lt;/p&gt;

&lt;p&gt;我们为了让业务应用升级尽可能如丝般顺滑，主要做了如下优化方案：&lt;/p&gt;

&lt;h4 id=&quot;1-无感镜像化&quot;&gt;1. 无感镜像化&lt;/h4&gt;

&lt;p&gt;蚂蚁金服内部还有部分应用未完成镜像化，或者说以富容器的方式来使用镜像化，这种方式也是在逐步淘汰的过程中，为了让业务更顺滑的镜像化，PAAS 平台联动整个研发体系，将应用的打包过程通过自动生成 Dockerfile 的方式主动帮用户完成镜像化。做到用户无感知镜像化改造。&lt;/p&gt;

&lt;h4 id=&quot;2-低感-mesh-化&quot;&gt;2. 低感 Mesh 化&lt;/h4&gt;

&lt;p&gt;镜像化完成之后，想要借助 Pod 模型将应用的容器和 SOFAMosn 的容器部署在一起，我们需要将底层资源管理与调度全部替换到 Kubernetes 体系。然后在 PAAS 上给 Mesh 化的应用增加标识，通过 Kubernetes 识别这些标识并主动注入 SOFAMosn sidecar 来完成应用的 Mesh 化接入。&lt;/p&gt;

&lt;h4 id=&quot;3-无感-sidecar-升级&quot;&gt;3. 无感 Sidecar 升级&lt;/h4&gt;

&lt;p&gt;Sidecar 与业务进程独立后，还有一个核心的诉求就是希望 Sidecar 可以独立升级，为了让 Sidecar 的升级尽量对生产做到无打扰，我们实现了 SOFAMosn 平滑升级的 Operator，通过对运行中 SOFAMosn 的连接迁移，实现整个升级过程应用完全无感知。当然这里面包含着很多挑战，后面我们会详细介绍。&lt;/p&gt;

&lt;h2 id=&quot;落地挑战&quot;&gt;落地挑战&lt;/h2&gt;

&lt;h3 id=&quot;sidecar-平滑升级&quot;&gt;Sidecar 平滑升级&lt;/h3&gt;

&lt;p&gt;目前我们已经实现 SOFAMosn 的平滑升级能力，SOFAMosn 的主要能力是 RPC 和 消息的通讯代理，平滑升级的目的是业务 App 进程不重启，业务请求不中断，完成 SOFAMosn 的版本升级。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/16.png&quot; alt=&quot;图16. SOFAMosn 平滑升级&quot; /&gt;&lt;/p&gt;

&lt;p&gt;由于 SOFAMosn 与应用是独立的 container，如上图描述，SOFAMosn 的升级是需要做到 Pod 内镜像的热替换，这种热替换能力必须要保障几点：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Pod 不会被重建，应用进程始终正常运行&lt;/li&gt;
  &lt;li&gt;镜像的替换不会影响运行中的流量&lt;/li&gt;
  &lt;li&gt;镜像替换后整个 Pod 描述需要进行更新&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;为了达成以上目标，我们通过对 Kubernetes 的改造以及自定义 Operator 来完成以上升级的处理。处理流程如下：&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/17.png&quot; alt=&quot;图17. SOFAMosn 平滑升级流程&quot; /&gt;&lt;/p&gt;

&lt;p&gt;在不考虑多镜像间做平滑升级的场景下，通过 Fork 进程，可以继承父进程的 FD 来完成长连接的迁移，实现无损热升级。SOFAMosn 以镜像化的方式运行后，平滑升级的难度极大增加。整个平滑升级的难点在于如何让不同容器内的 SOFAMosn 进程可互相感知并可完成连接迁移。&lt;/p&gt;

&lt;p&gt;下面我们来看下 SOFAMosn 升级过程中，如何保障流量无损：&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/18.png&quot; alt=&quot;图18. 正常流量走向&quot; /&gt;&lt;/p&gt;

&lt;p&gt;SOFAMosn 处理的正常流量分为入口流量和出口流量，Client 可以看成和 SOFAMosn 部署在同 Pod 内的 App，Server 可以是请求调用的目标服务提供方，可以是一个 App 也可以是被调用 App 侧的 SOFAMosn。当一笔请求从 Client 发至 Server 时，中间会经过两条长连接：TCP1 和 TCP2，SOFAMosn 会记录这笔请求对应的 ConnectionID，来完成请求的发起与响应。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/19.png&quot; alt=&quot;图19. 正向流量迁移&quot; /&gt;&lt;/p&gt;

&lt;p&gt;当新的 Mosn 容器被启动时，Mosn 会根据本地的 Domain Socket 来尝试发送请求，当另一个 Mosn 进程存在时，Mosn V1 和 Mosn V2 进入热升级模式，Mosn V1 会将已存在连接的 FD 和已读出的数据包 通过 Domain Socket 发送至 Mosn V2 同时 V1 将不会再从已迁移的 FD 中读取数据，FD 迁移完成所有流量将会直接由 Mosn V2 来处理。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/20.png&quot; alt=&quot;图20. 逆向流量迁移&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Mosn V1 和 Mosn V2 进入热升级模式之后，可能会存在 Mosn V1 已经将请求发给 Server 后 Server 还没有来得及响应的情况，这种场景 Mosn V1 在迁移 FD 给 Mosn V2 时，Mosn V2 会在 FD 接管到之后的 ConnectionID 返回给 Mosn V1，当 Mosn V1 收到 Server 返回的 Response 之后，会将这笔请求通过 Domain Socket 发送给 Mosn V2，然后 Mosn V2 根据 ConnectionId 即可找到 TCP1 的连接，然后响应给 Client。&lt;/p&gt;

&lt;h2 id=&quot;极致性能优化&quot;&gt;极致性能优化&lt;/h2&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/21.png&quot; alt=&quot;图21. 请求合并写&quot; /&gt;&lt;/p&gt;

&lt;p&gt;SOFAMosn 的核心网络模型是完全自实现的，我们在整个网络层做了非常多的优化，通过 golang 的 writev 我们把多笔请求合并成一次写，降低 sys.call 的调用，提升整体的性能与吞吐。同时在使用 writev 的过程中，有发现 golang 对 writev 的实现有 bug，会导致部分内存无法回收，我们给 golang 提交 PR 修复此问题，已被接受：https://github.com/golang/go/pull/32138&lt;/p&gt;

&lt;p&gt;其他优化点还有很多，不再一一详细描述，仅供思路参考，如：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;SOFAMosn 日志异步化，避免磁盘问题对 SOFAMosn 转发性能的影响&lt;/li&gt;
  &lt;li&gt;Route 路由结果缓存，空间换时间，提升吞吐&lt;/li&gt;
  &lt;li&gt;接近 90% 内存复用，尽量避免字节拷贝&lt;/li&gt;
  &lt;li&gt;Cluster 懒加载，提升 SOFAMosn 启动速度&lt;/li&gt;
  &lt;li&gt;通讯协议层优化，低版本协议针对性升级，降低解包成本&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;演进方向&quot;&gt;演进方向&lt;/h2&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/22.png&quot; alt=&quot;图22. 演进方向控制面结合&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Service Mesh 的控制面建设我们也在规划中逐步向前推进，希望能统一数据面和控制面的交互模型，控制面尽量遵循 SMI 标准，增加对 TCP 协议的描述支持，逐步增强 SOFAMosn 作为数据面的稳定性，减少变更频率，用更通用的模型来描述服务发现、服务治理等场景，DBMesh 也会基于 XDS 做配置的下发，统一又控制面收口数据下发通道。这里控制面直接对接中间件的服务端是基于性能与容量考虑，蚂蚁金服内部的服务发现数据达单机房千万级别，使用 Kubernetes 的 ETCD 无法承载如此巨大的数据量，需要又控制面做桥梁并分片服务于不同的数据面。&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/23.png&quot; alt=&quot;图23. 产品化模型&quot; /&gt;&lt;/p&gt;

&lt;p&gt;接下来还会有完整的产品层建设，借助于 Mesh 化架构的思想，更多的能力希望通过下沉至 Sidecar 的方式来拿到架构升级带来的红利。Mesh 的产品层将会包括多种 Mesh 数据面形态的 Metrics 采集、监控大盘，控制面的统一对外途径，屏蔽外部系统与 Mesh 的交互复杂度，统一控制面与数据面交互协议，通过完善的运维体系建设，提升 Mesh 模式下的 Sidecar 灰度升级能力，做到对应用无打扰且稳定无人值守即可完成版本升级的目的。&lt;/p&gt;

&lt;h2 id=&quot;总结&quot;&gt;总结&lt;/h2&gt;
&lt;p&gt;总结一下全文在 Service Mesh 领域的落地实践，可以归纳为以下六点：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;应用层与基础设施层分离&lt;/li&gt;
  &lt;li&gt;基础设置层一次编写多处复用&lt;/li&gt;
  &lt;li&gt;数据面通过能力平移优先落地&lt;/li&gt;
  &lt;li&gt;降低打扰度提升落地效率&lt;/li&gt;
  &lt;li&gt;控制面建设统一数据面配置模型&lt;/li&gt;
  &lt;li&gt;性能、稳定性、可观测性持续优化&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;本文介绍了蚂蚁金服在 Service Mesh 落地的演进过程以及相关痛点的解决方式，希望可以通过我们的实际经历来为读者带来一些不同与社区主流方案的演进思考。&lt;/p&gt;

&lt;h3 id=&quot;提到的相关开源组件地址&quot;&gt;提到的相关开源组件地址：&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;SOFAMosn：&lt;a href=&quot;https://github.com/sofastack/sofa-mosn&quot;&gt;https://github.com/sofastack/sofa-mosn&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;SOFARPC：&lt;a href=&quot;https://github.com/sofastack/sofa-rpc&quot;&gt;https://github.com/sofastack/sofa-rpc&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;SOFARegistry：&lt;a href=&quot;https://github.com/sofastack/sofa-registry&quot;&gt;https://github.com/sofastack/sofa-registry&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;SOFABoot：&lt;a href=&quot;https://github.com/sofastack/sofa-boot&quot;&gt;https://github.com/sofastack/sofa-boot&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name>JervyShi</name></author><category term="service-mesh" /><category term="service-mesh" /><category term="golang" /><summary type="html">本文整理自 GIAC（GLOBAL INTERNET ARCHITECTURE CONFERENCE）全球互联网架构大会，蚂蚁金服 Service Mesh 落地实践与挑战分享。分享基于 Service Mesh 的理念，结合蚂蚁金服内部实际场景，将中间件、数据层、安全层等能力从应用中剥离出来后下沉至独立的 Sidecar SOFAMosn 中，结合 Kubernetes 运维体系，提供应用无感知的情况下升级基础设施层能力的案例。 本次分享将从以如下次序展开进行： 蚂蚁金服当前的服务化现状 在看蚂蚁金服的服务化架构之前我们先从一个简单的服务化调用示例说起，下图是 SOFARPC 基本原理： 我们从上图可以看出，构建一个服务化框架需要有服务注册中心，有服务定义，调用方和服务提供方使用相同的服务定义来互相通讯。通过服务注册中心，调用方可以直接订阅到服务提供方的地址，采用点对点的方式直接发起请求。客户端内可实现服务发现、路由寻址、负载均衡、限流熔断等能力来增强服务通讯能力。通过我们开源的 SOFARPC、SOFARegistry、SOFABoot，用户已经可以直接构建起微服务体系，助力业务发展。 蚂蚁金服发展至今，双 11 系统需要应对的交易洪峰逐年递增： 每秒 26.5 万笔交易是 2017 年双 11 的峰值数据，这个数据背后有非常复杂的架构支持，LDC 单元化架构是蚂蚁金服沉淀多年的核心架构，依靠这个架构实现每年峰值交易量飞速增长下系统依然能平滑渡过。我们来简要看下 LDC 架构： 上图摘自 金融级分布式架构 中的 素描单元化 一文，这里不详细展开。LDC 的单元化架构给应用的服务化带来更多的规范与抽象，服务路由中需要考虑单元间的调用，跨机房调用等更多场景。这里主要希望表达的是 LDC 架构给 RPC 调用带来更高的复杂度。 服务化痛点 中间件版本升级 在上面介绍背景时，有介绍到目前 LDC 架构下服务调用的复杂度，这些复杂度目前是直接体现在应用的代码中。对于业务同学来讲，一个应用的关注重点是如何实现业务逻辑，至于高可用、容灾等能力更多是整体架构层面会考虑的点。应用内通过引入 RPC 的 jar 包即可获得 LDC 架构下服务调用各种能力的支撑，带来便利的同时也可以看到这种模式的缺点： 应用内除业务逻辑之外，由中间件的 SDK 引入大量外部依赖，来完成服务发现、路由寻址、负载均衡、限流熔断、序列化、通讯等能力，每个组件的引入都可能带来稳定性风险，以及更高的升级成本。 根据目前 SOFARPC 在内部的版本举例，服务发现依赖 SOFARegistry 的客户端做 IDC 内的服务发现，依赖 Antvip 做跨 IDC 的服务发现，ZoneClient 集成 LDC 架构的单元化信息，路由寻址需要根据请求的入参计算目前 Zone 然后确定调用目标，限流熔断依赖 Guardian 组件，通讯协议与序列化协议相对稳定，变更较少。仅为了完成服务调用，应用需要额外引入 7+ 客户端包。 每年双 11 需要涉及到架构调整时：比如支持弹性架构，需要做很多中间件客户端的版本升级来支撑更优的架构，对于业务同学来讲，这些升级是很耗费精力的，拿 200 个核心应用举例，每个应用升级中间件版本经过研发、测试、再到部署预发、灰度、生产等环境需要 5个人日的话，200 个核心应用中间件升级需要耗费 1000 人日，如果这部分时间可以节省出来，每年架构升级可以节约大量人力资源。 跨语言通讯 蚂蚁金服发展至今，内部业务百花齐放，搜索推荐、人工智能、安全等各种业务使用到的技术栈非常多样化，跨语言的服务通讯能力也十分重要。早在几年前，Java 之外规模最大的就是 NodeJS 应用，为了让 Java 和 NodeJS 应用之间可以复用蚂蚁金服内部的各种中间件和基础设施，前端团队使用 NodeJS 逐步重写了各种中间件客户端，让整个 NodeJS 和 Java 体系可以完美互通。 中间件 SDK 跨语言重写与维护成本极高，随着语言种类的增多，跨语言通讯的诉求也越来越多。 Java, NodeJS, Go, Python, C++ 等，5+ 语言，中间件 SDK 全部重写成本极高。这些问题不得不激励我们寻找更优的解法。 解决痛点 SDK 能力下沉 依然以上述 RPC SDK 举例，SDK 中的能力我们可以根据稳定性与不可剥离等特性来看，哪些是可以从应用中抽出来的，尽量把 SDK 做薄，做的足够稳定无需变更，那么升级成本将不复存在。</summary></entry><entry><title type="html">下载不同服务器相同域名下日志文件</title><link href="https://jervyshi.me/http-header-host-python-log-download/" rel="alternate" type="text/html" title="下载不同服务器相同域名下日志文件" /><published>2013-10-30T00:00:00+00:00</published><updated>2013-10-30T00:00:00+00:00</updated><id>https://jervyshi.me/http-header-host-python-log-download</id><content type="html" xml:base="https://jervyshi.me/http-header-host-python-log-download/">&lt;h3 id=&quot;前言&quot;&gt;前言&lt;/h3&gt;
&lt;p&gt;最近遇到一个问题：我们的应用部署在多台服务器上，偶尔需要把日志下载下来分析就需要手动更改本机hosts文件来连接到不同的服务器一遍遍的下载日志。本着懒人原则，如何更高效的从不同服务器上的相同域名上下载日志文件已经成为必须解决的问题。&lt;/p&gt;

&lt;h3 id=&quot;分析&quot;&gt;分析&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;过程：&lt;/strong&gt;下载日志文件需要发出一次http请求，如url: &lt;em&gt;http://jervyshi.me/logs/debug.log&lt;/em&gt; ，每次http请求都会根据url中的domain去做DNS解析获取到对应的服务器ip，如果我们指定hosts，则在做DNS解析前优先读取hosts中配置的ip，获取到ip之后与对应服务器建立连接然后获取数据。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;方案一：&lt;/strong&gt;如果能根据domain对应的已知服务器列表在每次请求日志文件时候更改hosts文件中此domain的配置可以实现此功能，之前手动操作完全是按照此方法来，缺点很明显下载一个文件改一次hosts。如果用程序实现，在程序下载日志时hosts频繁更改，影响正常浏览器访问，此方案不佳。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;方案二：&lt;/strong&gt;如果能在读取本地hosts文件之前就已经指定ip，显然会方便很多。其实在一次http请求发出时，请求头中会包含 &lt;em&gt;Host&lt;/em&gt; 信息，如果url中domain不是ip那么会把domain截取出来放进http请求头 &lt;em&gt;Host&lt;/em&gt; 中，如：&lt;em&gt;http://192.168.1.100/logs/debug.log&lt;/em&gt; 然后将本次请求的header中增加 &lt;em&gt;Host:jervyshi.me&lt;/em&gt; ，这样就可以使程序通过切换ip来访问不同服务器上的domain。&lt;/p&gt;

&lt;h3 id=&quot;实现&quot;&gt;实现&lt;/h3&gt;
&lt;p&gt;根据方案二，我用python做了一个简单的实现，可以通过配置来达到从不同服务器上获取相同域名下的日志文件并且分类保存。具体代码参见： &lt;em&gt;https://github.com/JervyShi/python-utils&lt;/em&gt;&lt;/p&gt;</content><author><name>JervyShi</name></author><category term="python" /><category term="python" /><category term="http" /><summary type="html">前言 最近遇到一个问题：我们的应用部署在多台服务器上，偶尔需要把日志下载下来分析就需要手动更改本机hosts文件来连接到不同的服务器一遍遍的下载日志。本着懒人原则，如何更高效的从不同服务器上的相同域名上下载日志文件已经成为必须解决的问题。 分析 过程：下载日志文件需要发出一次http请求，如url: http://jervyshi.me/logs/debug.log ，每次http请求都会根据url中的domain去做DNS解析获取到对应的服务器ip，如果我们指定hosts，则在做DNS解析前优先读取hosts中配置的ip，获取到ip之后与对应服务器建立连接然后获取数据。 方案一：如果能根据domain对应的已知服务器列表在每次请求日志文件时候更改hosts文件中此domain的配置可以实现此功能，之前手动操作完全是按照此方法来，缺点很明显下载一个文件改一次hosts。如果用程序实现，在程序下载日志时hosts频繁更改，影响正常浏览器访问，此方案不佳。 方案二：如果能在读取本地hosts文件之前就已经指定ip，显然会方便很多。其实在一次http请求发出时，请求头中会包含 Host 信息，如果url中domain不是ip那么会把domain截取出来放进http请求头 Host 中，如：http://192.168.1.100/logs/debug.log 然后将本次请求的header中增加 Host:jervyshi.me ，这样就可以使程序通过切换ip来访问不同服务器上的domain。 实现 根据方案二，我用python做了一个简单的实现，可以通过配置来达到从不同服务器上获取相同域名下的日志文件并且分类保存。具体代码参见： https://github.com/JervyShi/python-utils</summary></entry><entry><title type="html">Mac安装分区无损扩容</title><link href="https://jervyshi.me/mac-partition-lossless-expansion/" rel="alternate" type="text/html" title="Mac安装分区无损扩容" /><published>2013-06-01T00:00:00+00:00</published><updated>2013-06-01T00:00:00+00:00</updated><id>https://jervyshi.me/mac-partition-lossless-expansion</id><content type="html" xml:base="https://jervyshi.me/mac-partition-lossless-expansion/">&lt;h3 id=&quot;一背景&quot;&gt;一、背景&lt;/h3&gt;
&lt;p&gt;第一次装mac os x的时候考虑到双系统都使用SSD就仅为mac划分了30G的空间，渐渐的不怎么使用win7的时候发现30G不够用了，此时考虑重装的话又要耗费好多时间显然是不值得了。在网上寻觅了好久也却是没有太多关于mac分区无损扩容的文章，最后在远景上找到一个方案&lt;a href=&quot;http://bbs.pcbeta.com/viewthread-1156969-1-1.html&quot;&gt;扩容Mac系统盘方法之一&lt;/a&gt;，作者写的比较剪短但还是很感谢提供了这样的思路，故我把自己的无损分区过程记录下来，留给后人分享！&lt;/p&gt;

&lt;p&gt;注：此无损分区仅讨论MBR引导下的无损分区扩容方案，GPT分区表本身支持无损调整分区大小但不在本文的讨论范围之内。&lt;/p&gt;

&lt;p&gt;HDD我的笔记本有两块硬盘，一块120G的SSD，一块500G的HDD。SSD上有三个分区分别装着WIN7、MAC、软件，HDD留有最初安装的WIN7主分区及一些逻辑分区。此次需要解决的问题是把WIN7无损迁移至HDD，并把整个SSD合并为一个分区给MAC使用，当然MAC的迁移也需要是无损的。&lt;/p&gt;

&lt;h3 id=&quot;二简易解决步骤&quot;&gt;二、简易解决步骤&lt;/h3&gt;
&lt;h4 id=&quot;必备工具&quot;&gt;必备工具：&lt;/h4&gt;
&lt;p&gt;安装有WIN PE的U盘一个，如没有可下载&lt;a href=&quot;http://www.laomaotao.net/&quot;&gt;老毛桃pe&lt;/a&gt;自行制作&lt;/p&gt;
&lt;h5 id=&quot;步骤&quot;&gt;步骤：&lt;/h5&gt;
&lt;ol&gt;
  &lt;li&gt;通过PE将SSD上的WIN7分区通过Ghost工具的Partition to Partition完整copy到HDD上的主分区&lt;/li&gt;
  &lt;li&gt;把SSD上的软件分区完整合并到HDD的第一个逻辑分区，清空HDD最后一个逻辑分区数据&lt;/li&gt;
  &lt;li&gt;通过PE重建HDD主分区引导&lt;/li&gt;
  &lt;li&gt;进入HDD主分区的WIN7，并安装WINDOWS版变色龙&lt;/li&gt;
  &lt;li&gt;使用DiskGenius把HDD最后一个逻辑分区删除并重建为NTFS格式分区（未格式化状态）&lt;/li&gt;
  &lt;li&gt;进入MAC使用磁盘工具把HDD最后一个逻辑分区抹掉为&lt;em&gt;Mac OS 扩展（日志式）&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;使用 &lt;em&gt;Super Dumper!&lt;/em&gt; 把Mac整个分区完整copy至第6步建立的mac分区&lt;/li&gt;
  &lt;li&gt;重启进入PE用DiskGenius把HDD主分区设置为&lt;em&gt;活动&lt;/em&gt;分区&lt;/li&gt;
  &lt;li&gt;重启通过第4部安装的变色龙选择HDD最后一个分区进入copy后的mac系统（确保此分区mac可启动）&lt;/li&gt;
  &lt;li&gt;重启进入PE使用DiskGenius把SSD上面的三个分区全部删除并新建唯一NTFS格式主分区（未格式化状态）&lt;/li&gt;
  &lt;li&gt;重启进入HDD上的mac系统并使用磁盘工具把SSD上的未格式化分区抹掉为&lt;em&gt;Mac OS 扩展（日志式）&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;使用 &lt;em&gt;Super Dumper!&lt;/em&gt; 把当前Mac分区完整copy至SSD上的新mac分区&lt;/li&gt;
  &lt;li&gt;重启通过HDD上变色龙进入SSD的mac系统&lt;/li&gt;
  &lt;li&gt;重装mac版变色龙对SSD上的mac进行引导&lt;/li&gt;
  &lt;li&gt;重启直接把SSD做为第一启动项启动进入Mac，至此已经完成无损迁移&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;三详细图文步骤解说&quot;&gt;三、详细图文步骤解说&lt;/h3&gt;
&lt;p&gt;1、通过PE将SSD上的WIN7分区通过Ghost工具的Partition to Partition完整copy到HDD上的主分区：&lt;/p&gt;

&lt;p&gt;此步骤主要为无损迁移WIN7系统，通过Ghost工具的分区对分区的对拷可轻松实现整个windows系统的迁移，但是如此迁移后会有引导问题，后续会修复，见下图从SSD_MAC至HDD_MAIN&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/713d9449jw1e58o121lfkj206p05pdg7.jpg&quot; alt=&quot;partition-info&quot; /&gt;&lt;/p&gt;

&lt;p&gt;2、把SSD上的软件分区完整合并到HDD的第一个逻辑分区，清空HDD最后一个逻辑分区数据：&lt;/p&gt;

&lt;p&gt;此步骤采用直接复制文件的方式，因SSD_SOFT中安装了常用的windows软件，在windows主分区的注册表表中会有部分软件的路径信息，把SSD_SOFT中的全部文件copy到HDD_1中，再进入HDD_MAIN的win7系统后可修改HDD_1的盘符为D盘即可无损使系统及软件全部迁移。&lt;/p&gt;

&lt;p&gt;3、通过PE重建HDD主分区引导：&lt;/p&gt;

&lt;p&gt;老毛桃PE中桌面上就有重建windows引导的小工具，双击根据提示即可轻松重建引导，如果重建完引导还是无法开机就使用DiskGenius重建下HDD上的MBR引导（此操作不会破坏分区表）&lt;/p&gt;

&lt;p&gt;4、进入HDD主分区的WIN7，并安装WINDOWS版变色龙：&lt;/p&gt;

&lt;p&gt;没有变色龙将无法引导Mac系统，所以如果WIN7主分区上没有变色龙一定要安装变色龙，下载及安装方法见远景论坛-&lt;a href=&quot;http://bbs.pcbeta.com/viewthread-971434-1-1.html&quot;&gt;10.8 的变色龙 Chameleon_2.2svn_r2235 Mac版+Win版+EFI_Tools&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;5、使用DiskGenius把HDD最后一个逻辑分区删除并重建为NTFS格式分区（未格式化状态）：&lt;/p&gt;

&lt;p&gt;格式化的分区Mac下是无法直接对其进行抹掉操作的，所以需要在win下把一个分区删除并重建，但是不能对重建的分区进行格式化操作，新建完如步骤1中的H盘&lt;/p&gt;

&lt;p&gt;6、进入MAC使用磁盘工具把HDD最后一个逻辑分区抹掉为&lt;em&gt;Mac OS 扩展（日志式）&lt;/em&gt;：&lt;/p&gt;

&lt;p&gt;Mac只能对Mac下的分区格式进行操作，所以此步骤就是建立一个可以让Mac把本身的所有文件copy过去的分区&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/713d9449jw1e58psc0q9lj20kk0htac5.jpg&quot; alt=&quot;partition-format&quot; /&gt;&lt;/p&gt;

&lt;p&gt;7、使用 &lt;em&gt;Super Dumper!&lt;/em&gt; 把Mac整个分区完整copy至第6步建立的mac分区：&lt;/p&gt;

&lt;p&gt;工具&lt;em&gt;Super Dumper!&lt;/em&gt;在&lt;a href=&quot;http://bbs.pcbeta.com/viewthread-1156969-1-1.html&quot;&gt;扩容Mac系统盘方法之一&lt;/a&gt;中有下载，打开软件选择 Copy SSD_MAC to disk1s8 ，using Backup - all files 然后就点&lt;em&gt;Copy now&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/713d9449jw1e58o16oiu0j20ey08e3zl.jpg&quot; alt=&quot;ssdmactodisk1s8&quot; /&gt;&lt;/p&gt;

&lt;p&gt;整个过程根据所需要copy分区的大小需要的时间也不同，我30G的分区33分左右copy完成&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/713d9449jw1e58o13glmtj20ey0coq48.jpg&quot; alt=&quot;copy success&quot; /&gt;&lt;/p&gt;

&lt;p&gt;8、重启进入PE用DiskGenius把HDD主分区设置为&lt;em&gt;活动&lt;/em&gt;分区：&lt;/p&gt;

&lt;p&gt;经过第7步，HDD主分区的活动状态将会被转移到HDD最后一个分区的mac系统上，所以需要进入PE把HDD主分区设置为活动，这样就可以启动win7或者是windows版的变色龙&lt;/p&gt;

&lt;p&gt;9、重启通过第4部安装的变色龙选择HDD最后一个分区进入copy后的mac系统（确保此分区mac可启动）：&lt;/p&gt;

&lt;p&gt;此步骤十分重要，通过变色龙启动HDD分区上的mac很有可能不成功，如不成功，请在变色龙启动HDD mac分区之前加上&lt;em&gt;-v -f&lt;/em&gt;参数自行观察错误信息并解决后继续，如果不能确保此分区Mac无问题就把SSD上的Mac干掉后果……&lt;/p&gt;

&lt;p&gt;10、重启进入PE使用DiskGenius把SSD上面的三个分区全部删除并新建唯一NTFS格式主分区（未格式化状态）：&lt;/p&gt;

&lt;p&gt;此步骤同第5步&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/713d9449jw1e58o11cvepj206m04bgls.jpg&quot; alt=&quot;partition-format2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;11、重启进入HDD上的mac系统并使用磁盘工具把SSD上的未格式化分区抹掉为&lt;em&gt;Mac OS 扩展（日志式）&lt;/em&gt;：&lt;/p&gt;

&lt;p&gt;此步骤同第6步&lt;/p&gt;

&lt;p&gt;12、使用 &lt;em&gt;Super Dumper!&lt;/em&gt; 把当前Mac分区完整copy至SSD上的新mac分区：&lt;/p&gt;

&lt;p&gt;此步骤同第7步&lt;/p&gt;

&lt;p&gt;13、重启通过HDD上变色龙进入SSD的mac系统：&lt;/p&gt;

&lt;p&gt;直接启动SSD上的mac是成功不了的，因为mac版的变色龙失效了，所以先从HDD上的windows版变色龙启动SSD上的mac&lt;/p&gt;

&lt;p&gt;14、重装mac版变色龙对SSD上的mac进行引导&lt;/p&gt;

&lt;p&gt;15、重启直接把SSD做为第一启动项启动进入Mac，至此已经完成无损迁移：&lt;/p&gt;

&lt;p&gt;扩容成功，此思路同样适合单硬盘mac分区无损扩容，扩容后效果&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/713d9449jw1e58o15f1j2j20g90a6myu.jpg&quot; alt=&quot;disk-info&quot; /&gt;&lt;/p&gt;</content><author><name>JervyShi</name></author><category term="mac" /><category term="mac" /><category term="hackintosh" /><summary type="html">一、背景 第一次装mac os x的时候考虑到双系统都使用SSD就仅为mac划分了30G的空间，渐渐的不怎么使用win7的时候发现30G不够用了，此时考虑重装的话又要耗费好多时间显然是不值得了。在网上寻觅了好久也却是没有太多关于mac分区无损扩容的文章，最后在远景上找到一个方案扩容Mac系统盘方法之一，作者写的比较剪短但还是很感谢提供了这样的思路，故我把自己的无损分区过程记录下来，留给后人分享！ 注：此无损分区仅讨论MBR引导下的无损分区扩容方案，GPT分区表本身支持无损调整分区大小但不在本文的讨论范围之内。 HDD我的笔记本有两块硬盘，一块120G的SSD，一块500G的HDD。SSD上有三个分区分别装着WIN7、MAC、软件，HDD留有最初安装的WIN7主分区及一些逻辑分区。此次需要解决的问题是把WIN7无损迁移至HDD，并把整个SSD合并为一个分区给MAC使用，当然MAC的迁移也需要是无损的。 二、简易解决步骤 必备工具： 安装有WIN PE的U盘一个，如没有可下载老毛桃pe自行制作 步骤： 通过PE将SSD上的WIN7分区通过Ghost工具的Partition to Partition完整copy到HDD上的主分区 把SSD上的软件分区完整合并到HDD的第一个逻辑分区，清空HDD最后一个逻辑分区数据 通过PE重建HDD主分区引导 进入HDD主分区的WIN7，并安装WINDOWS版变色龙 使用DiskGenius把HDD最后一个逻辑分区删除并重建为NTFS格式分区（未格式化状态） 进入MAC使用磁盘工具把HDD最后一个逻辑分区抹掉为Mac OS 扩展（日志式） 使用 Super Dumper! 把Mac整个分区完整copy至第6步建立的mac分区 重启进入PE用DiskGenius把HDD主分区设置为活动分区 重启通过第4部安装的变色龙选择HDD最后一个分区进入copy后的mac系统（确保此分区mac可启动） 重启进入PE使用DiskGenius把SSD上面的三个分区全部删除并新建唯一NTFS格式主分区（未格式化状态） 重启进入HDD上的mac系统并使用磁盘工具把SSD上的未格式化分区抹掉为Mac OS 扩展（日志式） 使用 Super Dumper! 把当前Mac分区完整copy至SSD上的新mac分区 重启通过HDD上变色龙进入SSD的mac系统 重装mac版变色龙对SSD上的mac进行引导 重启直接把SSD做为第一启动项启动进入Mac，至此已经完成无损迁移 三、详细图文步骤解说 1、通过PE将SSD上的WIN7分区通过Ghost工具的Partition to Partition完整copy到HDD上的主分区： 此步骤主要为无损迁移WIN7系统，通过Ghost工具的分区对分区的对拷可轻松实现整个windows系统的迁移，但是如此迁移后会有引导问题，后续会修复，见下图从SSD_MAC至HDD_MAIN</summary></entry><entry><title type="html">MarkDown编辑器汇总</title><link href="https://jervyshi.me/markdown-editor-collections/" rel="alternate" type="text/html" title="MarkDown编辑器汇总" /><published>2013-05-08T00:00:00+00:00</published><updated>2013-05-08T00:00:00+00:00</updated><id>https://jervyshi.me/markdown-editor-collections</id><content type="html" xml:base="https://jervyshi.me/markdown-editor-collections/">&lt;p&gt;&lt;a href=&quot;http://markdown.tw/&quot;&gt;MarkDown&lt;/a&gt;是一种轻量级的标记语言，用于博文再合适不过了。汇总一些&lt;a href=&quot;http://markdown.tw/&quot;&gt;MarkDown&lt;/a&gt;的编辑器方便大家使用。&lt;/p&gt;

&lt;h3 id=&quot;一本地编辑器&quot;&gt;一、本地编辑器&lt;/h3&gt;
&lt;h4 id=&quot;1mac-app--mou&quot;&gt;1、Mac App － &lt;a href=&quot;http://mouapp.com/&quot;&gt;Mou&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;http://mouapp.com/&quot;&gt;Mou&lt;/a&gt;是Mac上非常好用的一款MarkDown编辑器，界面十分简洁，两栏设计编写加预览，用一用你会喜欢上的。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/713d9449jw1e4h6zdb2h9j20s60k60w5.jpg&quot; alt=&quot;Mou&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;2windows-software--markdownpad&quot;&gt;2、Windows Software － &lt;a href=&quot;http://markdownpad.com/&quot;&gt;MarkDownPad&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;http://markdownpad.com/&quot;&gt;MarkDownPad&lt;/a&gt;是 Windows 下的一款全功能的Markdown编辑器。类似Mac下的&lt;a href=&quot;http://mouapp.com/&quot;&gt;Mou&lt;/a&gt;，清爽的编辑界面，并有预览功能，如果不需要预览的话其实&lt;a href=&quot;http://www.sublimetext.com/2&quot;&gt;Sublime Text 2&lt;/a&gt;才是跨平台的不二之选。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/713d9449jw1e4h7flnkhfj20q40ibn2a.jpg&quot; alt=&quot;MarkDownPad&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;二在线编辑器&quot;&gt;二、在线编辑器&lt;/h3&gt;
&lt;h4 id=&quot;1mahua---支持vim模式&quot;&gt;1、&lt;a href=&quot;http://mahua.jser.me/&quot;&gt;MaHua&lt;/a&gt; - 支持vim模式&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;http://mahua.jser.me/&quot;&gt;MaHua&lt;/a&gt;可以直接拖拽markdown文本到页面进行编辑及预览，可导出html格式文件，多主题支持，兼容“GitHub”的markdown语法，并且支持“VIM快捷键”方便vim党。个人觉得很像是&lt;a href=&quot;http://dillinger.io/&quot;&gt;Dillinger&lt;/a&gt;的中文增强版。&lt;/p&gt;
&lt;h4 id=&quot;2prose--a-content-editor-for-github&quot;&gt;2、&lt;a href=&quot;http://prose.io/&quot;&gt;Prose · A Content Editor for GitHub&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;http://prose.io/&quot;&gt;Prose&lt;/a&gt;是一款可直接在线编辑Github中项目文件的在线编辑器，可通过登陆GitHub对Prose进行授权，然后在Prose中对项目文件进行编辑。可对MarkDown文件进行在线预览。&lt;/p&gt;
&lt;h4 id=&quot;3gist&quot;&gt;3、&lt;a href=&quot;https://gist.github.com/&quot;&gt;Gist&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://gist.github.com/&quot;&gt;Github gist&lt;/a&gt;可在线编写各种语言（包含MarkDown）文件并直接具备版本可被用作GitHub的repository。&lt;/p&gt;
&lt;h4 id=&quot;4简书&quot;&gt;4、&lt;a href=&quot;http://jianshu.io/&quot;&gt;简书&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;http://jianshu.io/&quot;&gt;简书&lt;/a&gt;并不是单纯的在线编辑器，它是一个专门为写作者量身打造的写作软件，支持 Markdown。&lt;/p&gt;
&lt;h4 id=&quot;5epiceditor&quot;&gt;5、&lt;a href=&quot;http://epiceditor.com/&quot;&gt;EpicEditor&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;http://epiceditor.com/&quot;&gt;EpicEditor&lt;/a&gt;我最看中的是它的可自定义性，丰富的API使得你可以在你的项目中自定义你最想要的MarkDown编辑器。&lt;/p&gt;

&lt;h3 id=&quot;三浏览器插件&quot;&gt;三、浏览器插件&lt;/h3&gt;
&lt;h4 id=&quot;1chrome插件---made&quot;&gt;1、Chrome插件 - &lt;a href=&quot;https://chrome.google.com/webstore/detail/made/oknndfeeopgpibecfjljjfanledpbkog&quot;&gt;MaDe&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://chrome.google.com/webstore/detail/made/oknndfeeopgpibecfjljjfanledpbkog&quot;&gt;MaDe&lt;/a&gt; 意为 MArkDown Editor，其拥有一个含义十足的图标，具体描述可参见&lt;a href=&quot;https://chrome.google.com/webstore/detail/made/oknndfeeopgpibecfjljjfanledpbkog&quot;&gt;MaDe&lt;/a&gt;内概述。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/713d9449jw1e4ha4j79qnj201e01ea9u.jpg&quot; alt=&quot;MaDe&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;2chrome插件---markdown-here&quot;&gt;2、Chrome插件 - &lt;a href=&quot;https://chrome.google.com/webstore/detail/markdown-here/elifhakcjgalahccnjkneoccemfahfoa&quot;&gt;Markdown Here&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://chrome.google.com/webstore/detail/markdown-here/elifhakcjgalahccnjkneoccemfahfoa&quot;&gt;Markdown Here&lt;/a&gt;推荐自&lt;a href=&quot;http://twitter.com/prime3721&quot;&gt;se7en&lt;/a&gt;，感谢分享！&lt;/p&gt;</content><author><name>JervyShi</name></author><category term="mac" /><category term="markdown" /><category term="editor" /><summary type="html">MarkDown是一种轻量级的标记语言，用于博文再合适不过了。汇总一些MarkDown的编辑器方便大家使用。 一、本地编辑器 1、Mac App － Mou Mou是Mac上非常好用的一款MarkDown编辑器，界面十分简洁，两栏设计编写加预览，用一用你会喜欢上的。 2、Windows Software － MarkDownPad MarkDownPad是 Windows 下的一款全功能的Markdown编辑器。类似Mac下的Mou，清爽的编辑界面，并有预览功能，如果不需要预览的话其实Sublime Text 2才是跨平台的不二之选。 二、在线编辑器 1、MaHua - 支持vim模式 MaHua可以直接拖拽markdown文本到页面进行编辑及预览，可导出html格式文件，多主题支持，兼容“GitHub”的markdown语法，并且支持“VIM快捷键”方便vim党。个人觉得很像是Dillinger的中文增强版。 2、Prose · A Content Editor for GitHub Prose是一款可直接在线编辑Github中项目文件的在线编辑器，可通过登陆GitHub对Prose进行授权，然后在Prose中对项目文件进行编辑。可对MarkDown文件进行在线预览。 3、Gist Github gist可在线编写各种语言（包含MarkDown）文件并直接具备版本可被用作GitHub的repository。 4、简书 简书并不是单纯的在线编辑器，它是一个专门为写作者量身打造的写作软件，支持 Markdown。 5、EpicEditor EpicEditor我最看中的是它的可自定义性，丰富的API使得你可以在你的项目中自定义你最想要的MarkDown编辑器。 三、浏览器插件 1、Chrome插件 - MaDe MaDe 意为 MArkDown Editor，其拥有一个含义十足的图标，具体描述可参见MaDe内概述。 2、Chrome插件 - Markdown Here Markdown Here推荐自se7en，感谢分享！</summary></entry><entry><title type="html">Mac OS X Shell 优化</title><link href="https://jervyshi.me/mac-os-x-shell-optimization/" rel="alternate" type="text/html" title="Mac OS X Shell 优化" /><published>2013-01-30T00:00:00+00:00</published><updated>2013-01-30T00:00:00+00:00</updated><id>https://jervyshi.me/mac-os-x-shell-optimization</id><content type="html" xml:base="https://jervyshi.me/mac-os-x-shell-optimization/">&lt;p&gt;Mac下的Shell默认是白底黑字并且没有linux下各种色彩区分的，这对于用习惯了linux下shell的童鞋们来讲实在是太不舒服了！&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/713d9449gw1e3pa9xfv1fj.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;本着折腾的精神，探索更完美的Shell使用体验之道，Let’s begin！&lt;/p&gt;

&lt;p&gt;##第一步
修改终端配色方案
终端 -&amp;gt; 编好设置 -&amp;gt; 高级 -&amp;gt; 声明终端为：xterm-256color
终端 -&amp;gt; 编好设置 -&amp;gt; 描述文件 -&amp;gt; Homebrew (要设置为默认的啦)
&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/713d9449gw1e3pa9u5x95j.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;这个时候打开终端已经能初见成果了，虽然文字依然只有一种颜色，但底色至少不是白色那样单调了&lt;/p&gt;

&lt;p&gt;##第二步
给当前用户增加配置文件，修改路径，提示符颜色，以及打开ls命令的高亮显示。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cd ~
vim .bash_profile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;保存以下内容&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# change shell color
export CLICOLOR=1
export LSCOLORS=gxfxaxdxcxegedabagacad
# grep
alias grep='grep --color=always'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;之后再重新打开终端之后，就有如下效果了&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/jervyshi/jervyshi.github.io/assets/images/713d9449gw1e3pa9wmqzsj.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;大功告成，享受你的shell吧！&lt;/p&gt;</content><author><name>JervyShi</name></author><category term="mac" /><category term="mac" /><category term="shell" /><summary type="html">Mac下的Shell默认是白底黑字并且没有linux下各种色彩区分的，这对于用习惯了linux下shell的童鞋们来讲实在是太不舒服了！ 本着折腾的精神，探索更完美的Shell使用体验之道，Let’s begin！ ##第一步 修改终端配色方案 终端 -&amp;gt; 编好设置 -&amp;gt; 高级 -&amp;gt; 声明终端为：xterm-256color 终端 -&amp;gt; 编好设置 -&amp;gt; 描述文件 -&amp;gt; Homebrew (要设置为默认的啦) 这个时候打开终端已经能初见成果了，虽然文字依然只有一种颜色，但底色至少不是白色那样单调了 ##第二步 给当前用户增加配置文件，修改路径，提示符颜色，以及打开ls命令的高亮显示。 cd ~ vim .bash_profile 保存以下内容 # change shell color export CLICOLOR=1 export LSCOLORS=gxfxaxdxcxegedabagacad # grep alias grep='grep --color=always' 之后再重新打开终端之后，就有如下效果了 大功告成，享受你的shell吧！</summary></entry><entry><title type="html">CXF webservice调用411 Length Required解决方案</title><link href="https://jervyshi.me/cxf-webservice-nginx-411/" rel="alternate" type="text/html" title="CXF webservice调用411 Length Required解决方案" /><published>2012-09-01T00:00:00+00:00</published><updated>2012-09-01T00:00:00+00:00</updated><id>https://jervyshi.me/cxf-webservice-nginx-411</id><content type="html" xml:base="https://jervyshi.me/cxf-webservice-nginx-411/">&lt;p&gt;项目中一直用到&lt;a href=&quot;http://cxf.apache.org/&quot;&gt;Apache CXF WebService&lt;/a&gt;，原本服务端都是apache做转发，一切都很正常。有一天服务端换成nginx做转发，问题就出来了，客户端调用时抛出 411 Length Required 异常。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;javax.xml.ws.soap.SOAPFaultException: Response was of unexpected text/html ContentType.  
Incoming portion of HTML stream: &amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;411 Length Required&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;
&amp;lt;body bgcolor=&quot;white&quot;&amp;gt;
&amp;lt;center&amp;gt;&amp;lt;h1&amp;gt;411 Length Required&amp;lt;/h1&amp;gt;&amp;lt;/center&amp;gt;
&amp;lt;hr&amp;gt;&amp;lt;center&amp;gt;nginx&amp;lt;/center&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
	at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:146)
	at $Proxy53.testCXF(Unknown Source)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;根据异常的提示大致分析出异常应该是在客户端向服务端发出请求时请求头中不包含”&lt;em&gt;Content-length&lt;/em&gt;”，尝试用空对象调用接口异常并未抛出，只有当List中超过一定量如50的bean之后会抛出此异常。据此分析apache cxf对不同数据量进行请求时并不是采用同种方式，为了方便分析不同数据量请求头的区别，我找到一台Linux用nc命令监控8080端口，并将客户端数据发送至此Linux上的8080端口。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# nc -l 8080
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;第一步:使用小数据量进行测试，获取请求头如下，发现可以调用成功时cxf发送数据时请求头中包含”&lt;em&gt;Content-Length&lt;/em&gt;”&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;POST / HTTP/1.1
Content-Type: text/xml; charset=UTF-8
SOAPAction: &quot;&quot;
Accept: */*
User-Agent: Apache CXF 2.2.4
Cache-Control: no-cache
Pragma: no-cache
Host: 192.168.1.110:8080
Connection: keep-alive
Content-Length: 286
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;第二步:使用大数据量进行测试，获取请求头如下，发现可以调用失败时cxf发送数据时请求头中没有包含”&lt;em&gt;Content-Length&lt;/em&gt;”，同时多了一个”&lt;em&gt;Transfer-Encoding&lt;/em&gt;”值为”chunked”，关于”&lt;em&gt;Transfer-Encoding&lt;/em&gt;”的介绍可以参考博文&lt;a href=&quot;http://www.51testing.com/?uid-390472-action-viewspace-itemid-233985&quot;&gt;http协议content-encoding &amp;amp; transfer-encoding&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;POST / HTTP/1.1
Content-Type: text/xml; charset=UTF-8
SOAPAction: &quot;&quot;
Accept: */*
User-Agent: Apache CXF 2.2.4
Cache-Control: no-cache
Pragma: no-cache
Host: 192.168.1.110:8080
Connection: keep-alive
Transfer-Encoding: chunked
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;通过一番搜索，发现apache默认就是支持&lt;em&gt;chunked&lt;/em&gt;块接收的，而nginx如果要支持这种格式必须要添加&lt;em&gt;chunkin-nginx-module&lt;/em&gt;模块，但是给nginx添加新模块需要重新编译nginx，虽然能解决现有问题但是有必要通过一系列的测试等，需要找到一个更简单的临时解决方案。&lt;/p&gt;

&lt;p&gt;既然apache cxf可以在请求头中添加”&lt;em&gt;Content-Length&lt;/em&gt;”来发送并且数据量达到一定值之后会转换为&lt;em&gt;chunked&lt;/em&gt;块发送，那么是否可以关掉chunked块发送方式呢，感谢apache cxf官网完善的文档，经过一番探索在&lt;a href=&quot;http://cxf.apache.org/docs/client-http-transport-including-ssl-support.html&quot;&gt;Apahce cxf-User’s Guide&lt;/a&gt;中找到了”&lt;em&gt;AllowChunking&lt;/em&gt;”的设置，有两种方式，可以直接在代码中设置&lt;em&gt;AllowChunking&lt;/em&gt;也可以在配置文件中设置&lt;em&gt;AllowChunking&lt;/em&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;//Turn off chunking so that NTLM can occur
Client client = ClientProxy.getClient(port);
HTTPConduit http = (HTTPConduit) client.getConduit();
HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
httpClientPolicy.setConnectionTimeout(36000);
httpClientPolicy.setAllowChunking(false);
http.setClient(httpClientPolicy);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;也可以在配置文件中设置&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;http-conf:conduit name=&quot;{http://apache.org/hello_world_soap_http}SoapPort.http-conduit&quot;&amp;gt;
  &amp;lt;http-conf:client Connection=&quot;Keep-Alive&quot; MaxRetransmits=&quot;1&quot; AllowChunking=&quot;false&quot; /&amp;gt;
&amp;lt;/http-conf:conduit&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;配置文件中”&lt;em&gt;http-conf:conduit&lt;/em&gt;”的name设置格式是”&lt;em&gt;{WSDL Namespace}portName.http-conduit&lt;/em&gt;”，但是这种方式经常由于搞错WSDL Namespace与portName而导致设置不生效，其实name还有一种设置格式是路径匹配，假如我是服务端提供了一个服务，服务地址是”&lt;em&gt;http://jervyshi.tk/services/userService?wsdl&lt;/em&gt;”，这个时候name只需要配置为”&lt;em&gt;http://jervyshi.tk/.*&lt;/em&gt;”即可拦截”&lt;em&gt;http://jervyshi.tk&lt;/em&gt;”下的所有服务。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;http-conf:conduit name=&quot;http://jervyshi.tk/.*&quot;&amp;gt;
  		&amp;lt;http-conf:client AllowChunking=&quot;false&quot; /&amp;gt;
&amp;lt;/http-conf:conduit&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name>JervyShi</name></author><category term="java" /><category term="java" /><category term="linux" /><category term="webservice" /><category term="nginx" /><summary type="html">项目中一直用到Apache CXF WebService，原本服务端都是apache做转发，一切都很正常。有一天服务端换成nginx做转发，问题就出来了，客户端调用时抛出 411 Length Required 异常。 javax.xml.ws.soap.SOAPFaultException: Response was of unexpected text/html ContentType. Incoming portion of HTML stream: &amp;lt;html&amp;gt; &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;411 Length Required&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt; &amp;lt;body bgcolor=&quot;white&quot;&amp;gt; &amp;lt;center&amp;gt;&amp;lt;h1&amp;gt;411 Length Required&amp;lt;/h1&amp;gt;&amp;lt;/center&amp;gt; &amp;lt;hr&amp;gt;&amp;lt;center&amp;gt;nginx&amp;lt;/center&amp;gt; &amp;lt;/body&amp;gt; &amp;lt;/html&amp;gt; at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:146) at $Proxy53.testCXF(Unknown Source) 根据异常的提示大致分析出异常应该是在客户端向服务端发出请求时请求头中不包含”Content-length”，尝试用空对象调用接口异常并未抛出，只有当List中超过一定量如50的bean之后会抛出此异常。据此分析apache cxf对不同数据量进行请求时并不是采用同种方式，为了方便分析不同数据量请求头的区别，我找到一台Linux用nc命令监控8080端口，并将客户端数据发送至此Linux上的8080端口。 # nc -l 8080 第一步:使用小数据量进行测试，获取请求头如下，发现可以调用成功时cxf发送数据时请求头中包含”Content-Length” POST / HTTP/1.1 Content-Type: text/xml; charset=UTF-8 SOAPAction: &quot;&quot; Accept: */* User-Agent: Apache CXF 2.2.4 Cache-Control: no-cache Pragma: no-cache Host: 192.168.1.110:8080 Connection: keep-alive Content-Length: 286 第二步:使用大数据量进行测试，获取请求头如下，发现可以调用失败时cxf发送数据时请求头中没有包含”Content-Length”，同时多了一个”Transfer-Encoding”值为”chunked”，关于”Transfer-Encoding”的介绍可以参考博文http协议content-encoding &amp;amp; transfer-encoding POST / HTTP/1.1 Content-Type: text/xml; charset=UTF-8 SOAPAction: &quot;&quot; Accept: */* User-Agent: Apache CXF 2.2.4 Cache-Control: no-cache Pragma: no-cache Host: 192.168.1.110:8080 Connection: keep-alive Transfer-Encoding: chunked 通过一番搜索，发现apache默认就是支持chunked块接收的，而nginx如果要支持这种格式必须要添加chunkin-nginx-module模块，但是给nginx添加新模块需要重新编译nginx，虽然能解决现有问题但是有必要通过一系列的测试等，需要找到一个更简单的临时解决方案。 既然apache cxf可以在请求头中添加”Content-Length”来发送并且数据量达到一定值之后会转换为chunked块发送，那么是否可以关掉chunked块发送方式呢，感谢apache cxf官网完善的文档，经过一番探索在Apahce cxf-User’s Guide中找到了”AllowChunking”的设置，有两种方式，可以直接在代码中设置AllowChunking也可以在配置文件中设置AllowChunking //Turn off chunking so that NTLM can occur Client client = ClientProxy.getClient(port); HTTPConduit http = (HTTPConduit) client.getConduit(); HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy(); httpClientPolicy.setConnectionTimeout(36000); httpClientPolicy.setAllowChunking(false); http.setClient(httpClientPolicy); 也可以在配置文件中设置 &amp;lt;http-conf:conduit name=&quot;{http://apache.org/hello_world_soap_http}SoapPort.http-conduit&quot;&amp;gt; &amp;lt;http-conf:client Connection=&quot;Keep-Alive&quot; MaxRetransmits=&quot;1&quot; AllowChunking=&quot;false&quot; /&amp;gt; &amp;lt;/http-conf:conduit&amp;gt; 配置文件中”http-conf:conduit”的name设置格式是”{WSDL Namespace}portName.http-conduit”，但是这种方式经常由于搞错WSDL Namespace与portName而导致设置不生效，其实name还有一种设置格式是路径匹配，假如我是服务端提供了一个服务，服务地址是”http://jervyshi.tk/services/userService?wsdl”，这个时候name只需要配置为”http://jervyshi.tk/.*”即可拦截”http://jervyshi.tk”下的所有服务。 &amp;lt;http-conf:conduit name=&quot;http://jervyshi.tk/.*&quot;&amp;gt; &amp;lt;http-conf:client AllowChunking=&quot;false&quot; /&amp;gt; &amp;lt;/http-conf:conduit&amp;gt;</summary></entry></feed>