Kruise Rollout 全链路灰度实践

2024-01-25 05:52

本文主要是介绍Kruise Rollout 全链路灰度实践,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

作者:旦酱、十眠

什么是全链路灰度?

在发布应用的过程中,我们通常希望用少量特定流量来验证新版本的发布是否正常,以保障整体稳定性。这个过程被称为灰度发布。关于灰度发布,我们通过逐步增加发布的范围,来验证新版本的稳定性。如果新版本出现问题,我们也能及时发现,控制影响范围,保障整体的稳定性。

图片

灰度发布一般具有以下特点:

  • 逐步增加发布的影响范围,拒绝一次性全部发布。
  • 阶段性的发布过程,可以通过金丝雀发布方式小心验证,以验证新版本的稳定性;
  • 可暂停、可回滚、可继续、可自动化状态流转,以便灵活地控制发布过程并确保稳定性;

据调研数据 70% 的线上问题都是由于变更导致,我们常说安全生产三板斧,可灰度、可观测、可回滚,也是为了控制变更带来的风险与影响面。 通过采用灰度发布的方式,我们能够更加稳健地发布新版本,避免因发布过程中出现的问题而带来的损失。

全链路灰度是微服务场景下灰度发布方案的最佳实践,通常每个微服务都会有灰度环境或分组来接受灰度流量。我们希望进入上游灰度环境的流量也能进入下游灰度的环境中,确保1个请求始终在灰度环境中传递,从而形成流量“泳道”。在“泳道”内的流量链路中,即使这个调用链路上有一些微服务应用不存在灰度环境,那么这些微服务应用在请求下游应用的时候依然能够回到下游应用的灰度环境中。

图片

全链路灰度为微服务发布保驾护航

这种方式可以根据服务的实际情况,可以对单个服务可以进行独立的发布和流量控制,也可以控制多个服务同时进行发布变更,从而保证整个系统的稳定性。同时,还可以采用自动化的部署方式,实现快速、可靠的发布过程,提高发布效率和稳定性。

Istio 全链路灰度技术解析

如何通过 Istio 实现全链路灰度能力,想必大家都很关心这个话题,今天我们就详细谈一下基于 istio 实现全链路灰度能力的几个关键技术细节。

流量标签全链路透传

在对微服务进行全链路灰度的过程中,一个最需要考虑的问题是流量中 header 透传的问题,一些微服务会仅保留特定的 header 进行透传,而去除其它 header,利用 Kruise Rollout,可以有效减少发布中对网关资源进行配置的复杂性,但却无法解决 header 透传的问题。如何保证灰度标识能够在链路中一直传递下去呢?分布式链路追踪技术对大型分布式系统中请求调用链路进行详细记录,核心思想就是通过一个全局唯一的 traceid 和每一条的 spanid 来记录请求链路所经过的节点以及请求耗时,其中 traceid 是需要整个链路传递的。借助于分布式链路追踪思想,我们也可以传递一些自定义信息,比如灰度标识。业界常见的分布式链路追踪产品都支持链路传递用户自定义的数据,其数据处理流程如下图所示:

图片

我们可以借助 Tracing Baggage 机制在全链路中传递对应染色标识,因为大部分 Tracing 框架都支持 Baggage 概念及能力,如:OpenTelemetry、Skywalking、Jaeger 等等。我们只需要在 Envoy outbound Filter 中讲指定的透传 key 如 x-mse-tag 从 Tracing 协议指定位置的 Baggage 中读出 x-mse-tag 对应的值,并塞入到 Http 的 Header 中,供 Envoy 进行路由。

流量路由

通过对服务下所有节点按照标签名和标签值不同进行分组,使得订阅该服务节点信息的服务消费端可以按需访问该服务的某个分组,即所有节点的一个子集。服务消费端可以使用服务提供者节点上的任何标签信息,根据所选标签的实际含义,消费端可以将标签路由应用到更多的业务场景中。

图片

在 Istio 中我们可以通过 Istio Gateway、DestinationRule 和 VirtualService 配置路由和外部访问;

节点打标

如何给服务节点添加不同的标签?我们只要在业务应用描述资源 Deployment 中的 Pod 模板中为节点添加标签即可。在使用 Kubernetes Service 作为服务发现的业务系统中,服务提供者通过向 ApiServer 提交 Service 资源完成服务暴露,服务消费端监听与该 Service 资源下关联的 Endpoint 资源,从 Endpoint 资源中获取关联的业务 Pod 资源,读取上面的 Labels 数据并作为该节点的元数据信息。

