当前位置: 首页 > news >正文

istio in action之应用弹性与容错机制

在分布式系统中,服务间的依赖关系就像一张错综复杂的网络,任何一个节点的抖动都可能引发连锁反应。这也是为什么我们需要强调弹性,因为在分布式系统中,服务之间通过网络进行通信,这本身就引入了无数个潜在的失败点。我们必须让服务从一开始就具备“容错”的意识,能够主动感知并尝试恢复,而不是被动等待。

例如A服务访问B服务,可能的错误有

  • 延迟,服务B响应慢
  • 错误,比如服务B暂时挂了,或者返回了500错误
  • 网络分区,导致服务A根本无法访问到服务B
  • 雪崩效应,服务A持续不断地请求一个出问题的服务B,它不仅自己会被拖累,还可能把请求堆积如山,最终导致服务B彻底崩溃,甚至影响到其他依赖服务B的服务。

在 Istio 这样的服务网格技术普及之前,我们通常需要在应用代码里自己写这些弹性逻辑。比如,Twitter 的 Finagle,Netflix 的 Hystrix 和 Ribbon,它们在 Java 社区非常流行,提供了超时、重试、熔断等能力。但这种方式有几个痛点:

  • 第一,侵入性太强,业务逻辑里掺杂着大量的网络处理代码;
  • 第二,维护成本高,不同的语言、不同的框架,可能需要维护不同的库版本,打补丁、做功能对齐,简直是噩梦;
  • 第三,一致性差,不同团队可能用不同的库,或者即使用了同一个库,配置也可能千差万别,很难保证全局的弹性策略是一致的。

那么,Istio 是如何解决这些问题的呢?它的核心理念是将这些共性的、基础的弹性能力,从应用代码中解放出来,放到服务网格层面去统一管理。这意味着什么呢?意味着我们可以为所有服务,无论用什么语言、什么框架写的,都提供一套一致的、可配置的弹性策略。而且,这一切都是通过配置来实现的,不需要修改任何一行应用代码。这背后的功臣就是 Istio 的 Sidecar 代理,部署在每个服务实例旁边,负责处理所有进出服务的网络流量。由于代理理解 HTTP、HTTPS 这些应用层协议,它就能在这些层面实现各种弹性机制,比如超时、重试、熔断等等。这大大降低了复杂性,提高了整体的可靠性。

在这里插入图片描述

这张图更直观地展示了 Istio 如何介入服务间的通信。服务A和B之间,不再是直接连接,而是各自通过一个 Sidecar Proxy 连接。所有的请求都必须先经过自己的代理,再经过对方的代理。代理不仅能处理网络层面的流量,还能理解应用层的请求,比如 HTTP 请求。这样,Istio 就可以在代理层面,非常灵活地实现各种弹性策略,比如当请求超时了,或者返回了特定的错误码,代理就可以自动进行重试,或者在多次失败后,将后续请求熔断,避免雪崩。

传统的中心化方案,比如昂贵的硬件负载均衡器,或者复杂的 ESB,它们往往成为新的瓶颈和单点故障。而 Istio 的 Sidecar 代理模式,天然地就是分布式的。每个请求的处理路径都分散在各个服务实例旁边,没有一个中央的控制点。这使得系统更加健壮,能够更好地适应云环境的动态伸缩和弹性变化。

负载均衡

我们接下来的示例,就是用 simple-web 服务来调用一个名为 simple backend 的服务,通过 Istio 的代理来实现客户端负载均衡。

在这里插入图片描述

客户端负载均衡就是让发起请求的客户端(比如我们的 simple-web 服务)自己去决定把请求发给哪个后端服务实例(比如 simple backend 的多个副本)。这和传统的服务器端负载均衡,比如 Nginx 或者硬件负载均衡器,把所有流量都导向一个中心点,然后由它决定转发到哪里,是完全不同的思路。客户端负载均衡的好处显而易见

  • 避免了中心化设备带来的潜在瓶颈和故障点,让客户端可以直接连接到目标服务,减少延迟
  • 更好地适应服务实例的动态变化

在 Istio 中,我们可以通过配置 DestinationRule 来定义客户端应该使用哪种负载均衡策略。Istio 基于强大的 Envoy 代理,提供了多种负载均衡策略。

  • 默认的 ROUND_ROBIN,也就是轮询,简单粗暴地依次请求后端的每个实例
  • RANDOM,随机选择
  • WEIGHTED_LEAST_REQUEST,它会根据后端实例当前活跃的请求数量来决定把请求发给谁。哪个实例当前处理请求的压力最小,就优先发给它

我们可以通过修改 DestinationRule 的 spec.trafficPolicy.loadBalancer.simple 字段来切换这些策略。

刚才我们提到了,ROUND_ROBIN 和 RANDOM 这种简单的策略,不考虑后端实例的实时状态。但在实际生产环境中,服务的响应时间是波动的,这是正常的。可能是因为请求本身复杂,或者数据库查询慢,或者它调用了其他慢服务。更糟糕的是,还可能遇到突发状况,比如 JVM 的 Full GC,或者 CPU 资源竞争激烈,或者网络突然拥塞。这些都会导致某个后端实例突然变得非常慢。如果我们还用简单的轮询,那大部分请求可能就会被不幸地分配给那个慢实例,导致整体性能下降。这时候,负载均衡的作用就体现出来了,它可以帮助我们分散请求,避免被个别慢实例拖累。

部署backend

