科普文:微服务之服务网格Service Mesh
一、ServiceMesh概念
背景
随着业务的发展,传统单体应用的问题越来越严重:
- 单体应用代码库庞大,不易于理解和修改
- 持续部署困难,由于单体应用各组件间依赖性强,只要其中任何一个组件发生更改,将重新部署整个应用,而频繁的部署将增加服务宕机的风险,因此频繁地进行部署几乎不可能
- 扩展应用困难,单体应用只能从一个维度进行扩展,即很容易通过增加实例副本提供处理能力。另一方面,单体应用各个组件对资源的使用情况需求不同,一些是CPU密集型,另一些是内存密集型,但是不能独立地扩展单个组件
- 阻碍快速开发,随着公司业务的发展,单体服务框架变得更加庞大,更多的部门将会参与系统的开发,但是各个部门又不能独立开发、维护相应的模块,即使其中一个部门完成相应的更新,仍然不能上线,因此需要花费更多时间在部门间协调和统一。还有,需要增加新的功能时,单体应用最初的设计限制开发人员灵活选择开发语言、工具等,导致新功能上线慢
- 迫使开发人员长期专注于一种技术栈,由于单体应用本身设计的原因,后期引入新的技术栈需要遵循最开始的设计,因此存在非常大的局限性、挑战性,否则可能需要重写整个框架。
针对上面问题的出现,微服务架构应运而生,将单体应用拆分后由多个微服务构建的复杂系统,系统中各个微服务之间彼此通过网络进行通信,很好地解决了上述问题。而微服务中最大的挑战便是如何以标准化的方式管理微服务以及如何保证复杂网络环境中微服务间的可靠通信,确保整个系统的最大可用性,提供尽可能高的SLA。
当单体应用拆分为微服务后,新的通信模型如下:

微服务构
每个微服务由两部分构成:
- 业务逻辑:定义如何处理应用业务逻辑
- 网络功能:网络功能部分主要负责服务间的通信,包括上述列出的构建分布式高可用的技术实现,如超时、重试、服务发现、负载均衡等,由于它基于下层网络协议栈实现,因此被称作网络功能
此时相对于传统的单体应用,网络功能部分可以通过一个中心化的组件来统一实现或者直接嵌入到业务逻辑中,但是在微服务架构中,服务的粒度变得更小,为了实现它们之间的可靠通信,开发人员为每个微服务实现网络功能比实现业务逻辑花费的时间和精力可能更多。

传统微服务架构
从软件设计的角度,存在以下缺点:
- 耦合性很高,每个应用都需封装负载均衡、服务发现、安全通信以及分布式追踪等功能
- 灵活性差,复用率低下,不同的应用需要重复实现
- 管理复杂,当其中一项如负载均衡逻辑发生变化,需要更新所有服务
- 可运维性低,所有组件均封装在业务逻辑代码中,不能作为一个独立运维对象
- 对开发人员能力要求很高
随着不断发展,考虑将应用处理服务发现、负载均衡、分布式追踪、安全通信等设计为一个公用库,从而使得应用与这些功能具有更低的耦合性,而且更加灵活、提高利用率及运维性。