图片

为什么选择 Kruise Rollout?

从上述技术细节中可以看出,实现基于 Istio 的全链路灰度操作非常复杂且成本较高。首先,需要创建灰度的 Deployment 并打上灰度的节点标识。其次,还需要配置 Istio 的流量路由 CRD,包括每一跳请求的 VirtualService 和 DestinationRule 规则,并且这些流量规则还需要与请求标识相配合。如果只是纸上谈谈技术细节,可能还能勉强理解,但如果真要实践起来,成本确实非常高。同时,如果在配置过程中出现错误,可能会导致生产流量出现问题,对业务造成重大影响。为了降低全链路灰度实践的成本,不得不提 Kruise Rollout 了。

Kruise Rollout [ 1] 是 OpenKruise 社区开源提出的一个渐进式交付框架。其设计理念是提供一组能够将流量发布与实例灰度相结合,支持金丝雀、蓝绿、A/B Testing 等多样化发布形式,以及支持基于 Prometheus Metrics 等自定义 Metrics 实现发布过程自动化,无感对接、易扩展的旁路式标准 Kubernetes 发布组件。

图片

从上图中我们可以看到 OpenKruise Rollout 能够将复杂的灰度发布过程自动化,因此通过 OpenKruise Rollout 可以大幅度降低全链路灰度的实施成本,对于使用者来说只需要配置 Kruise Rollout 的 CRD,然后直接进行应用发布,即可实现全链路灰度发布。

Kruise + Istio 全链路灰度实践

谈完技术实现的细节,下面我们就开始基于 Kruise Rollout 跟 Istio 的全链路灰度能力实践。

配置服务

首先部署两个服务 mocka 和 mockb,服务 mocka 会调用服务 mockb,⚠️服务只会保留流量中的 header my-request-id 而去除其它 header(我们也可以通过接入 OpenTelemetry 实现动态流量标签透传), 整个服务的访问可以表示为:

图片

服务的配置文件为:

apiVersion: v1
kind: Service
metadata:name: mockanamespace: e2elabels:app: mockaservice: mocka
spec:ports:- port: 8000name: httpselector:app: mocka
---
apiVersion: apps/v1
kind: Deployment
metadata:name: mocka-basenamespace: e2elabels:app: mocka
spec:replicas: 1selector:matchLabels:app: mockatemplate:metadata:labels:app: mockaversion: basespec:containers:- name: defaultimage: registry.cn-beijing.aliyuncs.com/aliacs-app-catalog/go-http-sample:1.0imagePullPolicy: Alwaysenv:- name: versionvalue: base- name: appvalue: mocka- name: upstream_urlvalue: "http://mockb:8000/"ports:- containerPort: 8000
---
apiVersion: v1
kind: Service
metadata:name: mockbnamespace: e2elabels:app: mockbservice: mockb
spec:ports:- port: 8000name: httpselector:app: mockb
---
apiVersion: apps/v1
kind: Deployment
metadata:name: mockb-basenamespace: e2elabels:app: mockb
spec:replicas: 1selector:matchLabels:app: mockbtemplate:metadata:labels:app: mockbversion: basespec:containers:- name: defaultimage: registry.cn-beijing.aliyuncs.com/aliacs-app-catalog/go-http-sample:1.0imagePullPolicy: Alwaysenv:- name: versionvalue: base- name: appvalue: mockbports:- containerPort: 8000

服务的 header 部分处理代码如下所示:

// All URLs will be handled by this function
m.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {requestId := r.Header.Get("my-request-id")fmt.Printf("receive request: my-request-id: %s\n", requestId)response := fmt.Sprintf("-> %s(version: %s, ip: %s)", app, version, ip)if url != "" {// 新请求只发送my-request-idcontent := doReq(url, requestId)response = response + content}w.Write([]byte(response))
})

之后部署 Istio Gateway、DestinationRule 和 VirtualService 配置路由和外部访问:

apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:name: gatewaynamespace: e2e
spec:selector:istio: ingressgatewayservers:- hosts:- "*"port:name: httpnumber: 80protocol: HTTP
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:name: dr-mockanamespace: e2e
spec:host: mockatrafficPolicy:loadBalancer:simple: ROUND_ROBINsubsets:- labels:version: basename: version-base
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:name: dr-mockbnamespace: e2e
spec:host: mockbtrafficPolicy:loadBalancer:simple: ROUND_ROBINsubsets:- labels:version: basename: version-base
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:name: vs-mockanamespace: e2e
spec:gateways:- simple-gatewayhosts:- "*"http:- route:- destination:host: mockasubset: version-base
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:name: vs-mockbnamespace: e2e
spec:hosts:- mockbhttp:- route:- destination:host: mockbsubset: version-base