$ kubectl get pod
NAME READY STATUS RESTARTS AGE
simple-backend-1-54856d64fc-59dz2 2/2 Running 0 29h
simple-backend-2-64f898c7fc-bt4x4 2/2 Running 0 29h
simple-backend-2-64f898c7fc-kx88m 2/2 Running 0 29h
simple-web-56d955b6f5-7nflr 2/2 Running 0 29h

设置负载均衡策略

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:name: simple-backend-dr
spec:host: simple-backend.istioinaction.svc.cluster.localtrafficPolicy:loadBalancer:simple: ROUND_ROBIN

为了更直观地看到这一点,我们接下来会用一个负载测试工具 Fortio 来模拟这种情况。现在,我们来做一个实验。

  1. 部署一个特殊的 simple-backend-1,它会故意让响应延迟增加到 1 秒,模拟一个性能变差的实例
  2. 然后我们用 Fortio 这个工具,模拟一个高负载场景,每秒发送 1000 个请求,持续 60 秒,用 10 个并发连接。
kubectl -n default run fortio --image=fortio/fortio:1.6.8 \
--restart='Never' -- load -H "Host: simple-web.istioinaction.io" \
-jitter -t 60s -c 10 -qps 1000 \
http://istio-ingressgateway.istio-system/

我们会分别测试三种负载均衡策略:ROUND_ROBIN、RANDOM 和 LEAST_CONN。Fortio 会记录下每个请求的响应时间,并生成直方图和百分位数报告。我们重点关注 p99 和 p99.9 这些高百分位数,它们代表了绝大多数请求的最坏情况延迟。通过比较这三种策略的结果,就能看出哪种策略在面对这种延迟抖动时表现更好。我们来看一下测试结果。

在这里插入图片描述

对比三种策略的 p50、p75、p90、p99 和 p99.9 这些关键指标。p50 是中位数,p99 是 99% 的请求的响应时间,p99.9 是 99.9% 的请求的响应时间。可以看到,

  1. ROUND_ROBIN 和 RANDOM 的 p50 延迟差不多,都在 180 到 190 毫秒左右,但它们的 p99 和 p99.9 延迟都超过了 1000 毫秒,这意味着有相当一部分请求会因为被分配到那个延迟 1 秒的实例而变得非常慢。
  2. LEAST_CONN 策略,虽然 p50 和 p75 的延迟略低,但它的 p90、p99 和 p99.9 延迟也超过了 1000 毫秒。这说明即使是最少连接策略,也无法完全避免偶尔被分配到那个慢实例。
  3. 从整体上看,这三种策略在面对这种极端情况时,表现都不是很理想

位置感知(Locality aware)负载均衡

这引出了一个问题:我们能不能更智能地处理这种情况呢?除了考虑负载均衡算法,我们还可以利用地理位置信息来优化路由。这就是所谓的位置感知负载均衡。它的核心思想是,如果一个服务在 us west 区域,它调用的另一个服务,如果也部署在 us west 区域,那么优先选择同一个区域内的服务实例,特别是同一个可用区的。这样做的好处是显而易见的:减少网络传输距离,降低延迟,同时也能节省跨区域或跨可用区的网络带宽成本。Istio 也支持这种能力,我们可以通过配置 DestinationRule 的 localityLbSetting 来实现。它会优先考虑同区域、同可用区的服务,然后才是更远的区域。

在这里插入图片描述

这张图就展示了这个概念,simple-web 在 us-west-1a,它优先调用也在 us-west-1a 的 simple-backend-1。为了演示位置感知,我们手动给服务打上了 istio locality 标签,模拟它们在不同地域和可用区的情况。

apiVersion: apps/v1
kind: Deployment
metadata:labels:app: simple-webname: simple-web
spec:replicas: 1selector:matchLabels:app: simple-webtemplate:metadata:labels:app: simple-webistio-locality: us-west1.us-west1-aspec:serviceAccountName: simple-webcontainers:- image: nicholasjackson/fake-service:v0.14.1imagePullPolicy: IfNotPresentname: simple-webports:- containerPort: 8080name: httpprotocol: TCPsecurityContext:privileged: false

比如,simple-web 和 simple-backend-1 都标记为 istio-locality: us-west1.us-west1-a,表示它们在同一个可用区;而 simple-backend-2 标记为 us-west1-b,表示在另一个可用区。Istio 会读取这些标签信息。在默认情况下,它会优先把流量路由到本地的可用区。

Istio’s ability to load balance across locality includes region, zone and even a more fine-grained “subzone”

Istio’s locality-aware load balancing is enabled by default. If you wish to disable it, you can configure the meshConfig.localityLbSetting.enabled setting to be false

也就是说,我们期望的流量路径应该是 simple-web 到 simple-backend-1,因为它们都在 us-west1-a。只有当 simple-backend-1 出现问题时,才会考虑路由到 simple-backend-2。但是,仅仅优先本地还不够。如果本地的可用区,比如 us-west1-a,里的所有服务都挂了,或者都变得非常慢,我们总不能一直傻等吧?这时候就需要健康检查机制了。

在实际的测试中会发现,即使配置了位置感知负载均衡,来自web的请求仍旧会倍转发到backend2。因为位置感知负载均衡想要生效需要开启健康检查。如果没有开启健康检查,Istio 就不知道负载均衡池中的哪些端点是不健康的,以及应该使用什么启发式方法来spill over到下一个地域。

异常值检测