微服务新架构
而这种方案也存在不足之处:
- 如果将类似Finagle、 Proxygen或者Zipkin的库集成现有的系统中,仍然需要花费大量的时间、人力将其集成到现有生态圈,甚至需要调整现有应用的代码。
- 缺乏多语言支持,由于这些库只针对某种语言或者少数几种语言,这使得在一个多技术栈的公司中需要限制开发语言和工具的选择
- 虽然公共库作为一个独立的整体,但在管理复杂性和运维性这些方面仍然有更大的提升空间
- 公共库并不能完全使得开发人员只关注业务代码逻辑,仍然需要对公共库有很深的认识
针对上面面临的问题,发现了更好的解决方案,OSI定义了开放系统的层次结构、层次之间的相互关系以及各层所包括的可能的任务,上层并不需要对底层具体功能有详细的了解,只需按照定义的准则协调工作即可。因此,我们也可参照OSI七层模型将公用库设计为位于网络栈和应用业务逻辑之间的独立层,即透明网络代理,新的独立层完全从业务逻辑中抽离,作为独立的运行单元,与业务不再直接紧密关联。通过在独立层的透明网络代理上实现负载均衡、服务发现、熔断、运行时动态路由等功能,该透明代理在业界有一个非常新颖时髦的名字:Service Mesh。率先使用这个Buzzword的产品恐怕非Buoyant的Linkerd(https://linkerd.io/)莫属了,随后Lyft也发布了他们的Service Mesh实现Envoy(https://github.com/envoyproxy/envoy),之后Istio(https://istio.io/)也迎面赶上,成为Service Mesh领域非常热门的一个项目。

Service Mesh架构
在这种方案中,Service Mesh作为独立运行层,它很好地解决了上述所面临的挑战,使应用具备处理网络弹性逻辑和提供可靠交互请求的能力。它使得耦合性更低、灵活性更强,跟现有环境的集成时间和人力代价更小,也提供多语言支持、多协议支持,运维和管理成本更低。最主要的是开发人员只需关注业务代码逻辑,而不需要关注业务代码以外的其他功能,即Service Mesh对开发人员是透明的。
什么是Service Mesh
Service Mesh的发起人、先驱者,Buoyant公司的CEO William Morgan,他对Service Mesh的定义如下:
- 专用基础设施层:独立的运行单元
- 包括数据平面和控制平面:数据平面负责交付应用请求,控制平面控制服务如何通信
- 轻量级透明代理:实现形式为轻量级网络代理
- 处理服务间通信:主要目的是实现复杂网络中服务间通信
- 可靠地交付服务请求:提供网络弹性机制,确保可靠交付请求
- 与服务部署一起,但服务感知不到:尽管跟应用部署在一起,但对应用是透明的
Service Mesh架构如下,告诉Service Mesh控制层和数据层在微服务架构中所处位置、服务间通信模式以及提供的各种功能

Service Mesh控制层和数据层图
Service Mesh是一种用于处理微服务架构中服务间通信的基础设施层。它的主要功能是提供可靠的网络通信,并在服务间通信中实现负载均衡、流量管理、安全认证、监控和故障处理等功能。Service Mesh通过在应用程序中部署轻量级代理(通常称为Sidecar)来实现这些功能,这些代理负责拦截和处理服务之间的所有网络流量。
Service Mesh的核心组件
Service Mesh的架构通常包括以下几个核心组件:
-
数据平面(Data Plane):
-
Sidecar Proxy:每个服务实例旁边运行的代理,负责拦截出入的网络流量并执行流量管理、安全策略等操作。常见的Sidecar Proxy包括Envoy、Linkerd-proxy等。
-
Service Proxy:在某些实现中,代理可能直接嵌入到服务实例中,作为服务的一部分运行。
-
-
控制平面(Control Plane):
-
配置管理:提供统一的配置管理接口,用于下发和管理数据平面的配置。常见的控制平面包括Istio的Pilot、Linkerd的Controller等。
-
服务发现:管理服务注册和发现,确保代理能够正确路由流量。
-
策略管理:用于定义和下发流量管理、安全认证、访问控制等策略。
-
可观察性组件:负责收集和聚合服务网格中的监控数据、日志和追踪信息,提供可视化和报警功能。
-
Service Mesh的工作原理

Service Mesh通过在每个服务实例旁边部署Sidecar Proxy,实现了对服务间通信的透明代理。这些代理负责拦截出入的所有流量,并根据控制平面下发的配置和策略执行相应的操作。具体工作原理如下:
-
服务发现:
-
当一个服务实例启动时,它会向服务注册中心注册自己的信息。控制平面负责管理这些服务实例信息,并将更新的服务列表分发给所有Sidecar Proxy。
-
-
流量管理:
-
当一个服务需要与另一个服务通信时,流量首先经过本地的Sidecar Proxy。代理根据配置的路由规则和负载均衡策略,将流量转发到目标服务实例。
-
控制平面可以动态更新这些路由规则,实现蓝绿部署、金丝雀发布等高级流量管理功能。
-
-
安全认证:
-
Service Mesh可以在服务间通信中引入双向TLS加密,确保数据在传输过程中不被篡改和窃听。控制平面负责管理和分发证书,Sidecar Proxy在通信过程中进行加密和解密操作。
-
通过引入身份认证和访问控制策略,可以细粒度地控制哪些服务可以访问其他服务。
-
-
可观察性:
-
Service Mesh中的代理会收集每个请求的日志、监控数据和追踪信息,并将这些数据发送到可观察性组件进行处理和存储。
-
运维人员可以通过控制平面提供的接口和仪表盘,实时监控服务间的流量情况、延迟、错误率等指标,并进行故障排查和性能优化。
-
常见Service Mesh框架介绍
目前市场上有多种Service Mesh框架,每种框架在功能、性能和易用性上都有不同的特点。以下是几个常见的Service Mesh框架:
-
Istio:
-
概述:Istio是目前最流行的Service Mesh框架之一,具有丰富的功能和广泛的社区支持。它采用Envoy作为数据平面代理,并提供了强大的控制平面组件(Pilot、Mixer、Citadel等)。
-
特点:支持复杂的流量管理、强大的安全特性和丰富的可观察性功能。
-
应用场景:适用于需要复杂流量控制和高级安全特性的企业级应用。
-
架构图:

-
-
Linkerd:
-
概述:Linkerd是一个轻量级的Service Mesh框架,专注于简单易用和性能优化。它最初由Buoyant开发,使用Linkerd2时采用了Rust编写的轻量级代理(Linkerd2-proxy)。
-
特点:安装和配置简单,性能高效,适合资源受限的环境。
-
应用场景:适用于需要快速部署和高性能的微服务架构。
-
-
Consul Connect:
-
概述:Consul Connect是HashiCorp的Service Mesh解决方案,集成了Consul的服务发现和健康检查功能。它使用Envoy作为数据平面代理,并提供了内置的服务网格功能。
-
特点:与Consul的无缝集成,提供了强大的服务发现和健康检查功能。
-
应用场景:适用于已经使用Consul进行服务发现的环境。
-
二、ServiceMesh核心技术
服务发现与负载均衡
服务发现
服务发现是Service Mesh的基本功能之一,用于识别和跟踪微服务实例的地址和状态。服务发现机制主要包括以下两种方式:
-
客户端服务发现:
-
原理:客户端负责向服务注册中心查询目标服务实例的地址,并直接与这些实例进行通信。
-
优点:实现简单,适合小规模部署。
-
缺点:客户端需要处理服务注册和实例健康检查逻辑,增加了复杂性。
-
-
服务端服务发现:
-
原理:服务端代理(如Sidecar Proxy)负责与服务注册中心通信,客户端只需将请求发送到代理,代理根据查询到的服务实例信息进行转发。
-
优点:客户端无需关心服务发现的细节,简化了应用程序逻辑。
-
缺点:依赖服务端代理的高可用性和性能。
-
常见的服务发现工具包括Consul、Eureka和Kubernetes的内置服务发现机制。Service Mesh通常采用服务端服务发现方式,通过控制平面与这些工具集成,动态更新Sidecar Proxy的路由表。
负载均衡
负载均衡是优化服务间流量分配、提高系统整体性能的重要机制。Service Mesh提供了多种负载均衡策略,包括:
-
轮询(Round Robin):
-
原理:按照固定顺序轮流将请求分配给可用的服务实例。
-
优点:实现简单,分配均匀。
-
缺点:不考虑服务实例的性能和负载情况。
-
-
随机(Random):
-
原理:随机选择一个可用的服务实例处理请求。
-
优点:实现简单,避免热点问题。
-
缺点:同样不考虑服务实例的性能和负载。
-
-
最少连接(Least Connections):
-
原理:将请求分配给当前连接数最少的服务实例。
-
优点:能够较均匀地分配负载。
-
缺点:需要实时监控和更新连接数,增加系统开销。
-
-
加权轮询(Weighted Round Robin):
-
原理:根据服务实例的权重分配请求,权重越高分配的请求越多。
-
优点:可以根据服务实例的性能和资源分配请求。
-
缺点:权重设置和调整较复杂。
-
-
哈希一致性(Consistent Hashing):
-
原理:基于请求的特定属性(如客户端IP)计算哈希值,并将请求分配给对应的服务实例。
-
优点:保证同一属性的请求总是分配到同一实例,适合缓存场景。
-
缺点:对负载均衡不均匀的情况可能不适用。
-
断路器与熔断机制
断路器(Circuit Breaker)和熔断机制(Fallback Mechanism)是保障系统稳定性和容错能力的关键技术。
断路器
断路器用于检测和应对服务调用失败,防止连锁故障导致系统崩溃。它的工作机制如下:
-
关闭状态(Closed):
-
行为:正常转发请求。
-
监控:统计请求的成功和失败率。
-
-
打开状态(Open):
-
行为:直接拒绝请求,返回错误响应。
-
触发:当失败率超过预设阈值,断路器进入打开状态。
-
-
半开状态(Half-Open):
-
行为:允许少量请求通过,监控其结果。
-
恢复:如果这些请求成功率高,断路器恢复到关闭状态;否则,重新进入打开状态。
-
通过断路器机制,可以在服务故障时快速响应,避免进一步的资源浪费和系统崩溃。
熔断机制
熔断机制是在断路器触发时,提供备用路径或降级服务以保证系统的基本功能。常见的熔断策略包括:
-
静态熔断:
-
原理:在配置文件中预定义熔断策略,当断路器触发时执行。
-
优点:实现简单,适用于固定的应急处理。
-
-
动态熔断:
-
原理:根据实时监控数据动态调整熔断策略。
-
优点:更灵活,能够根据实际情况进行调整。
-
缺点:实现复杂,需要高质量的监控数据和分析能力。
-
数据平面与控制平面
数据平面
数据平面负责处理服务间的实际网络流量,执行负载均衡、路由、断路器、熔断等操作。主要组件包括:
-
Sidecar Proxy:如Envoy、Linkerd-proxy,负责拦截和处理服务间的流量。
-
Ingress/Egress Gateway:用于处理外部流量的入口和出口,控制服务与外部系统之间的通信。
数据平面的关键特性:
-
低延迟和高吞吐量:确保流量处理的效率和性能。
-
可编程性:支持动态配置和策略调整。
-
安全性:支持TLS加密、身份认证和访问控制。
控制平面
控制平面负责管理和配置数据平面,提供统一的接口和管理功能。主要组件包括:
-
配置管理:负责下发和管理数据平面的配置,如Istio的Pilot。
-
策略管理:定义和下发流量管理、安全认证、访问控制等策略。
-
服务发现:管理服务注册和发现,如Consul、Eureka。
-
可观察性组件:收集和聚合监控数据、日志和追踪信息,如Prometheus、Jaeger。
控制平面的关键特性:
-
集中管理:提供统一的配置和管理接口,简化运维操作。
-
动态调整:支持实时配置和策略调整,适应快速变化的业务需求。
-
高可用性和扩展性:确保控制平面自身的稳定性和可扩展性,避免成为单点故障。
相关文章:
科普文:微服务之服务网格Service Mesh
一、ServiceMesh概念 背景 随着业务的发展,传统单体应用的问题越来越严重: 单体应用代码库庞大,不易于理解和修改持续部署困难,由于单体应用各组件间依赖性强,只要其中任何一个组件发生更改,将重新部署整…...
第四十九章 解决 IRIS 中的 SOAP 问题 - 发送消息时出现问题
文章目录 第四十九章 解决 IRIS 中的 SOAP 问题 - 发送消息时出现问题 第四十九章 解决 IRIS 中的 SOAP 问题 - 发送消息时出现问题 如果在向 IRIS Web 服务或客户端发送或接收 SOAP 消息时遇到问题,请考虑以下常见场景列表: SOAP 消息可能包含极长的字…...
STM32-HAL-FATFS(文件系统)(没做完,stm32f103zet6(有大佬的可以在评论区说一下次板子为什么挂载失败了))
1STM32Cube配置 1-1配置时钟 1-2配置调试端口 1-3配置uart 1-4配置SDIO(注意参数)(其中他的初始化的异常函数给注释,SD卡文件写了) 配置了还要打开中断和DMA可在我的其他文章中看一样的 1-5配置FatFs (只改了图选中…...
线性代数基础概念:矩阵
目录 线性代数基础概念:矩阵 1. 矩阵的定义 2. 矩阵的运算 3. 矩阵的特殊类型 4. 矩阵的秩 5. 矩阵的初等变换 6. 矩阵的特征值与特征向量 7. 矩阵的应用 8. 矩阵总结 总结 线性代数基础概念:矩阵 矩阵是线性代数中的另一个重要概念࿰…...
【优化论】约束优化算法
约束优化算法是一类专门处理目标函数在存在约束条件下求解最优解的方法。为了更好地理解约束优化算法,我们需要了解一些核心概念和基本方法。 约束优化的核心概念 可行域(Feasible Region): 比喻:想象你在一个园艺场…...
7寸微型FPV无人机技术详解
对于7寸微型FPV(First Person View,第一人称视角)无人机技术的详解,可以从以下几个方面进行介绍: 一、定义与基本概念 FPV无人机,全称为“第一人称视角无人机”,它利用安装在无人机上的摄像头…...
大数据面试题之Presto[Trino](2)
目录 描述Presto中的Connector是什么? Presto如何实现数据源的插件化? 如何在单机上安装Presto? 描述在集群环境中部署Presto的步骤。 如何为Presto配置JVM参数? 如何优化Presto的配置以提高性能? Presto的日…...
STM32和DHT11使用显示温湿度度(代码理解)+单总线协议
基于STM32CT,利用DHT11采集温湿度数据,在OLED上显示。一定要阅读DHT11数据手册。 1、 DHT11温湿度传感器 引脚说明 1、VDD 供电3.3~5.5V DC 2、DATA 串行数据,单总线 3、NC 空脚 4、GND 接地,电源负极 硬件电路 微…...
EVM-MLIR:以MLIR编写的EVM
1. 引言 EVM_MLIR: 以MLIR编写的EVM。 开源代码实现见: https://github.com/lambdaclass/evm_mlir(Rust) 为使用MLIR和LLVM,将EVM-bytecode,转换为,machine-bytecode。LambdaClass团队在2周…...
深入Django(八)
掌握Django的管理后台 引言 在前七天的教程中,我们介绍了Django的基础架构、模型、视图、模板、URL路由、表单系统以及数据库迁移。今天,我们将深入了解Django的管理后台,这是一个功能强大的内置管理界面,用于创建、更新、查看和…...
华为开发者大会2024纪要:鸿蒙OS的全新篇章与AI大模型的革命
华为开发者大会2024纪要:鸿蒙OS的全新篇章与AI大模型的革命 在科技的浪潮中,华为再次引领潮流,2024年的开发者大会带来了一系列令人瞩目的创新成果。从鸿蒙操作系统的全新Beta版到盘古大模型的震撼发布,华为正以前所未有的速度重塑智能生态。以下是本次大会的亮点,让我们…...
吴恩达深度学习笔记:机器学习策略(2)(ML Strategy (2)) 2.7-2.8
目录 第三门课 结构化机器学习项目(Structuring Machine Learning Projects)第二周:机器学习策略(2)(ML Strategy (2))2.7 迁移学习(Transfer learning) 第三门课 结构化机器学习项目࿰…...
云计算渲染时代:选择Blender或KeyShot进行高效渲染
在云渲染技术日益成熟的背景下,挑选一款贴合项目需求的3D渲染软件显得尤为关键。当前,Blender与KeyShot作为业界领先的全能渲染解决方案,广受推崇。它们虽皆能创造出令人信服的逼真视觉效果,但在特色功能上各有所长。本篇文章旨在…...
html5中的iframe
HTML5中的iframe 浏览上下文是浏览器展示文档的环境,通常是一个tab标签页,一个窗体或者是浏览器页面的一部分。每个浏览上下文都有一个活动文档的源和一个记录所有展示文档的有序历史。浏览上下文的通讯被严格限制,只有两个同源的浏览器上下…...
海睿思问数(TableGPT):开创企业新一代指标应用模式
1 指标建设对企业经营管理数字化的价值分析 指标是将海量数据中关键信息提炼和挖掘出来,以数据为载体展示企业经营管理和分析中的统计量。它通过分析数据,形成一个具有度量值的汇总结果,使得业务状态可以被描述、量化和分解。指标通常由度量…...
LM-Cocktail:一种创新的模型合并方法打破预训练语言模型微调后的性能局限,实现语言模型在一般任务与特定领域的均衡高性能
LM-Cocktail:一种创新的模型合并方法打破预训练语言模型微调后的性能局限,实现语言模型在一般任务与特定领域的均衡高性能 使语言模型的微调类似于调制一杯精致的鸡尾酒。模型合并可用于提高单个模型的性能。我们发现此方法对于大型语言模型和密集嵌入模型也很有用,并设计了…...
默认导出(default)和命名导出
1.默认导出 优点: 简洁的导入语法: 导入时不需要使用花括号,可以直接重命名。单一职责: 模块导出一个主要功能或对象时,默认导出更符合逻辑。 适用场景: 模块只有一个导出: 如一个组件、一个…...
开发个人Go-ChatGPT--1 项目介绍
开发个人Go-ChatGPT--1 项目介绍 开发个人Go-ChatGPT--1 项目介绍知识点大纲文章目录项目地址 开发个人Go-ChatGPT–1 项目介绍 本文将以一个使用Ollama部署的ChatGPT为背景,主要还是介绍和学习使用 go-zero 框架,开发个人Go-ChatGPT的服务器后端&#…...
皮卡超级壁纸 | 幸运壁纸幸运壁纸app是一款涵盖了热门影视剧、动漫、风景等等资源的装饰工具,
软件下载链接:壁纸下载方式在链接中文章底部 皮卡超级壁纸 皮卡超级壁纸是一款专为手机用户设计的壁纸应用,它提供了丰富多样的高清壁纸资源,让用户的手机界面焕然一新。这款应用以其海量的壁纸库和用户友好的操作界面,在市场上…...
普通集群与镜像集群配置
目录 一. 环境准备 二. 开始配置集群 三. RabbitMQ镜像集群配置 四. 安装并配置负载均衡器HA 一. 环境准备 关闭防火墙和selinux,进行时间同步 主机名系统IP服务rabbitmq-1 Rocky_linux9.4 192.168.226.22RabbitMQ,MySQLrabbitmq-2Rocky_linux9.41…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...
Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...
UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...
让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...
scikit-learn机器学习
# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...