部署完成后整个结构如下图所示:

图片

在本地集群中,可以通过运行如下指令获取 Gateway 入口 ip 以及 port 对服务进行访问:

kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}'
kubectl get po -l istio=ingressgateway -n istio-system -o jsonpath='{.items[0].status.hostIP}'

此时运行 curl http://GATEWAY_IP:PORT 可以得到如下结果:

-> mocka(version: base, ip: 10.244.1.36)-> mockb(version: base, ip: 10.244.1.37)

配置 Rollout 和 TrafficRouting 规则

之后部署 Rollout,分别对 mocka 和 mockb 进行控制。Rollout 以及 TrafficRouting 配置的策略如下:

  • 添加了匹配 my-request-id=canary 的 header 规则,包含指定 header 的流量会走灰度环境
  • 为发布的 pod 添加了 label istio.service.tag=gray 以及 version=canary

⚠️pod label 的添加规则是什么?

在配置中为新版本 pod 打上了两个 label,其中 istio.service.tag=gray 的目的是为了在 DestinationRule 中指定包含该 label 的 pod 作为一个 subset,lua 脚本会为 DestinationRule 自动添加该 Subset。添加 version=canary 的目的是为了覆盖原始版本中的 version=baselabel,如果不覆盖该 label, 原始 DestinationRule 也会将稳定版本的流量导入新版本 pod 中。

apiVersion: rollouts.kruise.io/v1alpha1
kind: Rollout
metadata:name: rollouts-anamespace: demoannotations:rollouts.kruise.io/rolling-style: canaryrollouts.kruise.io/trafficrouting: mocka-tr
spec:disabled: falseobjectRef:workloadRef:apiVersion: apps/v1kind: Deploymentname: mocka-basestrategy:canary:steps:- replicas: 1patchPodTemplateMetadata:labels:istio.service.tag: grayversion: canary
---
apiVersion: rollouts.kruise.io/v1alpha1
kind: TrafficRouting
metadata:name: mocka-trnamespace: demo
spec:strategy:matches:- headers:- type: Exactname: my-request-idvalue: canaryobjectRef:- service: mockacustomNetworkRefs:- apiVersion: networking.istio.io/v1alpha3kind: VirtualServicename: vs-mocka- apiVersion: networking.istio.io/v1beta1kind: DestinationRulename: dr-mocka
---
apiVersion: rollouts.kruise.io/v1alpha1
kind: Rollout
metadata:name: rollouts-bnamespace: demoannotations:rollouts.kruise.io/rolling-style: canaryrollouts.kruise.io/trafficrouting: mockb-tr
spec:disabled: falseobjectRef:workloadRef:apiVersion: apps/v1kind: Deploymentname: mockb-basestrategy:canary:steps:- replicas: 1patchPodTemplateMetadata:labels:istio.service.tag: grayversion: canary
---
apiVersion: rollouts.kruise.io/v1alpha1
kind: TrafficRouting
metadata:name: mockb-trnamespace: demo
spec:strategy:matches:- headers:- type: Exactname: my-request-idvalue: canaryobjectRef:- service: mockbcustomNetworkRefs:- apiVersion: networking.istio.io/v1alpha3kind: VirtualServicename: vs-mockb- apiVersion: networking.istio.io/v1beta1kind: DestinationRulename: dr-mockb

开始灰度发布