Istio 提供了一个叫做 Outlier Detection,也就是异常值检测的功能。它可以让 Istio 代理被动地监控后端服务的响应,如果发现某个服务实例连续返回了错误,比如连续 5xx 错误,超过了我们设定的阈值,比如 consecutiveErrors:1,那么代理就会认为这个实例是不健康的。然后,它会把这个不健康的实例暂时从负载均衡池里移除,不再把新请求发给它。这样,即使本地最优路径的实例出了问题,流量也会自动切换到其他可用区的健康实例,比如 us-west1-b 的 simple-backend-2。这大大增强了系统的容错能力。

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:name: simple-backend-dr
spec:host: simple-backend.istioinaction.svc.cluster.localtrafficPolicy:connectionPool:http:http2MaxRequests: 10maxRequestsPerConnection: 10outlierDetection:consecutiveErrors: 1interval: 1mbaseEjectionTime: 30s

我们来实际看看这个效果。假设我们配置了一个带有 outlierDetection 的 DestinationRule,比如 consecutiveErrors 设为 1。现在,我们让本地的 simple-backend-1 故意返回 500 错误。由于 Istio 的 outlier detection 监控到了这个错误,它会迅速将 simple-backend-1 标记为不健康。这时,即使我们继续 curl 请求,你会发现,返回的响应已经来自 simple-backend-2,也就是那个不在本地可用区的实例了。这说明,当本地的最优服务实例出现故障时,Istio 能够自动切换到健康的、可能稍远的实例,保证了服务的可用性。当然,outlier detection 是被动的,它需要我们根据实际场景配置合适的阈值,比如连续多少个错误才判定为异常。

高级应用弹性

当然,Istio 的弹性能力远不止于此,它还提供了强大的超时、重试、熔断等机制。

超时(timeout)

我们先来看第一个关键机制:超时。简单说,就是给请求设定一个耐心等待的上限。你不能无限期地等待一个请求,否则你的资源比如线程、连接池就会被耗尽,最终导致整个系统瘫痪。Istio 提供了三种主要的超时类型:

  • 连接超时,建立连接超时;
  • 空闲超时,连接建立起来了,但长时间没反应,也得断开;
  • 请求超时,请求发出去了,但响应迟迟不来,也得有个限度。

默认情况下,Istio 不会自动设置这些超时,你需要根据实际情况,比如服务的响应时间、网络状况等,来合理配置。这一步非常重要,是防止请求无限期挂起的第一道防线。

重试(retry)

网络世界充满了不确定性,有时候请求会失败,但可能只是短暂的网络抖动,或者服务端只是暂时过载。这时候,如果我们能给请求一次机会,重新发送一次,往往就能成功。重试机制能显著提高用户体验,避免因为一次偶然的失败而让用户感到沮丧。但是,凡事都有两面性。如果重试策略不当,比如对所有错误都盲目重试,或者重试次数过多,那就会变成灾难。这会导致系统压力越来越大,最终崩溃。所以,重试是个好东西,但用得好不好,直接关系到系统的稳定性和性能。我们需要找到一个平衡点。

那么,Istio 默认是怎么处理重试的呢?默认情况下是开启重试的,并且通常会尝试重试两次。但是,它不是对所有错误都重试,而是有选择性地进行重试。它会关注一些特定的错误场景,比如:

  • connect-failure
  • refused-stream
  • unavailable (grpc status code 14)
  • cancelled (grpc status code 1)
  • retriable-status-codes (default to HTTP 503 in istio)

默认情况下,HTTP 503 服务不可用 就是其中一个可恢复状态码。这意味着,如果后端服务返回 503,Istio 会认为这可能是暂时的,于是会尝试重试。这种默认的、有限的重试机制,能在一定程度上提升系统的健壮性,同时避免过度重试带来的风险。

当然,Istio 的默认行为只是起点,我们完全可以根据实际需求来定制重试策略。这主要通过 VirtualService 资源来实现。

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: simple-backend-vs
spec:hosts:- simple-backendhttp:- route:- destination:host: simple-backendretries:attempts: 2 retryOn: gateway-error,connect-failure,retriable-4xx perTryTimeout: 300ms retryRemoteLocalities: true 

我们可以精确控制很多方面:

  • 重试几次?在哪些错误情况下才重试?
  • 只重试 5xx 错误,还是也包括 4xx 客户端错误?还是只重试连接失败?可以通过 retryOn 参数来指定。
  • 每次重试之间,你希望等待多久?默认是 300毫秒,也可以调整。
  • 是否允许重试到其他区域的副本,这在跨地域部署时很有用。

通过这些灵活的配置,我们可以根据不同的服务和场景,设计出最合适的重试策略。我们来看一个具体的例子。

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: simple-backend-vs
spec:hosts:- simple-backendhttp:- route:- destination:host: simple-backendretries:attempts: 2retryOn: "5xx"

假设我们有一个服务,它偶尔会因为内部原因返回 500 Internal Server Error。我们知道,默认的重试策略是不包含 500 错误的。如果我们直接用默认配置,那请求失败后,Istio 就不会再尝试重试了,错误会直接传递给客户端。这显然不是我们想要的。如果 500 错误是暂时的,比如数据库连接暂时中断,那重试是有意义的。所以,我们可以在 VirtualService 的配置里,把 retryOn 参数改成 5xx。

