This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

调试与故障排除

帮助用户调试和诊断 Dapr 问题的工具、技术和常见问题

1 - 运行 Dapr 时的常见问题

运行 Dapr 应用程序时遇到的常见问题和故障

本指南涵盖了在安装和运行 Dapr 时可能遇到的常见问题。

安装 Dapr CLI 时 Dapr 无法连接到 Docker

在安装和初始化 Dapr CLI 时,如果运行 dapr init 后看到以下错误消息:

⌛  Making the jump to hyperspace...
❌  could not connect to docker. docker may not be installed or running

通过确保以下内容来排查错误:

  1. 正确的容器正在运行。

  2. 在 Docker Desktop 中,验证已选择 Allow the default Docker socket to be used (requires password) 选项。

我没有看到 Dapr 边车注入到我的 pod 中

边车可能无法注入到 pod 中有多种原因。 首先,检查您的 deployment 或 pod YAML 文件,并检查您是否在正确的位置具有以下注解:

annotations:
  dapr.io/enabled: "true"
  dapr.io/app-id: "nodeapp"
  dapr.io/app-port: "3000"

示例 deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nodeapp
  namespace: default
  labels:
    app: node
spec:
  replicas: 1
  selector:
    matchLabels:
      app: node
  template:
    metadata:
      labels:
        app: node
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "nodeapp"
        dapr.io/app-port: "3000"
    spec:
      containers:
      - name: node
        image: dapriosamples/hello-k8s-node
        ports:
        - containerPort: 3000
        imagePullPolicy: Always

在某些已知情况下,这可能无法正常工作:

  • 如果您的 pod 规范模板已正确注解,但您仍然没有看到边车注入,请确保 Dapr 在您的 deployment 或 pod 部署之前已部署到集群。

    如果是这种情况,重启 pod 将解决此问题。

  • 如果您在私有 GKE 集群上部署 Dapr,边车注入在无需额外步骤的情况下无法工作。请参阅设置 Google Kubernetes Engine 集群。

    为了进一步诊断任何问题,请检查 Dapr 边车注入器的日志:

     kubectl logs -l app=dapr-sidecar-injector -n dapr-system
    

    注意:如果您将 Dapr 安装到不同的命名空间,请将上面的 dapr-system 替换为所需的命名空间

  • 如果您在 Amazon EKS 上部署 Dapr 并使用 Calico 等覆盖网络,您需要将 hostNetwork 参数设置为 true,这是使用此类 CNI 的 EKS 的限制。

    您可以使用 Helm values.yaml 文件设置此参数:

    helm upgrade --install dapr dapr/dapr \
    --namespace dapr-system \
    --create-namespace \
    --values values.yaml
    

    values.yaml

    dapr_sidecar_injector:
      hostNetwork: true
    

    或使用命令行:

    helm upgrade --install dapr dapr/dapr \
    --namespace dapr-system \
    --create-namespace \
    --set dapr_sidecar_injector.hostNetwork=true
    
  • 确保 kube api 服务器可以到达以下 webhook 服务:

    请与您的集群管理员联系,以设置允许从 kube api 服务器到集群中上述端口 4000 和 19443 的入站规则。

我的 pod 处于 CrashLoopBackoff 或其他由于 daprd 边车导致的失败状态

如果 Dapr 边车 (daprd) 初始化时间过长,这可能被 Kubernetes 显示为运行状况检查失败。

如果您的 pod 处于失败状态,您应该检查以下内容:

kubectl describe pod <name-of-pod>

您可能会在命令输出的末尾看到如下表格:

  Normal   Created    7m41s (x2 over 8m2s)   kubelet, aks-agentpool-12499885-vmss000000  Created container daprd
  Normal   Started    7m41s (x2 over 8m2s)   kubelet, aks-agentpool-12499885-vmss000000  Started container daprd
  Warning  Unhealthy  7m28s (x5 over 7m58s)  kubelet, aks-agentpool-12499885-vmss000000  Readiness probe failed: Get http://10.244.1.10:3500/v1.0/healthz: dial tcp 10.244.1.10:3500: connect: connection refused
  Warning  Unhealthy  7m25s (x6 over 7m55s)  kubelet, aks-agentpool-12499885-vmss000000  Liveness probe failed: Get http://10.244.1.10:3500/v1.0/healthz: dial tcp 10.244.1.10:3500: connect: connection refused
  Normal   Killing    7m25s (x2 over 7m43s)  kubelet, aks-agentpool-12499885-vmss000000  Container daprd failed liveness probe, will be restarted
  Warning  BackOff    3m2s (x18 over 6m48s)  kubelet, aks-agentpool-12499885-vmss000000  Back-off restarting failed container

