15、云运行服务的日志记录、跟踪与本地部署实践

云运行服务的日志记录、跟踪与本地部署实践

1. 跟踪上下文与分布式跟踪

在处理请求并调用另一个云运行(Cloud Run)服务时,我们希望将第一个请求和第二个请求的日志分组显示。特别是在应用由多个微服务协同工作时,这一功能尤为重要。若下游服务出现问题,我们能知晓调用该服务的上游服务中发生了什么。

分布式跟踪是一个成熟且复杂的主题,这里仅作简要介绍。若要全面了解,可参考相关资料。

1.1 转发跟踪 ID

捕获传入的跟踪头并将跟踪 ID 转发到服务发起的请求中,云日志记录(Cloud Logging)会将所有请求添加到同一跟踪中。Google 前端(GFE)会为传入请求添加 X-Cloud-Trace-Context 头,并保留已有该头的请求的跟踪 ID。

在 Go 中实现跟踪 ID 转发的关键步骤如下:
1. 使用 crzerolog 包写入日志,将跟踪 ID 添加到日志中。
2. 以 idtoken 包能理解的方式(使用 Go 的请求上下文)将跟踪 ID 添加到所有传入请求中。
3. 将传入请求的上下文传递到传出请求,并使用 idtoken HTTP 客户端发起请求。

idtoken 包也可用于向公共云运行服务发送请求,ID 令牌仅用于标识请求。

1.2 为所有传入请求准备跟踪 ID

idtoken 包需要请求上下文中的跟踪 ID 以与开源分布式跟踪工具 OpenCensus 兼容。可以使用 OpenCensus 包装 HTTP 处理程序:

// "go.opencensus.io/plugin/ochttp"
// "contrib.go.opencensus.io/exporter/stackdriver/propagation"
httpHandler := &ochttp.Handler{
  Propagation: &propagation.HTTPFormat{}, 
  Handler:     handler,
 }
 http.ListenAndServe(":8080", httpHandler)
1.3 将请求上下文传递到传出请求

使用 idtoken 包发起请求时,应将传入请求的上下文传递到传出请求:

URL := "https://[SERVICE].run.app"
client, _ := idtoken.NewClient(context.Background(), URL)
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
  req, _ := http.NewRequest("GET", URL, nil)
  req = req.WithContext(r.Context()) // Pass context
  client.Do(req)
})

以下是一个完整的端到端示例:

package main
import (
   "context"
   "os"
   "contrib.go.opencensus.io/exporter/stackdriver/propagation"
   "github.com/rs/zerolog"
   "github.com/rs/zerolog/log"
   "github.com/yfuruyama/crzerolog"
   "go.opencensus.io/plugin/ochttp"
   "google.golang.org/api/idtoken"
   "net/http"
)
func main() {
   mux := http.NewServeMux()
   mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
       client, _ := idtoken.NewClient(context.Background(), r.Host)
       log.Ctx(r.Context()).Info().Msg("1st")
       req, _ := http.NewRequest("GET", "https://"+r.Host+"/call", nil)
       req = req.WithContext(r.Context())
       client.Do(req)
   })
   mux.HandleFunc("/call", 
     func(w http.ResponseWriter, r *http.Request) {
       log.Ctx(r.Context()).Info().Msg("2nd")
   })
   rootLogger := zerolog.New(os.Stdout)
   middleware := crzerolog.InjectLogger(&rootLogger)
   handler := middleware(mux)
   httpHandler := &ochttp.Handler{
       Propagation: &propagation.HTTPFormat{},
       Handler:     handler,
   }
   if err := http.ListenAndServe(":8080", httpHandler); err != nil {
       log.Fatal().Msg("Can’t start service")
   }
}
1.4 在云日志记录中查看跟踪上下文

将上述示例部署为云运行服务后,它会向自身发起请求并转发跟踪 ID。在云日志记录中查看跟踪的方法是:选取任意日志,点击带有蓝色条的药丸,然后选择“显示此跟踪的所有日志”。

2. 分布式跟踪的其他资源