一些重试功能考虑了一些不容易更改的默认值,比如退避重试时间或默认可重试的状态码。默认情况下,退避时间是 25 毫秒,可重试的代码仅限于 HTTP 503。但是我们可以使用 EnvoyFilter 直接操作底层的 Envoy 配置,设置 circuit_breakers 下的 retry_budget,来更精细地控制总的重试请求数量,或者按百分比来限制。这样,即使在高负载下,重试也能保持在一个可控的范围内,避免对系统造成更大的冲击。

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:name: simple-backend-retry-status-codesnamespace: istioinaction
spec:workloadSelector:labels:app: simple-webconfigPatches:- applyTo: HTTP_ROUTEmatch:context: SIDECAR_OUTBOUNDrouteConfiguration:vhost:name: "simple-backend.istioinaction.svc.cluster.local:80"patch:operation: MERGEvalue:route:retry_policy:retry_back_off:base_interval: 50msretriable_status_codes:- 402- 403

除了基本的重试次数和条件,我们还需要考虑更高级的特性,如果我们不加思考地进行简单的重试,并且不考虑分层重试,可能会使我们的系统严重过载。我们应该考虑通过固定数量或至少通过总请求数的一定比例来限制重试次数。

  • 固定请求数量,从而限制并行重试,通过DestinationRule来实现
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:name: simple-backend-dr
spec:host: simple-backend.istioinaction.svc.cluster.localtrafficPolicy:connectionPool:http:maxRetries: 3http2MaxRequests: 10maxRequestsPerConnection: 10
  • 重试预算就是用来限制这种并发压力的,通过EnvoyFilter API 来实现

还有一个复杂的特性叫做请求对冲(Request Hedging)。这通常也需要通过 EnvoyFilter 来配置。它的想法是这样的:如果一个请求在等待响应的时候超时了,Envoy 不会傻等,而是会立刻向另一个后端服务实例发送一个备份请求。这两个请求同时进行,就像赛跑一样,看谁先返回结果。如果备份请求先成功了,那么结果就给原始的客户端;如果原始请求后来也成功了,但已经晚了,那结果就丢弃了。目的是为了在某些场景下,比如后端服务只是偶尔慢,但最终能成功的情况下,尽可能地缩短用户的等待时间。当然,代价是增加了额外的请求负载,可能会对后端服务造成额外的压力。所以,这是一个需要权衡的高级选项。

在这里插入图片描述

我们已经看到了重试的好处,但也要警惕它的潜在风险。最著名的就是Thundering Herd。想象一条服务链,A 调用 B,B 调用 C,C 调用 D,D 调用 E。如果 E 服务突然挂了,返回错误,那么 D 会重试,C 会重试 D 的请求,B 会重试 C 的请求,A 会重试 B 的请求。如果每层服务都配置了重试,一个请求可能最终变成 2 的 5 次方等于 32 个请求!所以,我们需要非常小心地设计重试策略。一种常见的做法是,只在系统的边缘,比如 API Gateway 或者客户端,进行重试,而内部服务则尽量不重试。或者,更精细地,根据服务的层级和重要性,设置不同的重试次数。当然,前面提到的重试预算也是解决这个问题的有效手段。

断路器(Circuit breaking )

如果说重试是试图修复问题,那么断路器就是承认问题并主动保护系统。它的核心思想是,当检测到某个服务表现异常时,比如响应时间过长、错误率过高,就暂时停止向这个服务发送请求。在服务网格里,断路器的作用就是防止一个不健康的服务拖垮整个系统。Istio 通过 DestinationRule 的 trafficPolicy 来实现这个功能。它提供了一种从快速失败的模式,而不是持续重试的模式。这在处理严重过载或已知故障的服务时非常有用。Istio 实现断路器主要有两种方式。

连接池控制(connection pool)

第一种是连接池控制(connection pool)。如果请求太猛,超过了池子的容量,就会被截断。在 Istio 里,我们通过 DestinationRule 的 connectionPool 参数来设置。

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:name: simple-backend-dr
spec:host: simple-backend.istioinaction.svc.cluster.localtrafficPolicy:connectionPool:tcp:maxConnections: 1 # the threshold at which we’ll report a connection "overflow".http:http1MaxPendingRequests: 1 # this setting is the allowable number of requests that are"pending" and don’t have a connection to usemaxRequestsPerConnection: 1 # queued requestsmaxRetries: 1http2MaxRequests: 1 # (unfortunately misnamed in Istio)this controls the max number of parallel requests across all endpoints/hosts in a cluster regardless of HTTP2 or HTTP1.1

比如,你可以限制最大连接数 tcp.maxConnections,或者限制每个连接上最多允许多少个待处理的请求 http.maxRequestsPerConnection。对于 HTTP 1.1,还有 http1MaxPendingRequests。对于 HTTP 2,有 http2MaxRequests,这个参数实际上控制的是所有主机的总并发请求数。一旦请求量超过了这些限制,Istio 就不会继续发送请求,而是会立即返回一个错误,比如 503 服务过载。我们可以通过查看 Envoy 的统计指标,来确认确实是连接池控制在起作用,而不是后端服务本身的问题

$ kubectl exec -it deploy/simple-web -c istio-proxy \
-- curl localhost:15000/stats | grep simple-backend | grep overflow
<omitted>.upstream_cx_overflow: 32
<omitted>.upstream_cx_pool_overflow: 0
<omitted>.upstream_rq_pending_overflow: 2
<omitted>.upstream_rq_retry_overflow: 0
异常点检测(outlier detection)