消息 Container daprd failed liveness probe, will be restarted 表示 Dapr 边车未能通过其运行状况检查并将被重启。消息 Readiness probe failed: Get http://10.244.1.10:3500/v1.0/healthz: dial tcp 10.244.1.10:3500: connect: connection refused 和 Liveness probe failed: Get http://10.244.1.10:3500/v1.0/healthz: dial tcp 10.244.1.10:3500: connect: connection refused 显示运行状况检查失败,因为无法建立到边车的连接。

此失败的最常见原因是组件(例如状态存储)配置错误,导致初始化时间过长。当初始化耗时较长时,运行状况检查可能会在边车记录任何有用的信息之前终止边车。

要诊断根本原因:

  • 显著增加存活探针延迟 - 链接
  • 将边车的日志级别设置为 debug - 链接
  • 观察日志以获取有意义的信息 - 链接

请记得在解决问题后将存活检查延迟和日志级别配置回所需的值。

我无法保存状态或获取状态

您是否在集群中安装了 Dapr 状态存储?

要检查,请使用 kubectl 获取组件列表:

kubectl get components

如果没有状态存储组件,这意味着您需要设置一个。 访问这里了解更多详情。

如果一切设置正确,请确保您的凭据正确。 搜索 Dapr 运行时日志并查找任何状态存储错误:

kubectl logs <name-of-pod> daprd

我无法发布和接收事件

您是否在集群中安装了 Dapr 消息总线?

要检查,请使用 kubectl 获取组件列表:

kubectl get components

如果没有发布订阅组件,这意味着您需要设置一个。 访问这里了解更多详情。

如果一切设置正确,请确保您的凭据正确。 搜索 Dapr 运行时日志并查找任何发布订阅错误:

kubectl logs <name-of-pod> daprd

调用 Dapr 时收到 500 错误响应

这意味着 Dapr 运行时内部存在一些问题。 要诊断,请查看边车的日志:

kubectl logs <name-of-pod> daprd

调用 Dapr 时收到 404 Not Found 响应

这意味着您正在尝试调用一个不存在或 URL 格式错误的 Dapr API 端点。 查看这里的 Dapr API 参考,并确保您调用了正确的端点。

我没有看到来自其他服务的传入事件或调用

您是否指定了您的应用程序正在侦听的端口? 在 Kubernetes 中,确保指定了 dapr.io/app-port 注解:

annotations:
  dapr.io/enabled: "true"
  dapr.io/app-id: "nodeapp"
  dapr.io/app-port: "3000"

如果使用 Dapr Standalone 和 Dapr CLI,请确保将 --app-port 标志传递给 dapr run 命令。

我的启用 Dapr 的应用程序行为不正确

首先要做的是检查从 Dapr API 返回的 HTTP 错误代码(如果有)。 如果您仍然找不到问题,请尝试为 Dapr 运行时启用 debug 日志级别。请参阅这里了解如何执行此操作。

您可能还希望查看您自己进程的错误日志。如果在 Kubernetes 上运行,请找到包含您的应用程序的 pod,并执行以下命令:

kubectl logs <pod-name> <name-of-your-container>

如果在 Standalone 模式下运行,您应该在主控制台会话中看到来自您应用程序的 stderr 和 stdout 输出。

在本地运行 Actors 时出现超时/连接错误

每个 Dapr 实例都会将其主机地址报告给 placement 服务。然后,placement 服务将节点表及其地址分发给所有 Dapr 实例。如果该主机地址不可达,您可能会遇到套接字超时错误或其他请求失败的变体。

除非通过将名为 DAPR_HOST_IP 的环境变量设置为可访问、可 ping 的地址来指定主机名,否则 Dapr 将循环遍历网络接口并选择它找到的第一个非环回地址。

如上所述,为了告诉 Dapr 应该使用什么主机名,只需设置一个名为 DAPR_HOST_IP 的环境变量。

以下示例展示了如何将主机 IP 环境变量设置为 127.0.0.1:

注意:对于 <= 0.4.0 版本,使用 HOST_IP

export DAPR_HOST_IP=127.0.0.1

当我的应用程序启动时,我的组件都没有被加载。我一直收到"Error component X cannot be found"

这通常是由于以下问题之一

  • 您可能在本地定义了 NAMESPACE 环境变量,或者将组件部署到 Kubernetes 中的不同命名空间。检查您的应用程序和组件部署到哪个命名空间。阅读将组件限定为一个或多个应用程序以获取更多信息。
  • 您可能没有为 Dapr run 命令提供 --resources-path,或者没有将组件放入您操作系统的默认组件文件夹中。阅读定义组件以获取更多信息。
  • 您可能在组件 YAML 文件中有语法问题。使用组件 YAML 示例检查您的组件 YAML。

服务调用失败,我的 Dapr 服务缺少 appId(macOS)

某些组织将实现过滤掉所有 UDP 流量的软件,这是 mDNS 所基于的。最常见的是,在 MacOS 上,Microsoft Content Filter 是罪魁祸首。

为了使 mDNS 正常运行,请确保 Microsoft Content Filter 处于非活动状态。

  • 打开终端 shell。
  • 输入 mdatp system-extension network-filter disable 并按回车键。
  • 输入您的帐户密码。

当输出为"Success"时,Microsoft Content Filter 已被禁用。

某些组织会不时重新启用过滤器。如果您反复遇到 app-id 值缺失的情况,在进行更广泛的故障排除之前,请首先检查过滤器是否已重新启用。

Admission webhook 拒绝了请求

您可能会遇到与以下类似的错误,由于 admission webhook 对服务帐户创建或修改资源有允许列表。

root:[dapr]$ kubectl run -i --tty --rm debug --image=busybox --restart=Never -- sh
Error from server: admission webhook "sidecar-injector.dapr.io" denied the request: service account 'user-xdd5l' not on the list of allowed controller accounts

要解决此错误,您应该为当前用户创建一个 clusterrolebind:

kubectl create clusterrolebinding dapr-<name-of-user> --clusterrole=dapr-operator-admin --user <name-of-user>

您可以运行以下命令来获取集群中的所有用户:

kubectl config get-users

您可以在这里了解更多关于 webhook 的信息。

dapr init 期间端口不可用

在 Windows 上尝试执行 dapr init 后,您可能会遇到以下错误:

PS C:\Users\You> dapr init Making the jump to hyperspace… Container images will be pulled from Docker Hub Installing runtime version 1.14.4 Downloading binaries and setting up components… docker: Error response from daemon: Ports are not available: exposing port TCP 0.0.0.0:52379 -> 0.0.0.0:0: listen tcp4 0.0.0.0:52379: bind: An attempt was made to access a socket in a way forbidden by its access permissions.

要解决此错误,请在提升的终端中打开命令提示符并运行:

net stop winnat
dapr init
net start winnat

2 - 配置和查看 Dapr 日志

了解 Dapr 中的日志工作原理以及如何配置和查看日志

本节将帮助您了解 Dapr 中的日志工作原理,以及如何配置和查看日志。

概述

日志具有不同的、可配置的详细程度级别。 下面列出的级别对于系统组件和 Dapr 边车进程/容器都是相同的:

  1. error
  2. warn
  3. info
  4. debug

error 产生最少的输出,而 debug 产生最多的输出。默认级别是 info,它在正常条件下运行 Dapr 时提供平衡的信息量。

要设置输出级别,您可以使用 --log-level 命令行选项。例如:

./daprd --log-level error
./placement --log-level debug

这将启动日志级别为 error 的 Dapr 运行时二进制文件和日志级别为 debug 的 Dapr Actor Placement 服务。

独立模式下的日志

在使用 Dapr CLI 运行应用时设置日志级别,传递 log-level 参数:

dapr run --log-level warn node myapp.js

如上所述,每个 Dapr 二进制文件都接受 --log-level 参数。例如,要使用警告日志级别启动 placement 服务:

./placement --log-level warn

在独立模式下查看日志

使用 Dapr CLI 运行 Dapr 时,您的应用的日志输出和运行时的输出都将被重定向到同一会话中,以便于调试。 例如,这是运行 Dapr 时的输出:

dapr run node myapp.js
ℹ️  Starting Dapr with id Trackgreat-Lancer on port 56730
✅  You are up and running! Both Dapr and your app logs will appear here.