这里对分布式跟踪的解释较为实用,实际上还有更多功能,如创建自定义跨度、控制采样率以及提高整个堆栈的可见性等。可以参考相关文档,使用 OpenCensus 库在 Go 应用中配置云跟踪(Cloud Trace)。

3. 基于云监控的日志指标

云监控(Cloud Monitoring)可监控云运行系统指标,如容器 CPU 和内存(利用率和分配)、请求延迟和计数等。结构化日志为云日志记录中的日志带来了大量有用的额外数据,云监控可以摄取这些数据,从而创建图表并设置基于日志的指标警报。

创建基于日志的指标的步骤如下:
1. 进入云日志记录中的“基于日志的指标”选项卡。
2. 点击“创建指标”按钮。

4. 结构化日志的总结

日志记录是构建生产就绪应用程序的重要部分。在云运行中使用结构化日志可获得以下好处:
| 类型 | 说明 |
| ---- | ---- |
| 日志级别 | 表示日志事件的重要性(调试、信息、警告、错误、致命、恐慌),是最常见的元数据类型。 |
| 业务元数据 | 将日志与订单或产品等逻辑概念关联,有助于理解日志并发现模式,但要注意避免添加个人信息。 |
| 源代码位置 | 知道打印日志的具体代码行,无需在代码库中搜索日志来源。 |
| 请求上下文 | 发生错误时,可读取处理该请求时写入的所有日志。 |
| 跟踪上下文 | 在调用下游云运行服务时传播请求上下文,可一起查看所有请求的日志。 |

云运行与云日志记录集成,无需强制使用特定于供应商的库和工具,可使用开源库改善日志记录体验。

5. 云运行与 Knative 服务

云运行与开源项目 Knative 服务的 API 兼容,这意味着可以轻松地将服务从云运行迁移到 Knative 服务。

5.1 可移植性的重要性

虽然不建议将本地的 Knative 服务作为开发环境(Docker Compose 是本地容器编排的轻量级方法),但了解可移植性很重要。在供应商单方面改变定价或其他条款,或者法规要求在 Google Cloud 未覆盖的地理位置运行软件和存储数据时,可移植性能提供更多选择。

5.2 Knative 服务概述

Knative 服务的主要目标是为开发者提供一个良好的抽象,用于操作基于容器、由请求驱动且能自动从零扩展到多个容器的无状态服务。

Knative 服务与云运行具有相同的资源模型,开发者与之交互的主要资源相同。每次更改服务时,Knative 会创建一个新的不可变版本,版本是容器镜像和运行时配置(如环境变量和资源要求)的组合。其运行时行为也与云运行相同,单个容器是可丢弃的,服务会根据需求自动从零扩展到多个容器。

需要注意的是,云运行不是托管的 Knative 服务,它是对同一规范的兼容但完全独立的专有实现,直接运行在 Google 的超大规模容器基础设施 Borg 之上。

5.3 在 Google Cloud 上使用 Knative 服务

可以在自己的基础设施上运行完全自我管理的 Knative 服务,也可以使用云运行,或者介于两者之间的方案。Knative 提供了一个抽象层,无论是否管理自己的基础设施,开发者都能获得无服务器的开发体验。

6. 理解 Kubernetes

Knative 服务是 Kubernetes 集群的扩展,因此了解 Kubernetes 很有必要。

6.1 Kubernetes 概述

Kubernetes 集群是一组运行容器的节点(服务器),既可以使用供应商提供的托管 Kubernetes 集群,也可以在自己的数据中心的物理硬件上运行并自行管理。

Kubernetes 本质上是一个容器编排器,它会确定在哪个节点上启动容器,并确保网络流量能够到达容器。其架构支持大规模部署,Google 报告称使用 Google Kubernetes Engine(GKE)集群的实际部署可运行多达 15,000 个节点。