修改 mocka 和 mockb 中的环境变量为 version=canary 开始发布。Kruise Rollout 将自动获取网关资源并进行修改,此时查看 VirtualService 和 DestinationRule 可以得到,VirtualService 定义了路由规则将带有 my-request-id=canary 的 header 的流量路由至 canary 版本。DestinationRule 添加了对于包含 label istio.service.tag=gray 新的 Subset。

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:annotations:kubectl.kubernetes.io/last-applied-configuration: |{"apiVersion":"networking.istio.io/v1beta1","kind":"VirtualService","metadata":{"annotations":{},"name":"vs-mocka","namespace":"demo"},"spec":{"gateways":["simple-gateway"],"hosts":["*"],"http":[{"route":[{"destination":{"host":"mocka","subset":"version-base"}}]}]}}rollouts.kruise.io/origin-spec-configuration: '{"spec":{"gateways":["simple-gateway"],"hosts":["*"],"http":[{"route":[{"destination":{"host":"mocka","subset":"version-base"}}]}]},"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"networking.istio.io/v1beta1\",\"kind\":\"VirtualService\",\"metadata\":{\"annotations\":{},\"name\":\"vs-mocka\",\"namespace\":\"demo\"},\"spec\":{\"gateways\":[\"simple-gateway\"],\"hosts\":[\"*\"],\"http\":[{\"route\":[{\"destination\":{\"host\":\"mocka\",\"subset\":\"version-base\"}}]}]}}\n"}}'creationTimestamp: "2023-09-12T07:49:15Z"generation: 40name: vs-mockanamespace: demoresourceVersion: "98670"uid: c7da3a99-789c-4f1e-93a4-caaee41cbe06
spec:gateways:- simple-gatewayhosts:- '*'http:# -- lua脚本自动添加的规则- match:- headers:my-request-id:exact: canaryroute:- destination:host: mockasubset: canary# --- route:- destination:host: mockasubset: version-base
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:annotations:kubectl.kubernetes.io/last-applied-configuration: |{"apiVersion":"networking.istio.io/v1beta1","kind":"VirtualService","metadata":{"annotations":{},"name":"vs-mockb","namespace":"demo"},"spec":{"hosts":["mockb"],"http":[{"route":[{"destination":{"host":"mockb","subset":"version-base"}}]}]}}rollouts.kruise.io/origin-spec-configuration: '{"spec":{"hosts":["mockb"],"http":[{"route":[{"destination":{"host":"mockb","subset":"version-base"}}]}]},"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"networking.istio.io/v1beta1\",\"kind\":\"VirtualService\",\"metadata\":{\"annotations\":{},\"name\":\"vs-mockb\",\"namespace\":\"demo\"},\"spec\":{\"hosts\":[\"mockb\"],\"http\":[{\"route\":[{\"destination\":{\"host\":\"mockb\",\"subset\":\"version-base\"}}]}]}}\n"}}'creationTimestamp: "2023-09-12T07:49:16Z"generation: 40name: vs-mockbnamespace: demoresourceVersion: "98677"uid: 7c96ee2b-96ce-48e4-ba6d-cf94171ed854
spec:hosts:- mockbhttp:# -- lua脚本自动添加的规则- match:- headers:my-request-id:exact: canaryroute:- destination:host: mockbsubset: canary# -- - route:- destination:host: mockbsubset: version-base
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:annotations:kubectl.kubernetes.io/last-applied-configuration: |{"apiVersion":"networking.istio.io/v1beta1","kind":"DestinationRule","metadata":{"annotations":{},"name":"dr-mocka","namespace":"demo"},"spec":{"host":"mocka","subsets":[{"labels":{"version":"base"},"name":"version-base"}],"trafficPolicy":{"loadBalancer":{"simple":"ROUND_ROBIN"}}}}rollouts.kruise.io/origin-spec-configuration: '{"spec":{"host":"mocka","subsets":[{"labels":{"version":"base"},"name":"version-base"}],"trafficPolicy":{"loadBalancer":{"simple":"ROUND_ROBIN"}}},"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"networking.istio.io/v1beta1\",\"kind\":\"DestinationRule\",\"metadata\":{\"annotations\":{},\"name\":\"dr-mocka\",\"namespace\":\"demo\"},\"spec\":{\"host\":\"mocka\",\"subsets\":[{\"labels\":{\"version\":\"base\"},\"name\":\"version-base\"}],\"trafficPolicy\":{\"loadBalancer\":{\"simple\":\"ROUND_ROBIN\"}}}}\n"}}'creationTimestamp: "2023-09-12T07:49:15Z"generation: 12name: dr-mockanamespace: demoresourceVersion: "98672"uid: a6f49044-e889-473c-b188-edbdb8ee347f
spec:host: mockasubsets:- labels:version: basename: version-base# -- lua脚本自动添加的规则- labels:istio.service.tag: grayname: canary# --trafficPolicy:loadBalancer:simple: ROUND_ROBIN
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:annotations:kubectl.kubernetes.io/last-applied-configuration: |{"apiVersion":"networking.istio.io/v1beta1","kind":"DestinationRule","metadata":{"annotations":{},"name":"dr-mockb","namespace":"demo"},"spec":{"host":"mockb","subsets":[{"labels":{"version":"base"},"name":"version-base"}],"trafficPolicy":{"loadBalancer":{"simple":"ROUND_ROBIN"}}}}rollouts.kruise.io/origin-spec-configuration: '{"spec":{"host":"mockb","subsets":[{"labels":{"version":"base"},"name":"version-base"}],"trafficPolicy":{"loadBalancer":{"simple":"ROUND_ROBIN"}}},"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"networking.istio.io/v1beta1\",\"kind\":\"DestinationRule\",\"metadata\":{\"annotations\":{},\"name\":\"dr-mockb\",\"namespace\":\"demo\"},\"spec\":{\"host\":\"mockb\",\"subsets\":[{\"labels\":{\"version\":\"base\"},\"name\":\"version-base\"}],\"trafficPolicy\":{\"loadBalancer\":{\"simple\":\"ROUND_ROBIN\"}}}}\n"}}'creationTimestamp: "2023-09-12T07:49:15Z"generation: 12name: dr-mockbnamespace: demoresourceVersion: "98678"uid: 4bd0f6c5-efa1-4558-9e31-6f7615c21f9a
spec:host: mockbsubsets:- labels:version: basename: version-base# -- lua脚本自动添加的规则- labels:istio.service.tag: grayname: canary# --trafficPolicy:loadBalancer:simple: ROUND_ROBIN