== APP == App listening on port 3000!
== DAPR == time="2019-09-05T12:26:43-07:00" level=info msg="starting Dapr Runtime -- version 0.3.0-alpha -- commit b6f2810-dirty"
== DAPR == time="2019-09-05T12:26:43-07:00" level=info msg="log level set to: info"
== DAPR == time="2019-09-05T12:26:43-07:00" level=info msg="standalone mode configured"
== DAPR == time="2019-09-05T12:26:43-07:00" level=info msg="app id: Trackgreat-Lancer"
== DAPR == time="2019-09-05T12:26:43-07:00" level=info msg="loaded component statestore (state.redis)"
== DAPR == time="2019-09-05T12:26:43-07:00" level=info msg="loaded component messagebus (pubsub.redis)"
== DAPR == 2019/09/05 12:26:43 redis: connecting to localhost:6379
== DAPR == 2019/09/05 12:26:43 redis: connected to localhost:6379 (localAddr: [::1]:56734, remAddr: [::1]:6379)
== DAPR == time="2019-09-05T12:26:43-07:00" level=warn msg="failed to init input bindings: app channel not initialized"
== DAPR == time="2019-09-05T12:26:43-07:00" level=info msg="actor runtime started. actor idle timeout: 1h0m0s. actor scan interval: 30s"
== DAPR == time="2019-09-05T12:26:43-07:00" level=info msg="actors: starting connection attempt to placement service at localhost:50005"
== DAPR == time="2019-09-05T12:26:43-07:00" level=info msg="http server is running on port 56730"
== DAPR == time="2019-09-05T12:26:43-07:00" level=info msg="gRPC server is running on port 56731"
== DAPR == time="2019-09-05T12:26:43-07:00" level=info msg="dapr initialized. Status: Running. Init Elapsed 8.772922000000001ms"
== DAPR == time="2019-09-05T12:26:43-07:00" level=info msg="actors: established connection to placement service at localhost:50005"

Kubernetes 模式下的日志

了解如何在 Kubernetes 上调试 daprd。

您可以通过在 pod 规范模板中提供以下注释来为每个边车单独设置日志级别:

annotations:
  dapr.io/log-level: "debug"

设置系统 Pod 的日志级别

使用 Helm 3.x 将 Dapr 部署到集群时,您可以为每个 Dapr 系统组件单独设置日志级别:

helm install dapr dapr/dapr --namespace dapr-system --set <COMPONENT>.logLevel=<LEVEL>

组件:

  • dapr_operator
  • dapr_placement
  • dapr_sidecar_injector

示例:

helm install dapr dapr/dapr --namespace dapr-system --set dapr_operator.logLevel=error

在 Kubernetes 上查看日志

Dapr 日志被写入 stdout 和 stderr。 本节将指导您如何查看 Dapr 系统组件以及 Dapr 边车的日志。

边车日志

在 Kubernetes 中部署时,Dapr 边车注入器会将名为 daprd 的 Dapr 容器注入到带注释的 pod 中。 要查看边车的日志,只需运行 kubectl get pods 找到相关 pod:

NAME                                        READY     STATUS    RESTARTS   AGE
addapp-74b57fb78c-67zm6                     2/2       Running   0          40h

接下来,获取 Dapr 边车容器的日志:

kubectl logs addapp-74b57fb78c-67zm6 -c daprd

time="2019-09-04T02:52:27Z" level=info msg="starting Dapr Runtime -- version 0.3.0-alpha -- commit b6f2810-dirty"
time="2019-09-04T02:52:27Z" level=info msg="log level set to: info"
time="2019-09-04T02:52:27Z" level=info msg="kubernetes mode configured"
time="2019-09-04T02:52:27Z" level=info msg="app id: addapp"
time="2019-09-04T02:52:27Z" level=info msg="application protocol: http. waiting on port 6000"
time="2019-09-04T02:52:27Z" level=info msg="application discovered on port 6000"
time="2019-09-04T02:52:27Z" level=info msg="actor runtime started. actor idle timeout: 1h0m0s. actor scan interval: 30s"
time="2019-09-04T02:52:27Z" level=info msg="actors: starting connection attempt to placement service at dapr-placement.dapr-system.svc.cluster.local:80"
time="2019-09-04T02:52:27Z" level=info msg="http server is running on port 3500"
time="2019-09-04T02:52:27Z" level=info msg="gRPC server is running on port 50001"
time="2019-09-04T02:52:27Z" level=info msg="dapr initialized. Status: Running. Init Elapsed 64.234049ms"
time="2019-09-04T02:52:27Z" level=info msg="actors: established connection to placement service at dapr-placement.dapr-system.svc.cluster.local:80"