以下是 Kubernetes 的主要组件:
| 组件 | 说明 |
| ---- | ---- |
| API 服务器 | 位于 Kubernetes 的中心,通过客户端(如命令行客户端 kubectl )与之交互。Kubernetes API 基于资源,可创建、读取、更新或删除 Kubernetes 资源。例如,使用 kubectl create deployment --image=docker.io/library/nginx nginx 启动一个带有 Nginx 网络服务器的容器。 |
| Kubernetes 资源 | 如部署(Deployment)和 Pod 等。部署表示一组容器,若容器失败或变得不健康,Kubernetes 会重启它。Pod 是最简单的 Kubernetes 资源,代表集群中的一个或多个协同工作的容器。 |
| 数据库 | 存储所有 Kubernetes 资源,API 服务器是唯一与之连接的组件,负责处理客户端认证、授权和输入验证,并对资源进行更改,但不负责确定启动容器的节点。 |
| 控制器 | 每种资源类型都有一个专用的控制器,当创建、更新或删除资源时,控制器会尝试改变集群以使其符合描述。例如,创建部署资源后,部署控制器会创建其他低级别的 Kubernetes 资源(如 ReplicaSet),最终创建 Pod 并调度到节点上启动。每个节点上的 kubelet 进程会持续监视 API 服务器,一旦有 Pod 被调度到该节点,就会启动容器。 |

6.2 向 Kubernetes 添加扩展

可以使用自定义资源定义(CRD)定义自己的 Kubernetes 资源类型,并告知 API 服务器。然后启动自己的控制器,监视自定义资源的更改并创建其他内置 Kubernetes 资源。

Knative 就是 Kubernetes 的扩展,它添加了新资源,如服务(Service)、配置(Configuration)和版本(Revision),并启动新的控制器来监视这些资源。当有新的 Knative 服务到来时,Knative 控制器会在底层创建和管理 Kubernetes 部署资源。

7. 本地运行 Knative 服务

现在进行实践探索,目标是展示如何将服务从云运行迁移到本地安装的 Knative 服务。不过,不建议使用本地 Kubernetes 集群进行本地开发,可参考使用 Docker 的更好方法。

7.1 运行本地 Kubernetes 集群

运行本地 Kubernetes 集群有多种选择,常见的有 Minikube、k3s 和 kind。Minikube 历史最久,由社区维护,对初学者友好,它使用虚拟机(或 Docker 容器)运行单节点 Kubernetes 集群,便于学习时快速重置。

mermaid 流程图如下:

graph LR
    A[开始] --> B[选择本地 Kubernetes 集群方案]
    B --> C{方案类型}
    C -->|Minikube| D[使用虚拟机或 Docker 容器运行单节点集群]
    C -->|k3s| E[其他运行方式]
    C -->|kind| F[其他运行方式]
    D --> G[学习使用]
    E --> G
    F --> G
    G --> H[结束]

云运行服务的日志记录、跟踪与本地部署实践

8. 本地运行 Knative 服务的实践步骤

虽然前面提到不建议用本地 Kubernetes 集群进行开发,但为了展示云运行与 Knative 服务的兼容性,下面详细介绍本地运行 Knative 服务的步骤。

8.1 安装 Minikube(以 Minikube 为例)

如果你选择 Minikube 来运行本地 Kubernetes 集群,可按以下步骤操作:
1. 下载 Minikube :根据你的操作系统,从 Minikube 的官方 GitHub 仓库下载对应版本的二进制文件。
2. 安装 Minikube :将下载的二进制文件添加到系统的 PATH 环境变量中,以便可以在任何位置使用 minikube 命令。
3. 启动 Minikube :在终端中运行 minikube start 命令,Minikube 会自动下载所需的镜像并启动一个单节点的 Kubernetes 集群。

8.2 安装 Knative Serving

在 Minikube 集群上安装 Knative Serving,步骤如下:
1. 安装 Knative CRDs :使用 kubectl 命令部署 Knative Serving 的自定义资源定义(CRD)。

kubectl apply -f https://github.com/knative/serving/releases/download/vX.Y.Z/serving-crds.yaml

注意将 vX.Y.Z 替换为你要安装的 Knative Serving 版本号。
2. 安装 Knative Serving 核心组件 :同样使用 kubectl 命令部署核心组件。

