This is the multi-page printable view of this section. Click here to print.
调试与故障排除
- 1: 运行 Dapr 时的常见问题
- 2: 配置和查看 Dapr 日志
- 3: Dapr API 日志
- 4: 性能分析与调试
1 - 运行 Dapr 时的常见问题
本指南涵盖了安装和运行 Dapr 时可能遇到的常见问题。
安装 Dapr CLI 时 Dapr 无法连接到 Docker
在安装和初始化 Dapr CLI 时,如果在运行 dapr init
后看到以下错误信息:
⌛ 正在进行初始化...
❌ 无法连接到 Docker。Docker 可能未安装或未运行
请通过以下步骤进行排查:
在 Docker Desktop 中,确认已选择 允许使用默认 Docker 套接字(需要密码) 选项。
我没有看到 Dapr sidecar 注入到我的 pod 中
sidecar 未注入到 pod 中可能有多种原因。首先,检查您的部署或 pod YAML 文件,确保在正确的位置有以下注释:
annotations:
dapr.io/enabled: "true"
dapr.io/app-id: "nodeapp"
dapr.io/app-port: "3000"
示例部署:
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 规范模板注释正确,但仍未看到 sidecar 注入,请确保在部署或 pod 部署之前,Dapr 已部署到集群中。
如果是这种情况,重启 pod 将解决问题。
如果您在私有 GKE 集群上部署 Dapr,sidecar 注入在没有额外步骤的情况下不起作用。请参阅 设置 Google Kubernetes Engine 集群。
为了进一步诊断任何问题,请检查 Dapr sidecar 注入器的日志:
kubectl logs -l app=dapr-sidecar-injector -n dapr-system
注意:如果您将 Dapr 安装到不同的命名空间,请将上面的 dapr-system 替换为所需的命名空间
如果您在 Amazon EKS 上部署 Dapr 并使用诸如 Calico 的覆盖网络,您需要将
hostNetwork
参数设置为 true,这是 EKS 在此类 CNI 上的限制。您可以使用 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 服务:
- Sidecar Mutating Webhook Injector Service 在端口 4000,由 sidecar 注入器提供服务。
- Resource Conversion Webhook Service 在端口 19443,由 operator 提供服务。
请与您的集群管理员联系,以设置允许从 kube api 服务器到上述端口 4000 和 19443 的入口规则。
由于 daprd sidecar,我的 pod 处于 CrashLoopBackoff 或其他失败状态
如果 Dapr sidecar (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 sidecar 未通过健康检查并将被重启。消息 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
表明健康检查失败是因为无法连接到 sidecar。
此故障的最常见原因是某个组件(如状态存储)配置错误,导致初始化时间过长。当初始化时间过长时,健康检查可能会在 sidecar 记录任何有用信息之前终止它。
要诊断根本原因:
解决问题后,请记得将存活检查延迟和日志级别配置回您期望的值。
我无法保存状态或获取状态
您是否在集群中安装了 Dapr 状态存储?
要检查,请使用 kubectl 获取组件列表:
kubectl get components
如果没有状态存储组件,则意味着您需要设置一个。 访问 这里 了解更多详细信息。
如果一切设置正确,请确保您获得了正确的凭据。 搜索 Dapr 运行时日志并查找任何状态存储错误:
kubectl logs <name-of-pod> daprd
我无法发布和接收事件
您是否在集群中安装了 Dapr 消息总线?
要检查,请使用 kubectl 获取组件列表:
kubectl get components
如果没有 pub/sub 组件,则意味着您需要设置一个。 访问 这里 了解更多详细信息。
如果一切设置正确,请确保您获得了正确的凭据。 搜索 Dapr 运行时日志并查找任何 pub/sub 错误:
kubectl logs <name-of-pod> daprd
调用 Dapr 时收到 500 错误响应
这意味着 Dapr 运行时内部存在一些问题。 要诊断,请查看 sidecar 的日志:
kubectl logs <name-of-pod> daprd
调用 Dapr 时收到 404 未找到响应
这意味着您正在尝试调用一个不存在的 Dapr API 端点或 URL 格式错误。 查看 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 输出。
本地运行 actor 时出现超时/连接错误
每个 Dapr 实例都会向放置服务报告其主机地址。放置服务然后将节点及其地址的表分发给所有 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
我的应用程序启动时没有加载任何组件。我不断收到“错误组件 X 找不到”
这通常是由于以下问题之一
- 您可能在本地定义了
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 值丢失,首先检查过滤器是否已重新启用,然后再进行更广泛的故障排除。
准入 webhook 拒绝了请求
由于准入 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
您可以在 这里 了解有关 webhooks 的更多信息。
2 - 配置和查看 Dapr 日志
本节将帮助您了解 Dapr 中日志的工作原理,以及如何配置和查看日志。
概述
日志有不同的可配置级别。 以下列出的级别适用于系统组件和 Dapr sidecar 进程/容器:
- error
- warn
- info
- debug
error 级别输出最少,而 debug 级别输出最多。默认级别是 info,它在正常情况下为操作 Dapr 提供了足够的信息。
要设置输出级别,可以使用 --log-level
命令行选项。例如:
./daprd --log-level error
./placement --log-level debug
这将以 error
日志级别启动 Dapr 运行时二进制文件,并以 debug
日志级别启动 Dapr actor 放置服务。
独立模式下的日志
在使用 Dapr CLI 运行应用程序时,可以通过传递 log-level
参数来设置日志级别:
dapr run --log-level warn node myapp.js
如上所述,每个 Dapr 二进制文件都接受一个 --log-level
参数。例如,要以警告级别启动放置服务:
./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 模式下的日志
您可以通过在 pod 规范模板中提供以下注释,为每个 sidecar 单独设置日志级别:
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 sidecar 的日志。
Sidecar 日志
在 Kubernetes 中部署时,Dapr sidecar 注入器会将一个名为 daprd
的 Dapr 容器注入到您的注释 pod 中。
要查看 sidecar 的日志,只需通过运行 kubectl get pods
找到相关的 pod:
NAME READY STATUS RESTARTS AGE
addapp-74b57fb78c-67zm6 2/2 Running 0 40h
接下来,获取 Dapr sidecar 容器的日志:
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 注入器
- Dapr 放置服务
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,只需在上述命令中将命名空间替换为所需的命名空间
Sidecar 注入器日志
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,只需在上述命令中将命名空间替换为所需的命名空间
查看放置服务日志
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 sidecar 和/或系统组件(如果适用)的容器 ID 并查看其日志。
参考资料
3 - Dapr API 日志
API 日志记录可以让您查看应用程序对 Dapr sidecar 的 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 规范模板中添加以下注释来为 sidecar 启用 API 日志:
annotations:
dapr.io/enable-api-logging: "true"
在 Kubernetes 上查看 API 日志
Dapr API 日志会被写入标准输出(stdout)和标准错误(stderr),您可以在 Kubernetes 上查看这些日志。
通过执行以下命令查看 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 配置规范,您可以为 --enable-api-logging
标志(以及在 Kubernetes 上运行时的相应注释)设置默认值,使用 logging.apiLogging.enabled
选项。此值适用于引用定义该配置文档或资源的所有 Dapr 运行时。
- 如果
logging.apiLogging.enabled
设置为false
,即默认值,则 Dapr 运行时的 API 日志记录是禁用的,除非--enable-api-logging
设置为true
(或添加dapr.io/enable-api-logging: true
注释)。 - 当
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)。
为了减少在启用 API 日志记录时意外包含 PII 的风险,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和内存的使用高峰在很多情况下是常见的。
Dapr 允许用户通过其性能分析服务端点使用 pprof
启动按需性能分析会话,以检测并发、性能、CPU 和内存使用等问题。
启用性能分析
Dapr 支持在 Kubernetes 和独立模式下启用性能分析。
独立模式
在独立模式下启用性能分析时,可以通过 Dapr CLI 传递 --enable-profiling
和 --profile-port
标志:
注意,profile-port
是可选的,如果未指定,Dapr 会自动选择一个可用端口。
dapr run --enable-profiling --profile-port 7777 python myapp.py
Kubernetes
在 Kubernetes 中启用性能分析,只需在 Dapr 注解的 pod 中添加 dapr.io/enable-profiling
注解:
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
分析已分配的对象:
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