系统日志

Dapr 运行以下系统 Pod:

  • Dapr operator
  • Dapr sidecar injector
  • Dapr placement service

Operator 日志

kubectl logs -l app=dapr-operator -n dapr-system

I1207 06:01:02.891031 1 leaderelection.go:243] attempting to acquire leader lease dapr-system/operator.dapr.io...
I1207 06:01:02.913696 1 leaderelection.go:253] successfully acquired lease dapr-system/operator.dapr.io
time="2021-12-07T06:01:03.092529085Z" level=info msg="getting tls certificates" instance=dapr-operator-84bb47f895-dvbsj scope=dapr.operator type=log ver=unknown
time="2021-12-07T06:01:03.092703283Z" level=info msg="tls certificates loaded successfully" instance=dapr-operator-84bb47f895-dvbsj scope=dapr.operator type=log ver=unknown
time="2021-12-07T06:01:03.093062379Z" level=info msg="starting gRPC server" instance=dapr-operator-84bb47f895-dvbsj scope=dapr.operator.api type=log ver=unknown
time="2021-12-07T06:01:03.093123778Z" level=info msg="Healthz server is listening on :8080" instance=dapr-operator-84bb47f895-dvbsj scope=dapr.operator type=log ver=unknown
time="2021-12-07T06:01:03.497889776Z" level=info msg="starting webhooks" instance=dapr-operator-84bb47f895-dvbsj scope=dapr.operator type=log ver=unknown
I1207 06:01:03.497944 1 leaderelection.go:243] attempting to acquire leader lease dapr-system/webhooks.dapr.io...
I1207 06:01:03.516641 1 leaderelection.go:253] successfully acquired lease dapr-system/webhooks.dapr.io
time="2021-12-07T06:01:03.526202227Z" level=info msg="Successfully patched webhook in CRD "subscriptions.dapr.io"" instance=dapr-operator-84bb47f895-dvbsj scope=dapr.operator type=log ver=unknown

注意:如果 Dapr 被安装到 dapr-system 以外的命名空间,只需在上述命令中将命名空间替换为所需的命名空间

边车注入器日志

kubectl logs -l app=dapr-sidecar-injector -n dapr-system

time="2021-12-07T06:01:01.554859058Z" level=info msg="log level set to: info" instance=dapr-sidecar-injector-5d88fcfcf5-2gmvv scope=dapr.injector type=log ver=unknown
time="2021-12-07T06:01:01.555114755Z" level=info msg="metrics server started on :9090/" instance=dapr-sidecar-injector-5d88fcfcf5-2gmvv scope=dapr.metrics type=log ver=unknown
time="2021-12-07T06:01:01.555233253Z" level=info msg="starting Dapr Sidecar Injector -- version 1.5.1 -- commit c6daae8e9b11b3e241a9cb84c33e5aa740d74368" instance=dapr-sidecar-injector-5d88fcfcf5-2gmvv scope=dapr.injector type=log ver=unknown
time="2021-12-07T06:01:01.557646524Z" level=info msg="Healthz server is listening on :8080" instance=dapr-sidecar-injector-5d88fcfcf5-2gmvv scope=dapr.injector type=log ver=unknown
time="2021-12-07T06:01:01.621291968Z" level=info msg="Sidecar injector is listening on :4000, patching Dapr-enabled pods" instance=dapr-sidecar-injector-5d88fcfcf5-2gmvv scope=dapr.injector type=log ver=unknown

注意:如果 Dapr 被安装到 dapr-system 以外的命名空间,只需在上述命令中将命名空间替换为所需的命名空间

查看 Placement 服务日志

kubectl logs -l app=dapr-placement-server -n dapr-system