第二种是异常点检测(outlier detection)。如果我们向一个经常失败的服务发送请求,而构成该服务的其他端点没有失败,那么它可能过载或以某种方式降级了,我们最好在一段时间内停止向它发送流量。此时istio会主动移除服务中表现不佳的特定主机。

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:name: simple-backend-dr
spec:host: simple-backend.istioinaction.svc.cluster.localtrafficPolicy:outlierDetection:consecutive5xxErrors: 1interval: 5sbaseEjectionTime: 5smaxEjectionPercent: 100

以上配置,意味着异常检测在只有一个坏请求后就会触发。 interval 指定了服务代理检查的频率,并根据设置确定是否基于 consecutive5xxErrors 弹出端点。如果服务端点被弹出,它将被弹出 n * baseEjectionTime 时间,其中 n 是特定端点被移除的次数。在此时间过后,端点将被重新添加到负载均衡池中。我们可以通过maxEjectionPercent控制负载均衡池中最多有多少主机被移除。在这个特定的配置中,我们希望移除 100% 的主机,这将类似于断路器被打开,即当所有主机都表现不佳时,不会有请求通过。

相关文章:

istio in action之应用弹性与容错机制

在分布式系统中&#xff0c;服务间的依赖关系就像一张错综复杂的网络&#xff0c;任何一个节点的抖动都可能引发连锁反应。这也是为什么我们需要强调弹性&#xff0c;因为在分布式系统中&#xff0c;服务之间通过网络进行通信&#xff0c;这本身就引入了无数个潜在的失败点。我…...

将PyQt5设计的程序打包成.exe文件

打包教程 因为打包的机制是会把当前的解释器的包也打包上&#xff0c;而我的环境经常会有一些较大的包&#xff0c;比如torch之类的。所以这里会创建一个单独的环境。 conda create -n image_process python3.8 激活环境 conda activate image_process 现在先安装我需要安装…...

Java原生结合MQTTX---完成心跳对话(附带源码)

简言&#xff1a;✨当Java遇上MQTT&#xff1a;打造会"隔空传话"的魔法程序✨ 导语&#xff1a;想不想让两个Java程序像哈利波特里的双面镜一样实时对话&#xff1f;今天我们将用MQTT协议EMQX&#xff0c;在Ubuntu上搭建一个魔法邮局&#xff0c;再亲手编写会传信的…...

redis数据结构-06(LRANGE、LINDEX、LSET、LREM)

列表操作&#xff1a;LRANGE、LINDEX、LSET、LREM Redis 列表不仅仅是简单的数组&#xff1b;它们是一种强大的数据结构&#xff0c;可以高效地操作有序数据。本课将深入探讨使用 Redis 列表的四个基本命令&#xff1a; LRANGE 、 LINDEX 、 LSET 和 LREM 。掌握这些命令将使您…...

4.4 os模块

os模块&#xff1a; chdir:修改工作路径 --- 文件所在位置的标识 getcwd():返回当前路径&#xff0c;如果修改了则显示修改后的路径 curdir:获取当前目录的表示形式 cpu_count():返回当前cpu的线程数 getppid(): 获取当前进程编号 getppid()&#xff1a;获取当前进程的父进…...

在 Windows 系统上选择与部署 DICOM 医学影像开发工具与库

🧑 博主简介:CSDN博客专家、CSDN平台优质创作者,高级开发工程师,数学专业,10年以上C/C++, C#, Java等多种编程语言开发经验,拥有高级工程师证书;擅长C/C++、C#等开发语言,熟悉Java常用开发技术,能熟练应用常用数据库SQL server,Oracle,mysql,postgresql等进行开发应用…...

MYSQL数据库集群高可用和数据监控平台(详细版)

项目说明 概述 该项目共分为2个子项目&#xff0c;由MYSQL集群高可用和数据监控平台两部分组成 MYSQL集群高可用属于云原生高级课数据库运维部分的知识 数据监控平台属于云原生拔高项目&#xff0c;旨在让学生增加知识面&#xff0c;提高项目实习经历&#xff0c;充实简历 …...

学习通刷课稳定版(美化面板+完全免费)

学习通刷 &#xff08;美化面板完全免费&#xff09; 安装教程方法一源码文件 方法二 提示结尾 安装教程 方法一 我们首先在浏览器打开脚本猫网站并获取该插件&#xff08;浏览器以Edge为例&#xff09; 脚本猫首页&#xff1a;https://scriptcat.org/zh-CN/ 第一步&#xff…...

python 实现sha加密

在Python中&#xff0c;SHA&#xff08;Secure Hash Algorithm&#xff09;是一种加密哈希函数&#xff0c;通常用于生成数据的哈希值。SHA算法是单向的&#xff0c;这意味着它只能用于加密&#xff08;生成哈希值&#xff09;&#xff0c;而不能用于解密。因此&#xff0c;SHA…...

Linux epoll 详解:概念、使用、数据结构、流程及应用

epoll是什么&#xff1f; epoll 是从 Linux 2.6 起&#xff0c;Linux内核提供的一种高性能I/O事件通知机制&#xff0c;用于解决传统 select 和 poll 在处理大量并发连接时遍历、最大数量限制、频繁拷贝数据等问题。epoll 可以用来监听多个文件描述符&#xff08;socket、管道…...

Kubernetes排错(十一):lsof命令实战场景