此时运行 curl http://GATEWAY_IP:PORT 可以得到如下结果,所有流量均通过 base 版本服务。

-> mocka(version: base, ip: 10.244.1.36)-> mockb(version: base, ip: 10.244.1.37)

此时运行 curl -H http://GATEWAY_IP:PORT -Hmy-request-id:canary 可以得到如下结果,所有流量均通过 canary 版本服务。

-> mocka(version: canary, ip: 10.244.1.41)-> mockb(version: canary, ip: 10.244.1.42)

此时整个服务的流量可以表示为下图,包含 headermy-request-id=canary 的流量全部走灰度环境,其它流量全部走基线环境:

图片

(可选)利用 EnvoyFilter 进行流量染色

我们可以通过编写 EnvoyFilter 进一步简化流量染色的步骤,在之前的例子中,在请求的时候包含了可以透传的 header my-request-id,如果想要实现更加通用的 header 请求规则,例如包含 agent=pc 的流量全部走灰度环境,其它则走基线环境,则可以通过 EnvoyFilter 在入口网关进行染色。以下定义了一个 EnvoyFilter,该 EnvoyFilter 定义了一个 Lua 脚本,会对包含 agent=pc 的流量染色,为其添加 my-request-id=canary,而其它流量则添加 my-request-id=base。


apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:name: http-request-labelling-according-sourcenamespace: istio-system
spec:workloadSelector:labels:app: istio-ingressgatewayconfigPatches:- applyTo: HTTP_FILTERmatch:context: GATEWAYlistener:filterChain:filter:name: "envoy.filters.network.http_connection_manager"subFilter:name: "envoy.filters.http.router"patch:operation: INSERT_BEFOREvalue:name: envoy.luatyped_config:"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua"inlineCode: |function envoy_on_request(request_handle)local header = "agent"headers = request_handle:headers()version = headers:get(header)if (version ~= nil) thenif (version == "pc") thenheaders:add("my-request-id","canary")elseheaders:add("my-request-id","base")endelseheaders:add("my-request-id","base")endend

保持其它配置不变,此时运行 curl http://GATEWAY_IP:PORT 可以得到如下结果,所有流量均通过 base 版本服务。

-> mocka(version: base, ip: 10.244.1.36)-> mockb(version: base, ip: 10.244.1.37)

此时运行 curl -H http://GATEWAY_IP:PORT -Hagent:pc 可以得到如下结果,EnvoyFilter 自动为该流量添加 headermy-request-id=canary,因此所有流量均通过新版本服务。

-> mocka(version: canary, ip: 10.244.1.41)-> mockb(version: canary, ip: 10.244.1.42)

完整的全链路灰度方案

Kruise Rollout 除了支持开源的 Istio 实现全链路灰度外,还支持与 MSE 实现完整的全链路灰度方案,我们可以通过如下操作文档 [ 2] 快速实现体系化的全链路灰度能力。