time="2021-12-04T05:08:05.733416791Z" level=info msg="starting Dapr Placement Service -- version 1.5.0 -- commit 83fe579f5dc93bef1ce3b464d3167a225a3aff3a" instance=dapr-placement-server-0 scope=dapr.placement type=log ver=unknown
time="2021-12-04T05:08:05.733469491Z" level=info msg="log level set to: info" instance=dapr-placement-server-0 scope=dapr.placement type=log ver=1.5.0
time="2021-12-04T05:08:05.733512692Z" level=info msg="metrics server started on :9090/" instance=dapr-placement-server-0 scope=dapr.metrics type=log ver=1.5.0
time="2021-12-04T05:08:05.735207095Z" level=info msg="Raft server is starting on 127.0.0.1:8201..." instance=dapr-placement-server-0 scope=dapr.placement.raft type=log ver=1.5.0
time="2021-12-04T05:08:05.735221195Z" level=info msg="mTLS enabled, getting tls certificates" instance=dapr-placement-server-0 scope=dapr.placement type=log ver=1.5.0
time="2021-12-04T05:08:05.735265696Z" level=info msg="tls certificates loaded successfully" instance=dapr-placement-server-0 scope=dapr.placement type=log ver=1.5.0
time="2021-12-04T05:08:05.735276396Z" level=info msg="placement service started on port 50005" instance=dapr-placement-server-0 scope=dapr.placement type=log ver=1.5.0
time="2021-12-04T05:08:05.735553696Z" level=info msg="Healthz server is listening on :8080" instance=dapr-placement-server-0 scope=dapr.placement type=log ver=1.5.0
time="2021-12-04T05:08:07.036850257Z" level=info msg="cluster leadership acquired" instance=dapr-placement-server-0 scope=dapr.placement type=log ver=1.5.0
time="2021-12-04T05:08:07.036909357Z" level=info msg="leader is established." instance=dapr-placement-server-0 scope=dapr.placement type=log ver=1.5.0

注意:如果 Dapr 被安装到 dapr-system 以外的命名空间,只需在上述命令中将命名空间替换为所需的命名空间

非 Kubernetes 环境

上面的示例专门针对 Kubernetes,但原理对于任何基于容器的环境都是相同的:只需获取 Dapr 边车和/或系统组件(如适用)的容器 ID 并查看其日志。

参考

3 - Dapr API 日志

了解 Dapr 中的 API 日志记录是如何工作的以及如何查看日志

API 日志记录使您能够查看您的应用程序向 Dapr 边车发出的 API 调用。这对于监控应用程序的行为或其他调试目的非常有用。您还可以将 Dapr API 日志记录与 Dapr 日志事件(参见 配置和查看 Dapr 日志)结合到输出中,以便一起使用日志记录功能。

概述

默认情况下,API 日志记录是禁用的。

要启用 API 日志记录,可以在启动 daprd 进程时使用 --enable-api-logging 命令行选项。例如:

./daprd --enable-api-logging

在自托管模式下配置 API 日志记录

要在使用 Dapr CLI 运行应用程序时启用 API 日志记录,请传递 --enable-api-logging 标志:

dapr run \
  --enable-api-logging \
  -- node myapp.js

在自托管模式下查看 API 日志

当使用 Dapr CLI 运行 Dapr 时,您的应用程序日志输出和 Dapr 运行时日志输出都会被重定向到同一个会话中,以便于调试。

下面的示例显示了一些 API 日志:

$ dapr run --enable-api-logging -- node myapp.js

ℹ️  Starting Dapr with id order-processor on port 56730
✅  You are up and running! Both Dapr and your app logs will appear here.
.....
INFO[0000] HTTP API Called app_id=order-processor instance=mypc method="POST /v1.0/state/mystate" scope=dapr.runtime.http-info type=log useragent=Go-http-client/1.1 ver=edge
== APP == INFO:root:Saving Order: {'orderId': '483'}
INFO[0000] HTTP API Called app_id=order-processor instance=mypc method="GET /v1.0/state/mystate/key123" scope=dapr.runtime.http-info type=log useragent=Go-http-client/1.1 ver=edge
== APP == INFO:root:Getting Order: {'orderId': '483'}
INFO[0000] HTTP API Called app_id=order-processor instance=mypc method="DELETE /v1.0/state/mystate" scope=dapr.runtime.http-info type=log useragent=Go-http-client/1.1 ver=edge
== APP == INFO:root:Deleted Order: {'orderId': '483'}
INFO[0000] HTTP API Called app_id=order-processor instance=mypc method="PUT /v1.0/metadata/cliPID" scope=dapr.runtime.http-info type=log useragent=Go-http-client/1.1 ver=edge