在Kubernetes生产环境中&#xff0c;lsof作为Linux系统的"透视眼"&#xff0c;是排查容器级疑难杂症的必备工具。本文将深入解析其在容器化场景下的高阶用法&#xff0c;助你快速定位隐藏问题。 一、基础环境准备 1. 容器内安装lsof # 临时进入容器安装&#xff0…...

Java基础语法之循环结构

循环结构 1.定义 控制一段代码重复执行多次 2.分类 2.1 for循环 2.1.1 定义 控制一段代码反复执行很多次。 2.1.2 for循环格式 for (初始化语句; 循环条件; 迭代语句) { 循环体语句(重复执行的代码); }示例 // 输出3次HelloWorld for (int i 0; i < 3; i) { System…...

冒泡排序的原理

冒泡排序是一种简单的排序算法&#xff0c;它通过重复地遍历待排序的列表&#xff0c;比较相邻的元素并交换它们的位置来实现排序。具体原理如下&#xff1a; 冒泡排序的基本思想 冒泡排序的核心思想是通过相邻元素的比较和交换&#xff0c;将较大的元素逐步“冒泡”到列表的…...

AUTOSAR图解==>AUTOSAR_TR_InteractionWithBehavioralModels

AUTOSAR与行为模型交互详解 深入解析AUTOSAR软件组件与行为模型的交互关系与转换机制 目录 引言 1.1 AUTOSAR编辑工具概述 1.2 源起与目标 1.3 术语定义需求追溯AUTOSAR中行为建模的用例 3.1 软件组件的行为建模 3.2 软件组件描述到行为模型 3.3 行为模型到软件组件描述 3.4 组…...

GO语言内存管理结构

文章目录 1、内存分区1.1、栈&#xff08;Stack&#xff09;1.2、堆&#xff08;Heap&#xff09; 2、堆内存管理结构2.1、内存分配器&#xff08;MCache → MArena → MSpan → MHeap&#xff09;2.2、大小分类&#xff08;Size Class&#xff09;2.3、分配流程 3、垃圾回收&a…...

分享一些资料供大家学习

群里收集来的&#xff0c;自己感觉还是比较经典的&#xff0c;希望大家喜欢&#xff01;&#xff01;&#xff01; 20250428 夸克网盘分享一大波经典IT架构好货20250429夸克网盘分享精品文档-管理咨询师必备的思维模型20250430夸克网盘分享清华大学DeepSeek教程又来了《文科生A…...

RAGMCP基本原理说明和相关问题解惑

一、RAG架构原理和局限性 1.1 概念解释 RAG&#xff08;Retrieval-Augmented Generation&#xff09;&#xff1a;检索增强生成&#xff0c;让大模型接受外部输入后&#xff0c;总结输出 向量数据库&#xff1a;向量数据通常是高维空间中的点&#xff0c;代表复杂的数据结构…...

PyGame游戏开发(含源码+演示视频+开结题报告+设计文档)

前言&#xff1a; 大二小学期python课上基于pygame做的一个游戏小demo&#xff0c;当时老师花了一天讲解了下python基础语法后&#xff08;也是整个大学四年唯一学习python的时间&#xff09;&#xff0c;便让我们自学网课一周然后交项目&#xff0c;所以做的非常仓促&#xff…...

Git标签

Git标签 1. 添加标签 使用 tag 命令可以给某次 commit 提交的版本打上标签&#xff0c;相当于这个 commit id 的别名&#xff0c;在实践中&#xff0c;会使用 v1.0 之类的标签提示这是正式版的第一个版本。 git tag v1.0 [commit id]缺省输入 commit id会给最新的一次提交打…...

USB学习【6】USB传输错误的处理

1.前言 我们从物理层到信号层&#xff0c;到协议层&#xff0c;他们分别在不同的层面完成不同的功能。 总结一下&#xff1a; 物理层实现了高低电平的检测。 信号层更进一步&#xff0c;通过一些方法&#xff0c;实现了二进制的传输。 协议层&#xff0c;因为可以二进制传输了…...

深入解析 Vision Transformer (ViT) 与其在计算机视觉中的应用

在近年来&#xff0c;深度学习尤其在计算机视觉领域取得了巨大的进展&#xff0c;而 Vision Transformer&#xff08;ViT&#xff09;作为一种新的视觉模型&#xff0c;它的表现甚至在许多任务中超过了传统的卷积神经网络&#xff08;CNN&#xff09;&#xff0c;如 ResNet。在…...

《Go小技巧易错点100例》第三十一篇

本期分享&#xff1a; 1.Go struct内存对齐 2.使用空结构体(struct{})节省内存 Go struct内存对齐 在计算机系统中&#xff0c;CPU 访问内存时并不是逐字节读取的&#xff0c;而是以特定大小的块&#xff08;通常为 4/8 字节&#xff09;为单位进行读取。当数据的内存地址正…...

全栈项目实战:Vue3+Node.js开发博客系统

全栈项目实战&#xff1a;Vue3Node.js开发博客系统 一、项目架构设计 1. 技术栈选型 前端技术栈&#xff1a; Vue 3 Composition APITypeScriptPinia状态管理Vue Router 4Element Plus UI组件库Vite构建工具 后端技术栈&#xff1a; Node.js (Express/Koa)MongoDB (Mong…...

查看YOLO版本的三种方法