图片MSE 全链路灰度可以有效地控制流量在前端、网关、后端各个微服务等组件中闭环,不仅仅是 RPC/Http 的流量,对于异步调用比如 MQ 流量也支持符合全链路“泳道”调用的规则。通过 Kruise Rollout 跟 MSE 可以帮助我们更加便捷地实现微服务全链路灰度发布,提高微服务场景下发布的效率和稳定性。

加入 OpenKruise 社区

最后,非常欢迎你通过 Github/Slack/钉钉/微信 等方式加入我们来参与 OpenKruise 开源社区。

  • 加入社区 Slack channel (English)
  • 加入社区钉钉群:搜索群号 23330762 (Chinese)
  • 加入社区微信群(新):添加用户 openkruise 并让机器人拉你入群 (Chinese)

相关链接:

[1] Kruise Rollout

https://openkruise.io/rollouts/introduction

[2] 操作文档

https://help.aliyun.com/zh/mse/user-guide/implement-mse-based-end-to-end-canary-release-by-using-kruise-rollouts?spm=a2c4g.11186623.0.0.1d5a79dezV82UH

这篇关于Kruise Rollout 全链路灰度实践的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/642274

相关文章

SpringBoot项目中Maven剔除无用Jar引用的最佳实践

《SpringBoot项目中Maven剔除无用Jar引用的最佳实践》在SpringBoot项目开发中,Maven是最常用的构建工具之一,通过Maven,我们可以轻松地管理项目所需的依赖,而,... 目录1、引言2、Maven 依赖管理的基础概念2.1 什么是 Maven 依赖2.2 Maven 的依赖传递机

Oracle查询优化之高效实现仅查询前10条记录的方法与实践

《Oracle查询优化之高效实现仅查询前10条记录的方法与实践》:本文主要介绍Oracle查询优化之高效实现仅查询前10条记录的相关资料,包括使用ROWNUM、ROW_NUMBER()函数、FET... 目录1. 使用 ROWNUM 查询2. 使用 ROW_NUMBER() 函数3. 使用 FETCH FI

在C#中获取端口号与系统信息的高效实践

《在C#中获取端口号与系统信息的高效实践》在现代软件开发中,尤其是系统管理、运维、监控和性能优化等场景中,了解计算机硬件和网络的状态至关重要,C#作为一种广泛应用的编程语言,提供了丰富的API来帮助开... 目录引言1. 获取端口号信息1.1 获取活动的 TCP 和 UDP 连接说明:应用场景:2. 获取硬

Java内存泄漏问题的排查、优化与最佳实践

《Java内存泄漏问题的排查、优化与最佳实践》在Java开发中,内存泄漏是一个常见且令人头疼的问题,内存泄漏指的是程序在运行过程中,已经不再使用的对象没有被及时释放,从而导致内存占用不断增加,最终... 目录引言1. 什么是内存泄漏?常见的内存泄漏情况2. 如何排查 Java 中的内存泄漏?2.1 使用 J

SpringBoot如何使用TraceId日志链路追踪

《SpringBoot如何使用TraceId日志链路追踪》文章介绍了如何使用TraceId进行日志链路追踪,通过在日志中添加TraceId关键字,可以将同一次业务调用链上的日志串起来,本文通过实例代码... 目录项目场景:实现步骤1、pom.XML 依赖2、整合logback,打印日志,logback-sp

Linux中Curl参数详解实践应用

《Linux中Curl参数详解实践应用》在现代网络开发和运维工作中,curl命令是一个不可或缺的工具,它是一个利用URL语法在命令行下工作的文件传输工具,支持多种协议,如HTTP、HTTPS、FTP等... 目录引言一、基础请求参数1. -X 或 --request2. -d 或 --data3. -H 或

Docker集成CI/CD的项目实践

《Docker集成CI/CD的项目实践》本文主要介绍了Docker集成CI/CD的项目实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录一、引言1.1 什么是 CI/CD?1.2 docker 在 CI/CD 中的作用二、Docke

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

Prometheus与Grafana在DevOps中的应用与最佳实践

Prometheus 与 Grafana 在 DevOps 中的应用与最佳实践 随着 DevOps 文化和实践的普及,监控和可视化工具已成为 DevOps 工具链中不可或缺的部分。Prometheus 和 Grafana 是其中最受欢迎的开源监控解决方案之一,它们的结合能够为系统和应用程序提供全面的监控、告警和可视化展示。本篇文章将详细探讨 Prometheus 和 Grafana 在 DevO