在 Kubernetes 中配置 API 日志记录

您可以通过在 Pod 规范模板中添加以下注解来为边车启用 API 日志:

annotations:
  dapr.io/enable-api-logging: "true"

在 Kubernetes 上查看 API 日志

Dapr API 日志会被写入 stdout 和 stderr,您可以在 Kubernetes 上查看 API 日志。

执行以下命令以查看 Kubernetes API 日志。

kubectl logs <pod_name> daprd -n <name_space>

下面的示例显示了 Kubernetes 中 info 级别的 API 日志记录(启用了 URL 混淆)。

time="2022-03-16T18:32:02.487041454Z" level=info msg="HTTP API Called" method="POST /v1.0/invoke/{id}/method/{method:*}" app_id=invoke-caller instance=invokecaller-f4f949886-cbnmt scope=dapr.runtime.http-info type=log useragent=Go-http-client/1.1 ver=edge
time="2022-03-16T18:32:02.698387866Z" level=info msg="HTTP API Called" method="POST /v1.0/invoke/{id}/method/{method:*}" app_id=invoke-caller instance=invokecaller-f4f949886-cbnmt scope=dapr.runtime.http-info type=log useragent=Go-http-client/1.1 ver=edge
time="2022-03-16T18:32:02.917629403Z" level=info msg="HTTP API Called" method="POST /v1.0/invoke/{id}/method/{method:*}" app_id=invoke-caller instance=invokecaller-f4f949886-cbnmt scope=dapr.runtime.http-info type=log useragent=Go-http-client/1.1 ver=edge
time="2022-03-16T18:32:03.137830112Z" level=info msg="HTTP API Called" method="POST /v1.0/invoke/{id}/method/{method:*}" app_id=invoke-caller instance=invokecaller-f4f949886-cbnmt scope=dapr.runtime.http-info type=log useragent=Go-http-client/1.1 ver=edge
time="2022-03-16T18:32:03.359097916Z" level=info msg="HTTP API Called" method="POST /v1.0/invoke/{id}/method/{method:*}" app_id=invoke-caller instance=invokecaller-f4f949886-cbnmt scope=dapr.runtime.http-info type=log useragent=Go-http-client/1.1 ver=edge

API 日志记录配置

使用 Dapr 配置规范,您可以配置 Dapr 运行时中 API 日志记录的默认行为。

默认启用 API 日志记录

使用 Dapr 配置规范,您可以通过 logging.apiLogging.enabled 选项设置 --enable-api-logging 标志(以及在 Kubernetes 上运行时对应的注解)的默认值。此值适用于引用定义该选项的配置文档或资源的所有 Dapr 运行时。

  • 如果 logging.apiLogging.enabled 设置为 false(默认值),则除非将 --enable-api-logging 设置为 true(或添加 dapr.io/enable-api-logging: true 注解),否则 Dapr 运行时的 API 日志记录将被禁用。
  • 当 logging.apiLogging.enabled 为 true 时,Dapr 运行时默认启用 API 日志记录,可以通过设置 --enable-api-logging=false 或使用 dapr.io/enable-api-logging: false 注解来禁用。

例如:

logging:
  apiLogging:
    enabled: true

在 HTTP API 日志记录中混淆 URL

默认情况下,HTTP 端点中 API 调用的日志包含被调用的完整 URL(例如,POST /v1.0/invoke/directory/method/user-123),其中可能包含个人身份信息(PII)。

为了降低 PII 意外包含在 API 日志中的风险(启用时),Dapr 可以改为记录被调用的抽象路由(例如,POST /v1.0/invoke/{id}/method/{method:*})。这有助于确保遵守 GDPR 等隐私法规。

要在 Dapr 的 HTTP API 日志中启用 URL 混淆,请将 logging.apiLogging.obfuscateURLs 设置为 true。例如:

logging:
  apiLogging:
    obfuscateURLs: true

Dapr gRPC API 发出的日志不受此配置选项的影响,因为它们仅包含被调用方法的名称,不包含参数。

从 API 日志记录中省略健康检查

当启用 API 日志记录时,对 Dapr API 服务器的所有调用都会被记录,包括对健康检查端点的调用(例如 /v1.0/healthz)。根据您的环境,这每分钟可能会生成多个日志行,并可能产生不必要的噪音。