kubectl apply -f https://github.com/knative/serving/releases/download/vX.Y.Z/serving-core.yaml
  1. 等待组件就绪 :使用以下命令检查 Knative Serving 组件是否已成功部署。
kubectl get pods -n knative-serving

确保所有 Pod 都处于 Running 状态。

8.3 部署容器到 Knative Serving

现在可以将一个容器部署到本地的 Knative Serving 中,步骤如下:
1. 创建 Knative 服务定义文件 :例如,创建一个名为 service.yaml 的文件,内容如下:

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: my-service
spec:
  template:
    spec:
      containers:
        - image: gcr.io/your-project/your-image:tag

gcr.io/your-project/your-image:tag 替换为你实际的容器镜像地址。
2. 部署服务 :使用 kubectl 命令部署服务。

kubectl apply -f service.yaml
  1. 检查服务状态 :使用以下命令检查服务是否已成功部署。
kubectl get ksvc my-service

确保服务的 URL 已分配,并且状态为 Ready

9. 云运行与 Knative 服务的对比总结
对比项 云运行(Cloud Run) Knative 服务
部署难度 相对简单,无需管理底层基础设施 需要一定的 Kubernetes 知识,部署和管理相对复杂
可移植性 依赖 Google Cloud 平台,但与 Knative 规范兼容,可迁移 可在不同的 Kubernetes 集群上运行,具有较高的可移植性
功能特性 提供了简化的无服务器体验,功能相对精简 功能更丰富,可自定义性强,可根据需求扩展
成本 按使用量计费,成本相对透明 成本取决于底层 Kubernetes 集群的配置和使用情况
10. 未来展望

随着云计算和容器技术的不断发展,云运行和 Knative 服务都将在无服务器和容器编排领域发挥重要作用。云运行将继续为开发者提供简单、高效的无服务器解决方案,而 Knative 服务作为开源项目,将吸引更多的开发者参与,不断扩展其功能和应用场景。

对于开发者来说,了解云运行和 Knative 服务的特点和使用方法,能够根据项目的需求选择合适的技术方案,提高开发效率和系统的可维护性。同时,掌握分布式跟踪、结构化日志和基于日志的指标等技术,有助于更好地监控和调试应用程序,确保应用的稳定性和性能。

总之,云运行和 Knative 服务为开发者提供了强大的工具和平台,让我们能够更加专注于业务逻辑的实现,而无需过多关注底层基础设施的管理。通过不断学习和实践,我们可以充分发挥这些技术的优势,构建出更加优秀的应用程序。

【电能质量扰动】基于ML和DWT的电能质量扰动分类方法研究(Matlab实现)内容概要:本文研究了一种基于机器学习(ML)和离散小波变换(DWT)的电能质量扰动分类方法,并提供了Matlab实现方案。首先利用DWT对电能质量信号进行多尺度分解,提取信号的时频域特征,有效捕捉电压暂降、暂升、中断、谐波、闪变等常见扰动的关键信息;随后结合机器学习分类器(如SVM、BP神经网络等)对提取的特征进行训练分类,实现对不同类型扰动的自动识别准确区分。该方法充分发挥DWT在信号去噪特征提取方面的优势,结合ML强大的模式识别能力,提升了分类精度鲁棒性,具有较强的实用价值。; 适合人群:电气工程、自动化、电力系统及其自动化等相关专业的研究生、科研人员及从事电能质量监测分析的工程技术人员;具备一定的信号处理基础和Matlab编程能力者更佳。; 使用场景及目标:①应用于智能电网中的电能质量在线监测系统,实现扰动类型的自动识别;②作为高校或科研机构在信号处理、模式识别、电力系统分析等课程的教学案例或科研实验平台;③目标是提高电能质量扰动分类的准确性效率,为后续的电能治理设备保护提供决策依据。; 阅读建议:建议读者结合Matlab代码深入理解DWT的实现过程特征提取步骤,重点关注小波基选择、分解层数设定及特征向量构造对分类性能的影响,并尝试对比不同机器学习模型的分类效果,以全面掌握该方法的核心技术要点。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值