查看YOLO版本的三种方法&#xff1a; 一、通过命令行直接查询 使用Python交互式查询&#xff1a; from ultralytics import __version__ print(__version__) # 示例输出: 11.0.5二、检查PyTorch环境兼容性 import torch, ultralytics print(f"PyTorch: {torch.__versi…...

基于Docker的Bitwarden的私有本地部署

基于Docker的Bitwarden的私有本地部署 文章目录 基于Docker的Bitwarden的私有本地部署 本文首发地址 https://h89.cn/archives/355.html bitwarden 默认连接的是国外服务器 https://bitwarden.com/ &#xff0c;连接不是很稳定&#xff0c;也没有安全感&#xff0c;所以我选择了…...

点和体素哪个好

3D 深度学习中基于体素和基于点云的方法哪种更优&#xff1f;-腾讯云开发者社区-腾讯云 https://zhuanlan.zhihu.com/p/372497398 GitHub - open-mmlab/OpenPCDet: OpenPCDet Toolbox for LiDAR-based 3D Object Detection....

C++ STL编程 vector空间预留、vector高效删除、vector数据排序、vector代码练习

vector空间预留&#xff0c;作用是避免申请每次申请内存&#xff0c;提高运行效率。 对应的接口是 vector.reverse() vector的高效删除&#xff0c;对应的代码见下&#xff0c;一个时间复杂度是n&#xff0c;一个时间复杂度是1 #include<iostream> #include<vector…...

Android架构模式推荐及分析和MVC架构模式制作一个简单的底部tab切换

目录 主流架构模式对比 适用场景 MVP‌&#xff1a;团队协作开发,需要高可测试性的项目 MVC架构模式制作一个简单的底部tab切换 &#xff08;Model-View-Controller&#xff09;结构 代码 效果 主流架构模式对比 ‌对比维度‌‌MVC‌ ‌MVP‌ ‌MVVM‌ ‌MVI‌ ‌学习…...

【PVE】ProxmoxVE8虚拟机,存储管理(host磁盘扩容,qcow2/vmdk导入vm,vm磁盘导出与迁移等)

【PVE】ProxmoxVE8虚拟机&#xff0c;存储管理&#xff08;host磁盘扩容&#xff0c;qcow2/vmdk导入vm&#xff0c;vm磁盘导出与迁移等&#xff09; 文章目录 1、host 磁盘扩容2、qcow2/vmdk导入vm3、vm 磁盘导出与迁移 1、host 磁盘扩容 如何给host扩容磁盘&#xff0c;如增加…...

【JEECG 组件扩展】JSwitch开关组件扩展单个多选框样式

功能说明&#xff1a; 基于JeecgBoot开源框架&#xff0c;JSwitch开关组件扩展&#xff0c;支持单个多选样式。 效果展示&#xff1a; 使用示例&#xff1a; {field: JSwitch,component: JSwitch,label: JSwitch,},{field: JSwitchCheckBox,component: JSwitch,label: JSwitch…...

卷积神经网络-从零开始构建一个卷积神经网络

目录 一、什么是卷积神经网络CNN 1.1、核心概念 1.2、卷积层 二、什么是卷积计算 2.1、卷积计算的例子: 2.2、点积 2.3、卷积与点积的关系 2.4、Padding(填充) 2.4.1、Padding的主要作用 1、控制输出特征图尺寸 2、保留边缘信息 3. 支持深层网络训练 2.4.2、Str…...

Linux 常用命令集合

以下是一份 Linux 常用命令集合&#xff0c;涵盖文件操作、系统管理、网络管理、权限管理、进程管理等常见任务&#xff0c;并附上代码示例&#xff1a; 1. 文件与目录操作 命令作用示例ls列出目录内容ls -l&#xff08;详细列表&#xff09; ls -a&#xff08;显示隐藏文件&a…...

STM32f103 标准库 零基础学习之按键点灯(不涉及中断)

注意&#xff0c;此次代码不涉及中断&#xff0c;不涉及中断&#xff0c;不涉及中断 目录 1.初始化LED 2.初始化按键 3.粗略的延时函数 4.判断引脚电平 5.通过异或反转电平 开始 │ ├── 初始化LED&#xff08;GPIOA Pin1 推挽输出&#xff09; ├── 初始化按键&…...

【c++】【数据结构】二叉搜索树详解

目录 二叉搜索树的定义二叉搜索树的模拟实现查找函数循环版递归版 插入函数循环版递归版 删除函数循环版递归版 二叉搜索树的定义 二叉搜索树是一种特别的二叉树&#xff0c;是二叉树的搜索特化版。学过排序的都知道&#xff0c;在数组有序的情况下二分查找可以以极高的频率找…...

高精地图数据错误的侵权责任认定与应对之道

首席数据官高鹏律师团队 在自动驾驶与智慧交通快速发展的今天&#xff0c;高精地图作为核心基础设施&#xff0c;其数据准确性直接关系到公共安全。然而&#xff0c;技术并非完美&#xff0c;一旦因地图数据错误导致事故或损失&#xff0c;比如当自动驾驶汽车因高精地图数据错…...

Python训练营打卡——DAY22(2025.5.11)

复习日 学习参考如何使用kaggle平台&#xff0c;写下使用注意点&#xff0c;并对下述比赛提交代码 泰坦尼克号——来自灾难的机器学习 数据来源&#xff1a; kaggle泰坦里克号人员生还预测 挑战 泰坦尼克号沉没是历史上最臭名昭著的海难之一。 1912年4月15日&#xff0c;在被普…...