您可以使用 Dapr 配置规范配置 Dapr 在启用 API 日志记录时不记录对健康检查端点的调用,方法是将 logging.apiLogging.omitHealthChecks 设置为 true。默认值为 false,这意味着健康检查调用会记录在 API 日志中。

例如:

logging:
  apiLogging:
    omitHealthChecks: true

4 - 性能分析与调试

通过性能分析会话发现并发、性能、CPU 和内存使用等方面的问题和隐患

在任何真实场景中,应用程序可能会出现资源方面的异常行为。 在大多数情况下,CPU/内存飙升并不罕见。

Dapr 允许用户通过其性能分析服务端点使用 pprof 启动按需性能分析会话,并启动检测会话以发现并发、性能、CPU 和内存使用等方面的问题和隐患。

启用性能分析

Dapr 允许您在 Kubernetes 和独立模式两种模式下启用性能分析。

独立模式

要在独立模式下启用性能分析,请将 --enable-profiling 和 --profile-port 标志传递给 Dapr CLI: 请注意 profile-port 不是必需的,如果未提供,Dapr 将选择一个可用端口。

dapr run --enable-profiling --profile-port 7777 python myapp.py

Kubernetes

要在 Kubernetes 中启用性能分析,只需将 dapr.io/enable-profiling 注解添加到您的 Dapr 注解 pod 中:

   annotations:
    dapr.io/enabled: "true"
    dapr.io/app-id: "rust-app"
    dapr.io/enable-profiling: "true"

调试性能分析会话

启用性能分析后,我们可以启动性能分析会话来调查 Dapr 运行时发生了什么。

独立模式

对于独立模式,找到您想要分析的 Dapr 实例:

dapr list
APP ID           DAPR PORT     APP PORT  COMMAND      AGE  CREATED              PID
node-subscriber  3500          3000      node app.js  12s  2019-09-09 15:11.24  896

获取 DAPR PORT,如果已按照上述说明启用了性能分析,您现在可以开始使用 pprof 来分析 Dapr。 查看上面的 Kubernetes 示例,获取一些用于分析 Dapr 的有用命令。

有关 pprof 的更多信息可以在这里找到。

Kubernetes

首先,找到包含 Dapr 运行时的 pod。如果您还不知道 pod 名称,请输入 kubectl get pods:

NAME                                        READY     STATUS    RESTARTS   AGE
divideapp-6dddf7dc74-6sq4l                  2/2       Running   0          2d23h

如果性能分析已成功启用,运行时日志应显示以下内容: time="2019-09-09T20:56:21Z" level=info msg="starting profiling server on port 7777"

在这种情况下,我们要与 pod divideapp-6dddf7dc74-6sq4l 内的 Dapr 运行时启动会话。

我们可以通过端口转发连接到 pod 来实现:

kubectl port-forward divideapp-6dddf7dc74-6sq4 7777:7777
Forwarding from 127.0.0.1:7777 -> 7777
Forwarding from [::1]:7777 -> 7777
Handling connection for 7777

既然连接已经建立,我们可以使用 pprof 来分析 Dapr 运行时。

以下示例将创建一个 cpu.pprof 文件,其中包含持续 120 秒的性能分析会话的采样:

curl "http://localhost:7777/debug/pprof/profile?seconds=120" > cpu.pprof

使用 pprof 分析文件:

pprof cpu.pprof

您还可以将结果以可视化方式保存到 PDF 中:

go tool pprof --pdf your-binary-file http://localhost:7777/debug/pprof/profile?seconds=120 > profile.pdf

对于内存相关问题,您可以分析堆:

go tool pprof --pdf your-binary-file http://localhost:7777/debug/pprof/heap > heap.pdf

heap

分析已分配的对象:

go tool pprof http://localhost:7777/debug/pprof/heap
> exit

Saved profile in /Users/myusername/pprof/pprof.daprd.alloc_objects.alloc_space.inuse_objects.inuse_space.003.pb.gz

要进行分析,请获取上面的文件路径(这是一个动态文件路径,所以请注意记录并粘贴这个路径),然后执行:

go tool pprof -alloc_objects --pdf /Users/myusername/pprof/pprof.daprd.alloc_objects.alloc_space.inuse_objects.inuse_space.003.pb.gz > alloc-objects.pdf

alloc