在云原生社区近日主办的 Service Mesh Summit 2022 服务网格峰会上,网易数帆云原生技术专家方志恒分享了轻舟服务网格无侵入加强 Istio 的教训,本文据此次分享整顿,介绍了对无侵入和实现的思考,轻舟服务网格演进过程中的扩大加强,以及这些扩大加强和无侵入的关系。这里“无侵入”强调的是对服务网格基础设施自身的无侵入,而不是只有对业务的无侵入,后者是服务网格自身的定位所要思考的内容。
服务网格保护中的无侵入
对于无侵入,咱们从各自的实践经验也晓得,做无侵入的加强是十分艰难的。起因有很多,比如说咱们可能要做业务的适配,疾速落地,定制的一些需要等,业务以及我的项目周期的压力,迫使咱们不得不做出一些有侵入的抉择。然而咱们为什么还要去强调无侵入呢?因为对于咱们保护团队,或者说对于咱们本人这个技术计划的保护方来说,每一分侵入都会有每一分的老本,它会在后续会体现进去,比如说在做长期保护,做版本演进,去做社区的一些性能和新版本的对齐,咱们都须要去解决咱们的改变和社区的骨干分支之间的抵触。
因而,咱们须要在咱们的研发流程外面去贯彻这样一个指标或者理念:这个计划是不是做到无侵入了,如果没有做到的话,那做到的水平是怎么样的?这样可能才失去一个“求上得中”的成果,就是保持无侵入,咱们才可能做到比拟低的侵入。
在应用社区的计划去做定制开发、去演进的过程中,咱们认为,有一些比拟适合的用来去做保护的思路,最合适的形式,是间接应用社区原生的 API 提供的扩大点去做一些无侵入的扩大,这是最现实的状况。当然,社区的一些扩大的 API 可能无奈齐全满足咱们的需要,这个时候咱们能够在下层去做一个封装,业界的一些落地的实际案例也体现出这样的理念。这里援用一句名言:计算机科学畛域的任何问题,都能够通过减少一个中间层来解决。
即便是这样,咱们出于性能的思考,或者出于个性的思考,很多时候还是会面临一些不得不去做批改的状况。咱们有第二个准则,就是把扩大加强的内容去做一些封装在一个独自的库外面,这样能够做到最小的批改和替换。这也是一个比拟奢侈的工程教训。
第三点,如果咱们的确要做比拟大的一个批改,这个时候咱们能够尽量去贯彻一个理念,就是要对社区原生的一些设计思路和个性做一致性的对齐。这里我分享一个“撸猫准则”:如果咱们非要去撸一只猫的话,最好顺着它的毛去撸,否则咱们可能会把它的毛搞得很乱,甚至它还会反过来咬咱们一口。
服务和配置的扩大
首先介绍咱们对 Istio 的服务和配置的扩大。
配置
Istio 社区曾经提供反对多 configSource,并给出了一个协定叫 MCP-over-xds,通过这种形式咱们能够从不同的数据源去拿到所需的配置。
configSources:- address: xds://mesh-registry.istio-system.svc:16010?type=serviceentry&type=sidecar- address: k8s://
这里给出一个配置样例,是通过 xDS 协定去向某一个服务去获取它的配置,同时也能够去 Kubernetes 去获取那些规范的 CR,这是它的一个扩大的形式。
咱们的 URL 跟官网的略微有点不一样,是在这根底上略微做了一点改良,实现了一个叫做 Istio-MCP 的库平替社区原生的 adsc,这就是后面说的第二个准则。在这个库外面,咱们实现了 xDS 的增量推送,更加强了一个 revision 的机制,Istio 反对依照 revision 去获取本人感兴趣的配置,咱们对此做了加强。咱们还做了一个更灵便的分派,容许在 configSource 外面去指定一个类型,相当于从不同的 configSource 去获取不同类型的配置,这个很多时候都是实际的须要。
服务
服务这部分,在网易数帆的场景外面,比拟宽泛地利用到了 ServiceEntry
。Istio 对 Kubernetes 服务的反对很好,大部分状况下无需做额定的扩大,然而因为它的定位,Istio 把对非 Kubernetes 服务的反对简直都留给了它的一个扩大点,就是 ServiceEntry
这个API,以及后面所说的配置扩大的形式。通过这种形式,Istio 容许第三方来作为配置和服务的提供员,来提供其余的服务模型。当然在这个过程中,第三方须要本人去实现服务模型的转换,因为 ServiceEntry
简直就是 Istio 外部服务模型的 API 版本,你能够认为它是 Istio Service 模型。
咱们也有一个独自的组件,叫做 mesh-registry,实现了 MCP-over-xds 的协定,作为一个MCP server。在这个组件外部,咱们反对了不同的服务模型的转换,包含将 Dubbo/ZK、Eureka、Nacos 去转换成规范的 ServiceEntry,而后下发。
这是在服务这一块的扩大。从目前来说,以上两局部的扩大形式都能够说是无侵入的,是基于社区原生接口和协定的扩大。
插件的扩大
第二局部是插件的扩大。Istio 的性能的确很丰盛,这导致它在市场上成为支流,应用的人很多。但很多人应用同时也意味着,即便 Istio 的能力再丰盛,它也无奈笼罩所有用户的场景,就会须要这种扩大机制。
EnvoyFilter
Istio 社区的扩大形式是一个比拟典型的 EnvoyFilter 的形式。这种形式,configPatches 进去的内容是 Envoy 的一个一个 filter 的配置,Envoy 具体的内容咱们能够先疏忽,先看一下 applyTo、context、match、routeConfiguration、vhost 这一堆货色。
举个例子,咱们要做一个限流的性能,因为它是一个业务性能,作为使用者,咱们要晓得限流 API 的业务语义,首先须要去看 Envoy 的限流插件它的 API 是怎么样的,跟下层对限流的业务需要是不是对得上,再确定我应该怎么样去写一个限流的插件的配置。到这一步还只是实现了要 Patch 进去的内容,要写出这个 EnvoyFilter 的时候,咱们还须要去理解更多的货色,比方这里的 applyTo、HTTP_ROUTE 以及 vhost 等。如果是其余的类型的 Patch,可能还有其余的概念。
apiVersion: networking.istio.io/v1alpha3kind: EnvoyFiltermetadata: name: bookinfo-gateway-sampling namespace: istio-systemspec: configPatches: - applyTo: HTTP_ROUTE match: context: GATEWAY routeConfiguration: portNumber: 80 vhost: name: "*:80" patch: operation: MERGE value:
这外面有一个实质的问题,filter 是 Istio 提供的一个简直是纯数据结构级别的 Patch 机制,它间接操作 Istio 下发给 Envoy 的 xDS 配置,它的数据结构的形容、定义和类型都是 Envoy 侧的一些概念,比方 vhost,这就意味着 Istio 的使用者须要深刻理解 Envoy 侧的概念。同时还有一些的灰色地带,举个例子,如果咱们要给一个 vhost 去 Patch 一些货色,就要晓得 vhost name,而 vhost name 是 Istio 本人的一个实现,纯正实现层面的货色,相当于说下层的使用者还要晓得某一个版本的 Istio,它的 vhost name 是通过什么规定拼起来的。咱们会认为对使用者来说累赘会比拟多,一个比拟现实的做法是,他既然是 Istio 的使用者,那么他接触到的应该尽量是 Istio 层面的一些语义。咱们对它做加强的思路就是这样的。
上面是轻舟服务网格做的一个比拟浅的封装,然而在咱们外部用得很多,所以咱们认为它解决了一些理论问题。这个字段形容咱们这个插件要去作用于网关,作用于某一个 host,作用于某一条路由,也就是说咱们会尽量用 Istio 层面的语义来做这种相似的封装,帮用户转成上层的 Envoy 语义。
apiVersion: microservice.slime.io/v1alpha1kind: EnvoyPluginmetadata: name: reviews-ep namespace: istio-samplesspec: workloadSelector: labels: app: reviews gateway: - gateway-system/prod-gateway host: - reviews.istio-samples.svc.cluster.local route: - ratings.istio-samples.svc.cluster.local:80/default - prefix-route1 plugins: - name: envoy.filters.network.ratelimit enable: true inline: settings: {{plugin_settings}} # plugin settings
基于同样的思路,咱们还做了一个限流的模块。但这里不是为了讲限流,而是说咱们怎么去做下层的业务语义形容。限流这个性能有点特地,能够做得很简单,所以 Envoy 提供了一个非常灵活的 API,这带的一个问题是,别说 Istio 的用户,就是 Istio 的维护者本人要把 Envoy 限流 API 看明确,都须要付出较多的工夫和精力。所以,咱们心愿把它做得简化一点,更靠近业务语义形容,这也是一个复杂度的消化——Envoy 做得非常灵活,它什么都能够做,但复杂度不会凭空隐没,两头须要必定有一层实现业务语义到底层的灵便能力的映射。
apiVersion: microservice.slime.io/v1alpha2kind: SmartLimitermetadata: name: review namespace: defaultspec: sets: v1: descriptor: - action: fill_interval: seconds: 1 quota: "10" strategy: "single" condition: "{{.v1.cpu.sum}}>10" target: port: 9080
Rider 插件扩大
插件扩大的第二大类是咱们的 Rider 的插件,Rider 比拟像 Envoy 版本的 OpenResty,Envoy 自身有反对 Lua 的插件,然而它的反对比较简单,外面的 API 比拟少,相熟 OpenResty 的同学应该晓得,咱们写 Lua 和 OpenResty 是齐全不一样的,因为 OpenResty 提供了很丰盛的,跟网络操作、跟 Nginx 外部 API 做交互的 API,让咱们很容易去做理论业务性能的开发,你无奈设想咱们纯正用 Lua 去开发一个 HTTP_SERVER。基于这个背景,咱们对 Lua 做了一个加强,在 Rider 插件提供了比拟丰盛的 Lua 交互的 API,让用户能够绝对容易地在外面去实现一个下层的业务和治理的性能。另外,咱们也对原生的 Lua 插件实现做了一些性能优化,相比来说 Rider 是有肯定的性能劣势的。
Rider 和原生的 Envoy Lua 插件的比照,是咱们能够反对插件的配置。这里的配置是指相似于 Envoy 的 WASM 或者 Lua 插件,都是分成两局部,一部分是下发一个可执行的内容,无论是 Lua 脚本还是 WASM 二进制,都是一个插件理论执行的逻辑,咱们还能够给它一份配置,这个配置跟执行内容两相结合,造成最终的业务行为。
社区的 Lua 不反对如路由级别的插件配置,这导致它的行为比拟死,比拟 hardcode,咱们反对它的插件配置,反对更多的 API,性能也会更好一点。
当初 WASM 是一个很火的概念,咱们也跟 WASM 做了一个比照,第一点是 Lua 跟 WASM 的比照,作为脚本语言,Lua 更加可见即可得,尽管 WASM 也能够从脚本编译而得,但如果用脚本转成 WASM 再做下发,WASM 编译语言性能损耗更小的劣势就没有了。第二点是便于散发,因为没有编译的过程。第三点也是反对更多的API,原生的 Envoy WASM API 的确会少一些。最初一点是更好的性能,咱们原以为即便思考上 LuaJIT,Rider 的性能也不会更好,但实际上 Envoy WASM API 的实现导致 Envoy WASM 跟 Envoy 外部交互的老本略高,所以测进去它的性能反而比 Rider 要更差一点。
扩大计划 | 是否反对插件配置 | 是否反对动静扩大 | 性能 | 反对语言 | 开发复杂度 |
---|---|---|---|---|---|
原生 C++ | 是 | 否 | 最优 | C++ | 简单 |
社区 Lua | 否 | 是 | 较差 | Lua | 简略 |
社区 WASM | 是 | 是 | 差 | C++/Rust/Go等 | 中等 |
这是咱们实际上测进去的一个比照,咱们别离模仿三种场景下,一个很简略的,一个中等复杂度的,还有一个略微高一点复杂度的,不同计划的性能差异,从图中能够都能够看到,三种场景下 Rider 插件的性能都是好于 WASM C++ 的,尤其是在简单场景,大略有10%左右的晋升,当然这三者相比于原生插件都有不小的差异。
这里给出了一个咱们提供的 API 的列表,能够看到格调还是十分的 Resty 的。
咱们做的 RiderPlugin,这个货色比拟有意思,上面是一个 WASM 的样例,大家能够看到它的 API 的数据结构,齐全是一个 WASM 的 API,但实际上做的事件,是通过镜像的形式把咱们的 Rider 插件给下发了,再散发到数据面,成果是将 HTTP 申请的那个 response 的 body 改成了 C++ is awesome
。所以说,应用上不能说差不多,几乎是截然不同。
# wasm_plugin.yamlapiVersion: extensions.istio.io/v1alpha1kind: WasmPluginmetadata: name: test1.riderspec: imagePullPolicy: IfNotPresent imagePullSecret: qingzhou-secret pluginConfig: destination: Body message: C++ is awesome!! source: Static selector: matchLabels: app: reviews sha256: nil url: oci://slimeio/rider_plugin:0.1.0
我过后看到 Istio 的 WasmPlugin 这个 API 的时候,是有点诧异的,第一是不晓得它为什么要做一个 WasmPlugin,而不是做一个通用的插件散发机制,有点过于耦合了;第二是我发现它字段的设计就是一个通用的插件散发,然而它的名字就叫做 WasmPlugin,当然它在实现的时候也是这样的。所以,咱们齐全能够用这个 API 来实现咱们的 Rider 插件的散发,这个是咱们目前已有的一个个性。当然咱们还另外设计了一个 RiderPlugin CRD,次要是思考到后续 Rider 可能提供更丰盛的性能,会有更多的字段。咱们在实现这个反对的时候,不能说没有侵入,但真的是只改了一点点——它的那些插件散发,包含 Pilot agent 外面,怎么从镜像外面去提取 WASM 文件,咱们简直按同样的标准去定义 Rider 的镜像,去在外面放咱们的 Rider 的插件的配置,Lua 的文件,简直是齐全一样的。这就是后面提到的另一个准则,如果咱们非要去做一些新的性能,能够做得跟原生的比拟像,这样的话无论是咱们本人还是用户,都很容易上手。
咱们最终下发给 Envoy 的一个数据结构,和 WASM 是有一些差别的,这个差别是在实现外面去做了一个屏蔽,实质上说,咱们只是在最初生成下发给 Envoy 的数据的时候对内容做了一些批改,让它是一个 Rider 的格局。
route_config: name: local_route virtual_hosts: - name: local_service domains: - "*" # Plugin config here applies to the VirtualHost # # typed_per_filter_config: # proxy.filters.http.rider: # "@type": type.googleapis.com/proxy.filters.http.rider.v3alpha1.RouteFilterConfig # plugins: routes: - match: prefix: "/static-to-header" route: cluster: web_service # Plugin config here applies to the Route # # plugins is a list of plugin route configs. Each entry has a name and its config. # The filter will look up the list by order given a plugin name, and use the first match entry. typed_per_filter_config: proxy.filters.http.rider: "@type": type.googleapis.com/proxy.filters.http.rider.v3alpha1.RouteFilterConfig plugins: - name: echo config: message: "Lua is awesome!" source: Static destination: Header header_name: x-echo-foo http_filters: - name: proxy.filters.http.rider typed_config: "@type": type.googleapis.com/proxy.filters.http.rider.v3alpha1.FilterConfig plugin: vm_config: package_path: "/usr/local/lib/rider/?/init.lua;/usr/local/lib/rider/?.lua;" code: local: filename: /usr/local/lib/rider/examples/echo/echo.lua name: echo config: message: "C++ is awesome!" source: Static destination: Body - name: envoy.filters.http.router typed_config: {}
基于此咱们还做了后面提到的一个 EnvoyPlugin 的插件,对插件散发做了一个比拟浅的下层封装,也退出了对 WASM、Rider 的反对,将会在近期 release。
Dubbo 协定扩大
接下来介绍协定的扩大。咱们第一个做的是 Dubbo 协定扩大,因为 Dubbo 在国内的确应用很宽泛,同时咱们还有一些非凡的考量,稍后再详解。
- 数据面
首先看数据面的局部。第一,咱们做了比拟丰盛的七层的 dubbo filters,Istio + Envoy 这套体系的大部分治理性能都是通过七层插件来实现的,HTTP 的比拟丰盛的治理性能有很多七层插件,所以咱们也实现了很多 Dubbo 的插件。
"typed_per_filter_config": { "proxy.filters.dubbo.locallimit": { "@type": "type.googleapis.com/udpa.type.v1.TypedStruct", "type_url": "type.googleapis.com/proxy.filters.dubbo.local_limit.v2.\ ProtoCommonConfig", "value": {
第二,咱们实现了一个 DRDS,也就是 Dubbo RDS,因为 Envoy RDS 简直等同于 HTTP RDS,只定义了 HTTP 协定相干的路由的数据结构,咱们要实现一个比拟灵便的路由,以及性能比拟好的路由散发,就须要定义一个独自的 xDS 资源类型。
第三,咱们还做了一个 Dubbo 协定嗅探,这是有一些非凡的场景,Istio 社区对协定嗅探有一部分的的反对,它的本意不是为了实现一个很丰盛的基于协定嗅探的治理,而是为了解决一部分场景需要,相当于咱们引入一个代理之后,会有一些场景须要通过非凡的技术手段去解决,而咱们在理论生产中会面临 HTTP 的、TCP 的、Dubbo 的协定,也须要用同样的机制去解决它,所以咱们也反对 Dubbo 的协定嗅探。其中技术细节十分多,这里就不开展。
- 管制面
管制面的改变更多,用户会更可感知。咱们的反对比拟非凡,因为咱们实现了跟 HTTP 简直齐全等同语义的 Istio API,体现为 VS/DR,就是根本的治理。还有比拟丰盛的治理,是那些七层的 filter,还有 Istio 这一层所形象进去的认证鉴权的策略是只作用于 HTTP 的,咱们也是对它做了 Dubbo 的反对。还有一个比拟非凡的就是 Sidecar,Istio 有一个资源是用来形容利用或者服务之间的依赖关系的,这样就能够实现按需下发,像配置瘦身、推送范畴的影响,都能够失去一个比拟好的优化,咱们对此也做了 Dubbo 的反对,相当于用规范的 API 去反对 Dubbo 的相似于服务依赖形容和按需下发。还有一个是 EnvoyFilter,咱们也反对了用 EnvoyFilter 的规范的 API 去做 Dubbo 插件的散发。
- applyTo: DUBBO_FILTER match: context: SIDECAR_OUTBOUND listener: filterChain: filter: name: envoy.filters.network.dubbo_proxy subFilter: name: envoy.filters.dubbo.router patch: operation: INSERT_BEFORE value: config: '@type': type.googleapis.com/udpa.type.v1.TypedStruct type_url: type.googleapis.com/proxy.filters.dubbo.traffic_mark.v2.ProtoCommonConfig
- 通用七层扩大框架
咱们也做了通用的七层扩大框架的反对,咱们在 Envoy 社区的 Maintainer 也和国内同行沟通过,共同努力推动,目前曾经合入 Envoy 社区版本,也就是说在数据面是有通用七层扩大框架的反对的,后续 Istio 社区相干的反对,我感觉也是能够期待的。
这里简要开展一下我集体对通用七层扩大框架的了解。咱们服务网格多协定适配以及长期保护的老本很高,每接入一个新的协定,都须要去做一个额定的适配。在 Envoy 视角来说,反对一个新的协定须要做的事件,首先是对协定根本的编解码和协定流程的反对,这是协定外部的货色,必定要做的;除此之外,还波及到它要跟 Envoy 原有流程的对接,比方 Cluster 是不是能够用,路由是怎么失效的,流量的分派从 listener 进来怎么走到协定解析器或者是四层的 filter,也就是说,一个新的协定的反对要做很多重复性的事件,比方跟原有的机制相结合,这部分反复的工作量咱们是能够省去的。
从服务代理和服务治理的视角来说,很多时候咱们不关怀它是什么协定,服务治理能够了解为一个基于特色的流量调配或者是流量解决,也就是说通常咱们关怀的是它的特色是否用一种比拟通用的形式去形容,就好比咱们在做协定设计的时候,可能都会塞进去一个字段,叫做 metadata,HTTP 的协定外面的 header 其实就是一种 metadata,如果能用一个比较简单的通用模型去形容咱们所有协定的特色,咱们就能够基于这个模型去做服务治理,剩下的事件就是把已有的协定来转化成这个通用模型。当然,所有的这种加一个简略的中间层去做一个复杂度的屏蔽,都会有一个问题,就是无奈感知咱们形象进去的共性以外的货色。
举个例子,如果咱们要反对 HTTP2,想做一些绝对上层的治理,可能会比拟艰难,因为感知不到 stream、frame 等等,能感知到的就只有它这个形象。这就是我感觉所有相似的技术计划都有同样的问题。然而一个技术计划的价值,必定是在它带来的收益减去副作用之后的,如果咱们感觉还不错,就能够持续去应用它。
咱们目前在用这个通用框架去实现 Dubbo。以前 Dubbo 之所以没有进 Istio 社区,是因为 Istio 社区并不想保护一个特定的协定,即便该协定国内用户比拟多,而且因为年代的起因,Dubbo 是不那么云原生的。然而如果咱们这里引入的不是 Dubbo,而是一个通用的七层框架,那应该比拟乐观一些。所以咱们后续会替换原有的 Dubbo Proxy,就是数据面这一块,同时也会尝试跟相干方去推动管制面的接入,看能不能进入 Istio 社区。
Slime 开源我的项目的集成
上述的很多扩大加强,都曾经积淀在咱们开源的 Slime 我的项目(github.com/slime-io/slime )外面了。这个我的项目曾经进入 Istio 生态,咱们对 Istio 的加强,或者是说魔改也好,或者是说生态丰盛也好,都会放进 Slime 我的项目外面,它是一个 group,外面蕴含比拟多的子项目。这里简略介绍 Slime 最近的一些停顿。首先在架构层面,咱们做了比拟彻底的模块化设计,能够疾速地去对 Slime 做下层性能的裁减。
咱们定义了一个比拟明确的框架层来治理下层的模块,同时也提供一些根底能力给下层,蕴含定义的一些 metric 框架,让下层能够用很少的代码去获取到一些像 Kubernetes 乃至更多类型的 metric 信息,并且对它做一些解决。同时咱们也做了多集群的反对——很多时候咱们之所以做一些货色,是因为 Istio 的多个加强性能都须要去做相干的反对,咱们就会把它放到框架层——在这个框架层咱们间接做了与 Istio 原生比拟统一的多集群感知,社区叫做 multi cluster discovery。
咱们还反对了一个对立的服务模型数据,反对了 Kubernetes Services 和 ServiceEntry,两个消化完当前解决为外部的一个数据类型。咱们之前有理解到,一些同行的敌人在调研技术计划的时候,发现咱们只反对 Kubernetes 就没有持续了。比方懒加载的计划,咱们当初曾经做了一个比拟彻底的反对。
还有一个模块聚合和治理的能力,最终的状态大略是这样,只有手动写几行代码,把每一个模块间接放进来就能够了。
func main() { module.Main("bundle", []module.Module{ &limitermod.Module{}, &pluginmod.Module{}, &pilotadminmod.Module{}, &sidecarmgrmod.Module{}, &tracetiomod.Module{}, &meshregistrymod.Module{}, })}
咱们在最近一年多做了很多的模块,比方后面提到的 meshregistry、pilotadmin、sidecarmgr、tracetio,其中外面有一部分曾经开源进来了,还有一部分因为耦合了一些业务逻辑,可能会晚一点开源。
略微重点说一下,咱们有一个子项目叫做 i9s(github.com/slime-io/i9s ),是从另一个开源我的项目 K9s fork 过去的。相熟 Kubernetes 的同学可能会用过 K9s ,它提供一种交互式的形式,咱们感觉它很好用。同时咱们也想到,对于 Istio 的运维治理,有很多中央也能够用这种形式来实现,应用起来会更不便一些。i9s 实质上是用 K9s 这种交互式的视图去展现 Istio 的各种外部信息,比方能够去查看 Istio 下面连贯哪些 Sidecar,每个 Sidecar 的运行状态,下发的配置,它的配置是否和应有的配置统一,咱们能够去 watch 推送的频率,以及推送的时延,等等。
Slime 我的项目后续会凋谢更多服务网格治理的能力,期待大家共建社区。谢谢!
延长浏览
- 视频回放:https://www.bilibili.com/vide...
- IstioCon 回顾 | 网易数帆的 Istio 推送性能优化教训
- Slime 2022 瞻望:把 Istio 的复杂性塞入智能的黑盒
- Slime 我的项目:https://github.com/slime-io/s...
- i9s 子项目:https://github.com/slime-io/i9s
- Rider 插件框架:https://github.com/hango-io/r...
作者简介: 方志恒,网易数帆云原生技术专家,负责轻舟 Service Mesh,先后参加多家科技公司 Service Mesh 建设及相干产品演进。从事多年基础架构、中间件研发,有较丰盛的 Istio 治理保护、性能拓展和性能优化教训。