【计算机视觉】OpenCV实战项目 :Image_Cartooning_Web_App:基于深度学习的图像卡通化

Image_Cartooning_Web_App&#xff1a;基于深度学习的图像卡通化Web应用深度解析 1. 项目概述2. 技术原理与模型架构2.1 核心算法2.2 系统架构 3. 实战部署指南3.1 环境配置3.2 模型部署3.3 处理流程示例 4. 常见问题与解决方案4.1 模型加载失败4.2 显存溢出4.3 边缘伪影 5. 关…...

王道计算机网络知识点总结

计算机网络知识点总结 一、计算机网络体系结构 &#xff08;一&#xff09;计算机网络概述 计算机网络概念&#xff1a;互连的、自治的计算机系统的集合&#xff0c;目的是资源共享&#xff0c;组成包括多台自治计算机&#xff0c;规则是网络协议。 计算机网络的组成&#…...

Java学习笔记(对象)

一、对象本质 状态&#xff08;State&#xff09;&#xff1a;通过成员变量&#xff08;Field&#xff09;描述 行为&#xff08;Behavior&#xff09;&#xff1a;通过成员方法&#xff08;Method&#xff09;实现 class Person {String name;int age;void eat() {System.o…...

并发笔记-给数据上锁(二)

文章目录 核心挑战 (The CRUX)29.1 并发计数器 (Concurrent Counters)1. 简单非并发计数器 (Figure 29.1)2. 同步计数器&#xff08;单锁版本 - Coarse-Grained Lock, Figure 29.2&#xff09;3. 可伸缩计数&#xff1a;近似/懒惰计数器 (Approximate/Sloppy Counter, Figure 2…...

Three.js + React 实战系列 - 页脚区域 Footer 组件 ✨

对个人主页设计和实现感兴趣的朋友可以订阅我的专栏哦&#xff01;&#xff01;谢谢大家&#xff01;&#xff01;&#xff01; 为个人主页画上完美句号&#xff1a;设计一个美观实用的页脚组件 在完成 Hero、About、Projects、Contact 等模块后&#xff0c;我们为整个页面添上…...

基于Flask、Bootstrap及深度学习的水库智能监测分析平台

基于Flask、Bootstrap及深度学习的水库智能监测分析平台 项目介绍 本项目是基于Flask框架构建的水库智能监测分析平台&#xff0c;集水库数据管理、实时监测预警、可视化分析和智能预测功能于一体。 预测水位的预警级别&#xff1a;蓝色预警没有超过正常水位且接近正常水位1米…...

JavaSE核心知识点02面向对象编程02-08(异常处理)

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 JavaSE核心知识点02面向对象编程02-08&#…...

7系列 之 SelectIO 资源

背景 《ug471_7Series_SelectIO.pdf》介绍了Xilinx 7 系列 SelectIO 的输入/输出特性及逻辑资源的相关内容。 第 1 章《SelectIO Resources》介绍了输出驱动器和输入接收器的电气特性&#xff0c;并通过大量实例解析了各类标准接口的实现。 第 2 章《SelectIO Logic Resource…...

【目标检测系列】YOLOV1解读

目标检测系列文章 目录 目标检测系列文章&#x1f4c4; 论文标题&#x1f9e0; 论文逻辑梳理1. 引言部分梳理 (动机与思想) &#x1f4dd; 三句话总结&#x1f50d; 方法逻辑梳理&#x1f680; 关键创新点&#x1f517; 方法流程图关键疑问解答Q1: 关于 YOLOv1 中的 "conf…...

GIF图像技术介绍

以下是对GIF格式的详细介绍,涵盖其定义、发展历程、技术特性、应用场景及与其他格式的对比: 一、GIF的定义与起源 GIF(Graphics Interchange Format,图形交换格式)由美国CompuServe公司于1987年推出,旨在解决早期互联网带宽不足的问题。其开发者Steve Wilhite采用LZW无损…...

【TI MSPM0】CCS工程管理

一、关于WORKSPACE 1.导入工程路径 导入工程时&#xff0c;实际是将工程从原路径复制到了Workspace路径下&#xff08;默认是在C盘user路径下&#xff09; 2.工程保存备份 关于工程的保存&#xff0c;可以右击文件夹&#xff0c;点击Reveal打开文件夹 将对应的文件夹进行复…...

牛客周赛 Round 92-题解

牛客周赛 Round 92-题解 A-小红的签到题 code #include<iostream> #include<string> using namespace std; string s; int main() {int n;cin >> n;cout << "a_";for (int i 0; i < n - 2; i )cout << b;return 0; }B-小红的模…...

iVX 图形化编程平台:结合 AI 原生开发的革新与实践

一、技术架构&#xff1a;重构 AI 与编程的交互逻辑 1. 信息密度革命&#xff1a;从线性代码到图形化语义单元 传统文本编程存在显著的信息密度瓶颈。以 "按钮点击→条件判断→调用接口→弹窗反馈" 流程为例&#xff0c;Python 实现需定义函数、处理缩进并编写 30 …...

微服务架构中如何保证服务间通讯的安全

在微服务架构中,保证服务间通信的安全至关重要。服务间的通信通常是通过HTTP、gRPC、消息队列等方式实现的,而这些通信链路可能面临多种安全风险。为了应对这些风险,可以采取多种措施来保证通信安全。 常见的服务间通信风险 1.数据泄露:在服务间通信过程中,敏感数据可能会…...