K8S--配置存活、就绪和启动探针
目录
- 1 本人基础环境
- 2 目的
- 3 存活、就绪和启动探针介绍
- 3.1 存活探针
- 3.2 就绪探针
- 3.3 启动探针
- 4 探针使用场景
- 4.1 存活探针
- 4.2 就绪探针
- 4.3 启动探针
- 5 配置存活、就绪和启动探针
- 5.1 定义存活探针
- 5.2 定义一个存活态 HTTP 请求接口
- 5.3 定义 TCP 的就绪探针、存活探测
- 5.4 定义 gRPC 存活探针
- 6 使用场景
- 6.1 使用启动探针保护慢启动容器
- 6.2 定义就绪探针
- 7 Probe的配置字段
- 7.1 HTTP 探测配置
- 7.2 TCP 探测配置
1 本人基础环境
- 操作系统:CentOSStream9 CPU - 2核 内存 - 4GB 硬盘 - 60G
- 安装了docker及k8s(CentOS9安装docker及k8s)
2 目的
- 介绍存活(Liveness)、就绪(Readiness)和启动(Startup)探针
- 如何给容器配置存活(Liveness)、就绪(Readiness)和启动(Startup)探针。
3 存活、就绪和启动探针介绍
3.1 存活探针
存活探针决定何时重启容器。 例如,当应用在运行但无法取得进展时,存活探针可以捕获这类死锁。
如果一个容器的存活探针失败多次,kubelet 将重启该容器。
存活探针不会等待就绪探针成功。 如果你想在执行存活探针前等待,你可以定义 initialDelaySeconds
,或者使用启动探针。
3.2 就绪探针
就绪探针决定何时容器准备好开始接受流量。 这种探针在等待应用执行耗时的初始任务时非常有用,例如建立网络连接、加载文件和预热缓存。
如果就绪探针返回的状态为失败,Kubernetes 会将该 Pod 从所有对应服务的端点中移除。
就绪探针在容器的整个生命期内持续运行。
3.3 启动探针
启动探针检查容器内的应用是否已启动。 启动探针可以用于对慢启动容器进行存活性检测,避免它们在启动运行之前就被 kubelet 杀掉。
如果配置了这类探针,它会禁用存活检测和就绪检测,直到启动探针成功为止。
这类探针仅在启动时执行,不像存活探针和就绪探针那样周期性地运行。
4 探针使用场景
4.1 存活探针
kubelet 使用存活探针来确定什么时候要重启容器。 例如,存活探针可以探测到应用死锁(应用在运行,但是无法继续执行后面的步骤)情况。 重启这种状态下的容器有助于提高应用的可用性,即使其中存在缺陷。
4.2 就绪探针
kubelet 使用就绪探针可以知道容器何时准备好接受请求流量。 这种信号的一个用途就是控制哪个 Pod 作为 Service 的后端。 当 Pod 的 Ready
状况 为 true 时,Pod 被认为是就绪的。若 Pod 未就绪,会被从 Service 的负载均衡器中剔除。 当 Pod 所在节点的 Ready
状况不为 true 时、当 Pod 的某个 readinessGates 为
false 时,或者当 Pod 中有任何一个容器未就绪时,Pod 的 Ready 状况为 false。
4.3 启动探针
kubelet 使用启动探针来了解应用容器何时启动。 如果配置了这类探针,存活探针和就绪探针在启动探针成功之前不会启动,从而确保存活探针或就绪探针不会影响应用的启动。 启动探针可以用于对慢启动容器进行存活性检测,避免它们在启动运行之前就被杀掉。
注意:
存活探针是一种从应用故障中恢复的强劲方式,但应谨慎使用。 你必须仔细配置存活探针,确保它能真正标示出不可恢复的应用故障,例如死锁。
说明:
错误的存活探针可能会导致级联故障。 这会导致在高负载下容器重启;例如由于应用无法扩展,导致客户端请求失败;以及由于某些 Pod 失败而导致剩余 Pod 的工作负载增加。了解就绪探针和存活探针之间的区别, 以及何时为应用配置使用它们非常重要。
5 配置存活、就绪和启动探针
5.1 定义存活探针
许多长时间运行的应用最终会进入损坏状态,除非重新启动,否则无法被恢复。 Kubernetes 提供了存活探针来发现并处理这种情况。
在本练习中,你会创建一个 Pod,其中运行一个基于 registry.k8s.io/busybox
镜像的容器。 下面是这个 Pod 的配置文件。
# pods/probe/exec-liveness.yaml
apiVersion: v1
kind: Pod
metadata:labels:test: livenessname: liveness-exec
spec:containers:- name: livenessimage: registry.k8s.io/busyboxargs:- /bin/sh- -c- touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600livenessProbe:exec:command:- cat- /tmp/healthyinitialDelaySeconds: 5periodSeconds: 5
在这个配置文件中,可以看到 Pod 中只有一个 Container
。 periodSeconds
字段指定了 kubelet 应该每 5 秒执行一次存活探测。 initialDelaySeconds
字段告诉 kubelet 在执行第一次探测前应该等待 5 秒。 kubelet 在容器内执行命令 cat /tmp/healthy
来进行探测。 如果命令执行成功并且返回值为 0,kubelet 就会认为这个容器是健康存活的。 如果这个命令返回非 0 值,kubelet 会杀死这个容器并重新启动它。
当容器启动时,执行如下的命令:
/bin/sh -c "touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600"
这个容器生命的前 30 秒,/tmp/healthy
文件是存在的。 所以在这最开始的 30 秒内,执行命令 cat /tmp/healthy
会返回成功代码。 30 秒之后,执行命令 cat /tmp/healthy
就会返回失败代码。
创建 Pod:
kubectl apply -f https://k8s.io/examples/pods/probe/exec-liveness.yaml
在 30 秒内,查看 Pod 的事件:
kubectl describe pod liveness-exec
输出结果表明还没有存活探针失败:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 11s default-scheduler Successfully assigned default/liveness-exec to node01
Normal Pulling 9s kubelet, node01 Pulling image "registry.k8s.io/busybox"
Normal Pulled 7s kubelet, node01 Successfully pulled image "registry.k8s.io/busybox"
Normal Created 7s kubelet, node01 Created container liveness
Normal Started 7s kubelet, node01 Started container liveness
35 秒之后,再来看 Pod 的事件:
kubectl describe pod liveness-exec
在输出结果的最下面,有信息显示存活探针失败了,这个失败的容器被杀死并且被重建了。
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 57s default-scheduler Successfully assigned default/liveness-exec to node01
Normal Pulling 55s kubelet, node01 Pulling image "registry.k8s.io/busybox"
Normal Pulled 53s kubelet, node01 Successfully pulled image "registry.k8s.io/busybox"
Normal Created 53s kubelet, node01 Created container liveness
Normal Started 53s kubelet, node01 Started container liveness
Warning Unhealthy 10s (x3 over 20s) kubelet, node01 Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
Normal Killing 10s kubelet, node01 Container liveness failed liveness probe, will be restarted
再等 30 秒,确认这个容器被重启了:
kubectl get pod liveness-exec
输出结果显示 RESTARTS
的值增加了 1。 请注意,一旦失败的容器恢复为运行状态,RESTARTS
计数器就会增加 1:
NAME READY STATUS RESTARTS AGE
liveness-exec 1/1 Running 1 1m
5.2 定义一个存活态 HTTP 请求接口
另外一种类型的存活探测方式是使用 HTTP GET 请求。 下面是一个 Pod 的配置文件,其中运行一个基于 registry.k8s.io/e2e-test-images/agnhost
镜像的容器。
# pods/probe/http-liveness.yaml
apiVersion: v1
kind: Pod
metadata:labels:test: livenessname: liveness-http
spec:containers:- name: livenessimage: registry.k8s.io/e2e-test-images/agnhost:2.40args:- livenesslivenessProbe:httpGet:path: /healthzport: 8080httpHeaders:- name: Custom-Headervalue: AwesomeinitialDelaySeconds: 3periodSeconds: 3
在这个配置文件中,你可以看到 Pod 也只有一个容器。 periodSeconds
字段指定了 kubelet 每隔 3 秒执行一次存活探测。 initialDelaySeconds
字段告诉 kubelet 在执行第一次探测前应该等待 3 秒。 kubelet 会向容器内运行的服务(服务在监听 8080 端口)发送一个 HTTP GET 请求来执行探测。 如果服务器上 /healthz
路径下的处理程序返回成功代码,则 kubelet 认为容器是健康存活的。 如果处理程序返回失败代码,则 kubelet 会杀死这个容器并将其重启。
返回大于或等于 200 并且小于 400 的任何代码都标示成功,其它返回代码都标示失败。
你可以访问 server.go 阅读服务的源码。 容器存活期间的最开始 10 秒中,/healthz 处理程序返回 200 的状态码。 之后处理程序返回 500 的状态码。
http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {duration := time.Now().Sub(started)if duration.Seconds() > 10 {w.WriteHeader(500)w.Write([]byte(fmt.Sprintf("error: %v", duration.Seconds())))} else {w.WriteHeader(200)w.Write([]byte("ok"))}
})
kubelet 在容器启动之后 3 秒开始执行健康检查。所以前几次健康检查都是成功的。 但是 10 秒之后,健康检查会失败,并且 kubelet 会杀死容器再重新启动容器。
创建一个 Pod 来测试 HTTP 的存活检测:
kubectl apply -f https://k8s.io/examples/pods/probe/http-liveness.yaml
10 秒之后,通过查看 Pod 事件来确认存活探针已经失败,并且容器被重新启动了。
kubectl describe pod liveness-http
5.3 定义 TCP 的就绪探针、存活探测
第三种类型的存活探测是使用 TCP 套接字。 使用这种配置时,kubelet 会尝试在指定端口和容器建立套接字链接。 如果能建立连接,这个容器就被看作是健康的,如果不能则这个容器就被看作是有问题的。
apiVersion: v1
kind: Pod
metadata:name: goproxylabels:app: goproxy
spec:containers:- name: goproxyimage: registry.k8s.io/goproxy:0.1ports:- containerPort: 8080readinessProbe:tcpSocket:port: 8080initialDelaySeconds: 15periodSeconds: 10livenessProbe:tcpSocket:port: 8080initialDelaySeconds: 15periodSeconds: 10
如你所见,TCP 检测的配置和 HTTP 检测非常相似。 下面这个例子同时使用就绪探针和存活探针。kubelet 会在容器启动 15 秒后运行第一次存活探测。 此探测会尝试连接 goproxy
容器的 8080 端口。 如果此存活探测失败,容器将被重启。kubelet 将继续每隔 10 秒运行一次这种探测。
除了存活探针,这个配置还包括一个就绪探针。 kubelet 会在容器启动 15 秒后运行第一次就绪探测。 与存活探测类似,就绪探测会尝试连接 goproxy
容器的 8080 端口。 如果就绪探测失败,Pod 将被标记为未就绪,且不会接收来自任何服务的流量。
要尝试 TCP 存活检测,运行以下命令创建 Pod:
kubectl apply -f https://k8s.io/examples/pods/probe/tcp-liveness-readiness.yaml
15 秒之后,通过查看 Pod 事件来检测存活探针:
kubectl describe pod goproxy
5.4 定义 gRPC 存活探针
如果你的应用实现了 gRPC 健康检查协议, 这个例子展示了如何配置 Kubernetes 以将其用于应用的存活性检查。 类似地,你可以配置就绪探针和启动探针。
下面是一个示例清单:
# pods/probe/grpc-liveness.yaml
apiVersion: v1
kind: Pod
metadata:name: etcd-with-grpc
spec:containers:- name: etcdimage: registry.k8s.io/etcd:3.5.1-0command: [ "/usr/local/bin/etcd", "--data-dir", "/var/lib/etcd", "--listen-client-urls", "http://0.0.0.0:2379", "--advertise-client-urls", "http://127.0.0.1:2379", "--log-level", "debug"]ports:- containerPort: 2379livenessProbe:grpc:port: 2379initialDelaySeconds: 10
要使用 gRPC 探针,必须配置 port
属性。 如果要区分不同类型的探针和不同功能的探针,可以使用 service
字段。 你可以将 service
设置为 liveness
,并使你的 gRPC 健康检查端点对该请求的响应与将 service
设置为 readiness
时不同。 这使你可以使用相同的端点进行不同类型的容器健康检查而不是监听两个不同的端口。 如果你想指定自己的自定义服务名称并指定探测类型,Kubernetes 项目建议你使用使用一个可以关联服务和探测类型的名称来命名。 例如:myservice-liveness(使用 - 作为分隔符)。
说明:
与 HTTP 或 TCP 探针不同,gRPC 探测不能按名称指定健康检查端口, 也不能自定义主机名。
配置问题(例如:错误的 port
或 service
、未实现健康检查协议) 都被认作是探测失败,这一点与 HTTP 和 TCP 探针类似。
kubectl apply -f https://k8s.io/examples/pods/probe/grpc-liveness.yaml
15 秒钟之后,查看 Pod 事件确认存活性检查结果:
kubectl describe pod etcd-with-grpc
当使用 gRPC 探针时,需要注意以下一些技术细节:
- 这些探针运行时针对的是 Pod 的 IP 地址或其主机名。 请一定配置你的 gRPC 端点使之监听于 Pod 的 IP 地址之上。
- 这些探针不支持任何身份认证参数(例如 -tls)。
- 对于内置的探针而言,不存在错误代码。所有错误都被视作探测失败。
- 如果 ExecProbeTimeout 特性门控被设置为 false,则 grpc-health-probe 不会考虑 timeoutSeconds 设置状态(默认值为 1s), 而内置探针则会在超时时返回失败。
工作原理:
当Kubernetes配置了gRPC存活探针后,它会定期向指定的gRPC端口发送健康检查请求。如果应用程序能够正常响应这些请求,则表明应用程序是健康的;如果应用程序无法响应或响应不符合预期,则Kubernetes会认为应用程序已经崩溃或不再存活,并会根据容器的重启策略重新启动容器。
6 使用场景
6.1 使用启动探针保护慢启动容器
有时候,会有一些现有的应用在启动时需要较长的初始化时间。 在这种情况下,若要不影响对死锁作出快速响应的探测,设置存活探测参数是要技巧的。 解决办法是使用相同的命令来设置启动探测,针对 HTTP 或 TCP 检测,可以通过将 failureThreshold
* periodSeconds
参数设置为足够长的时间来应对最糟糕情况下的启动时间。
比如:
ports:
- name: liveness-portcontainerPort: 8080livenessProbe:httpGet:path: /healthzport: liveness-portfailureThreshold: 1periodSeconds: 10startupProbe:httpGet:path: /healthzport: liveness-portfailureThreshold: 30periodSeconds: 10
对于 HTTP 和 TCP 存活检测可以使用命名的 port(gRPC 探针不支持使用命名端口)。
幸亏有启动探测,应用将会有最多 5 分钟(30 * 10 = 300s)的时间来完成其启动过程。 一旦启动探测成功一次,存活探测任务就会接管对容器的探测,对容器死锁作出快速响应。 如果启动探测一直没有成功,容器会在 300 秒后被杀死,并且根据 restartPolicy
来执行进一步处置。
failureThreshold参数:定义了探针在连续失败多少次后,才将容器视为不健康或未就绪。
periodSeconds参数:定义了探针(存活探针、就绪探针或启动探针)多长时间执行一次健康检查。
6.2 定义就绪探针
有时候,应用会暂时性地无法为请求提供服务。 例如,应用在启动时可能需要加载大量的数据或配置文件,或是启动后要依赖等待外部服务。 在这种情况下,既不想杀死应用,也不想给它发送请求。 Kubernetes 提供了就绪探针来发现并缓解这些情况。 容器所在 Pod 上报还未就绪的信息,并且不接受通过 Kubernetes Service 的流量。
说明:
就绪探针在容器的整个生命周期中保持运行状态。
注意:
存活探针与就绪性探针相互间不等待对方成功。 如果要在执行就绪性探针之前等待,应该使用 initialDelaySeconds 或 startupProbe。
就绪探针的配置和存活探针的配置相似。 唯一区别就是要使用 readinessProbe
字段,而不是 livenessProbe
字段。
readinessProbe:exec:command:- cat- /tmp/healthyinitialDelaySeconds: 5periodSeconds: 5
HTTP 和 TCP 的就绪探针配置也和存活探针的配置完全相同。
就绪和存活探测可以在同一个容器上并行使用。 两者共同使用,可以确保流量不会发给还未就绪的容器,当这些探测失败时容器会被重新启动。
7 Probe的配置字段
Probe 有很多配置字段,可以使用这些字段精确地控制启动、存活和就绪检测的行为:
-
initialDelaySeconds
:容器启动后要等待多少秒后才启动启动、存活和就绪探针。 如果定义了启动探针,则存活探针和就绪探针的延迟将在启动探针已成功之后才开始计算。 如果periodSeconds
的值大于initialDelaySeconds
,则initialDelaySeconds
将被忽略。默认是 0 秒,最小值是 0。 -
periodSeconds
:执行探测的时间间隔(单位是秒)。默认是 10 秒。最小值是 1。 当容器未就绪时,ReadinessProbe
可能会在除配置的periodSeconds
间隔以外的时间执行。这是为了让 Pod 更快地达到可用状态。 -
timeoutSeconds
:探测的超时后等待多少秒。默认值是 1 秒。最小值是 1。 -
successThreshold
:探针在失败后,被视为成功的最小连续成功数。默认值是 1。 存活和启动探测的这个值必须是 1。最小值是 1 -
failureThreshold
:探针连续失败了failureThreshold
次之后, Kubernetes 认为总体上检查已失败:容器状态未就绪、不健康、不活跃。 默认值为 3,最小值为 1。 对于启动探针或存活探针而言,如果至少有failureThreshold
个探针已失败, Kubernetes 会将容器视为不健康并为这个特定的容器触发重启操作。 kubelet 遵循该容器的terminationGracePeriodSeconds
设置。 对于失败的就绪探针,kubelet 继续运行检查失败的容器,并继续运行更多探针; 因为检查失败,kubelet 将 Pod 的Ready
状况设置为false
。 -
terminationGracePeriodSeconds
:为 kubelet 配置从为失败的容器触发终止操作到强制容器运行时停止该容器之前等待的宽限时长。 默认值是继承 Pod 级别的terminationGracePeriodSeconds
值(如果不设置则为 30 秒),最小值为 1。
注意:
如果就绪态探针的实现不正确,可能会导致容器中进程的数量不断上升。 如果不对其采取措施,很可能导致资源枯竭的状况
7.1 HTTP 探测配置
HTTP Probes 允许针对 httpGet
配置额外的字段:
host
:连接使用的主机名,默认是 Pod 的 IP。也可以在 HTTP 头中设置 “Host” 来代替scheme
:用于设置连接主机的方式(HTTP 还是 HTTPS)。默认是 “HTTP”。path
:访问 HTTP 服务的路径。默认值为 “/”。httpHeaders
:请求中自定义的 HTTP 头。HTTP 头字段允许重复。port
:访问容器的端口号或者端口名。如果数字必须在 1~65535 之间。
对于 HTTP 探测,kubelet 发送一个 HTTP 请求到指定的端口和路径来执行检测。 除非 httpGet
中的 host
字段设置了,否则 kubelet 默认是给 Pod 的 IP 地址发送探测。 如果 scheme
字段设置为了 HTTPS
,kubelet 会跳过证书验证发送 HTTPS 请求。 大多数情况下,不需要设置 host
字段。 这里有个需要设置 host
字段的场景,假设容器监听 127.0.0.1,并且 Pod 的 hostNetwork
字段设置为了 true
。那么 httpGet
中的 host
字段应该设置为 127.0.0.1。 可能更常见的情况是如果 Pod 依赖虚拟主机,你不应该设置 host
字段,而是应该在 httpHeaders
中设置 Host
。
当将Pod的hostNetwork字段设置为true时,该Pod将与其所在节点(Node)共享网络命名空间。这意味着Pod将使用主机的网络栈和IP地址,而不是由Kubernetes创建并管理的专用网络栈。
针对 HTTP 探针,kubelet 除了必需的 Host 头部之外还发送两个请求头部字段:
User-Agent
:默认值是 kube-probe/1.32,其中 1.32 是 kubelet 的版本号。Accept
:默认值 /。
你可以通过为探测设置 httpHeaders
来重载默认的头部字段值。例如:
livenessProbe:httpGet:httpHeaders:- name: Acceptvalue: application/jsonstartupProbe:httpGet:httpHeaders:- name: User-Agentvalue: MyUserAgent
你也可以通过将这些头部字段定义为空值,从请求中去掉这些头部字段。
livenessProbe:httpGet:httpHeaders:- name: Acceptvalue: ""startupProbe:httpGet:httpHeaders:- name: User-Agentvalue: ""
注意:
当 kubelet 使用 HTTP 探测 Pod 时,仅当重定向到同一主机时,它才会遵循重定向。 如果 kubelet 在探测期间收到 11 个或更多重定向,则认为探测成功并创建相关事件:
Events:Type Reason Age From Message---- ------ ---- ---- -------Normal Scheduled 29m default-scheduler Successfully assigned default/httpbin-7b8bc9cb85-bjzwn to daocloudNormal Pulling 29m kubelet Pulling image "docker.io/kennethreitz/httpbin"Normal Pulled 24m kubelet Successfully pulled image "docker.io/kennethreitz/httpbin" in 5m12.402735213sNormal Created 24m kubelet Created container httpbinNormal Started 24m kubelet Started container httpbinWarning ProbeWarning 4m11s (x1197 over 24m) kubelet Readiness probe warning: Probe terminated redirects
如果 kubelet 收到主机名与请求不同的重定向,则探测结果将被视为成功,并且 kubelet 将创建一个事件来报告重定向失败。
7.2 TCP 探测配置
对于 TCP 探测而言,kubelet 在节点上(不是在 Pod 里面)发起探测连接, 这意味着你不能在 host
参数上配置服务名称,因为 kubelet 不能解析服务名称。
探针层面的 terminationGracePeriodSeconds
在 1.25 及以上版本中,用户可以指定一个探针层面的 terminationGracePeriodSeconds
作为探针规约的一部分。 当 Pod 层面和探针层面的 terminationGracePeriodSeconds
都已设置,kubelet 将使用探针层面设置的值。
当设置 terminationGracePeriodSeconds 时,请注意以下事项:
- kubelet 始终优先选用探针级别
terminationGracePeriodSeconds
字段 (如果它存在于 Pod 上)。 - 如果你已经为现有 Pod 设置了
terminationGracePeriodSeconds
字段并且不再希望使用针对每个探针的终止宽限期,则必须删除现有的这类 Pod。
例如:
spec:terminationGracePeriodSeconds: 3600 # Pod 级别设置containers:- name: testimage: ...ports:- name: liveness-portcontainerPort: 8080livenessProbe:httpGet:path: /healthzport: liveness-portfailureThreshold: 1periodSeconds: 60# 重载 Pod 级别的 terminationGracePeriodSecondsterminationGracePeriodSeconds: 60
探针层面的 terminationGracePeriodSeconds
不能用于就绪态探针。 这一设置将被 API 服务器拒绝。
相关文章:
K8S--配置存活、就绪和启动探针
目录 1 本人基础环境2 目的3 存活、就绪和启动探针介绍3.1 存活探针3.2 就绪探针3.3 启动探针 4 探针使用场景4.1 存活探针4.2 就绪探针4.3 启动探针 5 配置存活、就绪和启动探针5.1 定义存活探针5.2 定义一个存活态 HTTP 请求接口5.3 定义 TCP 的就绪探针、存活探测5.4 定义 g…...
solidity基础 -- 枚举
在智能合约开发领域,Solidity语言因其简洁高效而被广泛使用。其中,枚举(enum)作为一种特殊的数据类型,为合约的状态管理提供了极大的便利。本文将通过一个具体的Solidity合约示例,深入探讨枚举的定义、使用…...
重回C语言之老兵重装上阵(六)枚举
1. 什么是枚举 (enum)? 枚举(enum)是 C 语言中的一种数据类型,用于定义一组具名的整数常量。它可以使代码更加可读,帮助程序员更容易理解程序中的常量值。通过枚举,程序员可以使用有意义的名称来代替数字&…...
python+playwright自动化测试(一):安装及简单使用,截图录屏
目录 基本使用 浏览器调用 启用浏览器 创建窗口对象 访问URL 页面的刷新、返回、前进 关闭 截图、录屏、保存pdf 截图 录屏 保存为pdf 设置窗口大小 调试模式 手机模式及new_context的更多参数 手机模式 new_context的其他参数 设置语言和时区 设置和修改位置…...
Mysql--架构篇--体系结构(连接层,SQL层,存储引擎层,文件存储层)
MySQL是一种广泛使用的关系型数据库管理系统(RDBMS),其体系结构设计旨在提供高效的数据存储、查询处理和事务管理。MySQL的体系结构可以分为多个层次,每个层次负责不同的功能模块。 MySQL的体系结构主要由以下几个部分组成&#…...
git merge 压缩提交
在 Git 中,执行 git merge 时可以通过一些操作来“压缩”提交,通常是指将合并过程中的多个提交压缩成一个单一的提交。这可以通过使用 --squash 选项来完成,或者在合并后进行交互式 rebase。以下是两种常见的方法: 方法 1&#x…...
Python脚本自动发送电子邮件
要编写一个Python脚本来自动发送电子邮件,你可以使用smtplib库来处理SMTP协议,以及email库来构建邮件内容。 安装必要的库 通常情况下,smtplib和email库是Python标准库的一部分,因此不需要额外安装。如果你使用的是较旧的Python版…...
uniapp中rpx和upx的区别
在 UniApp 中,rpx 和 upx 是两种不同的单位,它们的主要区别在于适用的场景和计算方式。 ### rpx(Responsive Pixel) - **适用场景**:rpx 是一种响应式单位,主要用于小程序和移动端的布局。 - **计算方式**…...
CentOS 9 Stream 中查看 Python 版本并升级 Python
CentOS 9 Stream 中查看 Python 版本并升级 Python 1. 查看当前 Python 版本2. 升级 Python 版本(1)安装开发工具(2)安装必要的依赖包(3)下载和安装新版本的 Python(4)验证安装 3. …...
可以用于分割字符串的方法(python)
一、str.split(sep,maxsplit)函数(返回列表) sep:分隔符 maxsplit:分割次数 a"Hello world" list1a.split(" ",1) print(list1) 结果: [Hello, world] 二、str.rsplit(sep,maxsplit)函数&…...
【Vue】全局/局部组件使用流程(Vue2为例)
全局组件和局部组件区别 如何使用 全局组件:全局注册后,可以在任意页面中直接使用。局部组件:在页面中需要先导入子组件路径,注册组件才能使用。 适用场景 全局组件:适用于高频使用的组件,如导航栏、业…...
virtual box虚拟机误删Python3.6后导致UBUNTU18.04开机无UI界面(进不了desktop)的解决方法
最近在解决一个python引起的问题的时候,作者心一狠,删了系统自带的python3.6, 顺便还删了python3。导致重启后ubuntu的virtual box虚拟机无法看到UI登录界面,只给我了孤零零的命令行。装了很多东西不可能重装,无奈只能…...
虚拟线程JDK与Spring Core Reactor
两种虚拟线程对比:JDK vs. Spring Core Reactor性能对比 1、基于 JDK 的虚拟线程实现: 摘自实际代码: public static void withFlatMapUsingJDK() { ... var virtualThreadExecutor Executors.newThreadPerTaskExecutor( Thread .ofVirtual…...
纯 Python、Django、FastAPI、Flask、Pyramid、Jupyter、dbt 解析和差异分析
一、纯 Python 1.1 基础概念 Python 是一种高级、通用、解释型的编程语言,以其简洁易读的语法和丰富的标准库而闻名。“纯 Python” 在这里指的是不依赖特定的 Web 框架或数据分析工具,仅使用 Python 原生的功能和标准库来开发应用程序或执行任务。 1.…...
C++ NULL和nullptr
NULL实际是一个宏,在传统的C头文件(stddef.h)中,可以看到如下代码: #ifndef NULL #ifdef __cplusplus #define NULL 0 #else #define NULL ((void *)0) #endif #endif 如上是条件编译的宏定义 确保在不同编程环境下正确处理NULL的定义 C中NULL可能被定义…...
算法日记1:洛谷p2678跳石头(二分答案)
1、题目 二、题解: 2.1解题思路: 1.题目要求求出最小值最大,明显的二分答案题目,所以我们可以二分可以跳跃距离int l-1,rL1; 2.此时我们思考lmid和rmid的处理,当我们的check(mid)为true时候 表明我们此时的mid是符合要求的, 那么…...
PID控制器 (Proportional-Integral-Derivative Controller) 算法详解及案例分析
PID控制器 (Proportional-Integral-Derivative Controller) 算法详解及案例分析 目录 PID控制器 (Proportional-Integral-Derivative Controller) 算法详解及案例分析1. 引言2. PID控制器的基本概念2.1 PID控制器的定义2.2 PID控制器的核心思想2.3 PID控制器的应用领域 3. PID控…...
Vue中nextTick实现原理
源码实现思路(面试高分回答) 面试官问我 Vue 的 nextTick 原理是怎么实现的,我这样回答: 在调用 this.$nextTick(cb) 之前: 存在一个 callbacks 数组,用于存放所有的 cb 回调函数。存在一个 flushCallbac…...
【MATLAB】subplot如何增加title
在 Matlab 中,使用 subplot 函数将图形窗口划分为多个子图,并使用 title 函数为每个子图添加标题。以下是一个示例: matlab % 生成示例数据 x 0:0.1:10; y1 sin(x); y2 cos(x); % 创建一个 2 行 1 列的子图布局,并选…...
vue3+ts的<img :src=““ >写法
vue3ts的<img :src"" >写法<img :src"datasetImage" alt"数据分布示意图" /><script setup lang"ts">const datasetImage ref();datasetImage.value new URL(../../../assets/images/login-background.jpg, impo…...
Vue+Echarts+百度地图 实现 路径规划
实现功能: 通过选择 相关调拨,系统自动规划 路径,并且以地图的形式呈现最佳路径 技术难点: 1. vue 结合使用 echarts 2.echarts 在 vue嵌入百度地图,并且做出路径 曲线 最终结果:...
uniapp 小程序 textarea 层级穿透,聚焦光标位置错误怎么办?
前言 在开发微信小程序时,使用 textarea 组件可能会遇到一些棘手的问题。最近我在使用 uniapp 开发微信小程序时,就遇到了两个非常令人头疼的问题: 层级穿透:由于 textarea 是原生组件,任何元素都无法遮盖住它。当其…...
IGP协议的双点双向注入(路由引入)
一、拓扑环境 二、单向注入 以上拓扑为例,单点注入存在路由回包问题 在AR5上注入直连路由 55.5.5.5 需求:AR1上的10.1.1.1 需访问AR5上的55.5.5.5 1、在AR2和AR3上查看注入的55.5.5.5的路由信息 2、现在边界设备以学习到目的网段的路由信息࿰…...
【React】新建React项目
目录 create-react-app基础运用React核心依赖React 核心思想:数据驱动React 采用 MVC体系package.jsonindex.html好书推荐 官方提供了快速构建React 项目的脚手架: create-react-app ,目前使用它安装默认是19版本,我们这里降为18…...
“AI 自动化效能评估系统:开启企业高效发展新征程
在当今数字化飞速发展的时代,企业面临着日益激烈的市场竞争,如何提升效率、降低成本成为了企业生存与发展的关键。AI 自动化效能评估系统应运而生,它如同一把智能钥匙,为企业开启了高效发展的新征程。 AI 自动化效能评估系统&…...
免 root 开启 Pixel 手机 VoLTE 功能
部分运营商需要开启 VoLTE 功能才可以正常通话和接收短信,但是默认情况下,Pixel 是无法开启的,需要我们手动开启一下。经过网友的确认,这种方法还适用于荣耀 MAGIC 等其他品牌的手机。 具体流程如下: 1.打开开发者选…...
华为2024嵌入式研发面试题
01 你认为最好的排序算法是什么? 在实际的编程中,最好的排序算法要根据实际需求和数据规模来选择,因为每种排序算法都有其优势和劣势。以下是一些常见排序算法及其优缺点: 冒泡排序 冒泡排序是一种简单直观的排序算法࿰…...
Android Room 报错:too many SQL variables (code 1 SQLITE_ERROR) 原因及解决方法
报错信息: android.database.sqlite.SQLiteException: too many SQL variables (code 1 SQLITE_ERROR): while compiling: SELECT * FROM points WHERE id IN (?,?,?,...,?,?,?)SQLiteException: too many SQL variables 通常是由于一次查询或插入的 SQL 语句…...
PHP 字符串
PHP 字符串 引言 在 PHP 中,字符串是一种非常基础且重要的数据类型。字符串可以包含字母、数字、标点符号以及特殊字符。PHP 提供了丰富的字符串函数,使得字符串操作变得简单而高效。本文将详细介绍 PHP 中字符串的常用操作,包括字符串的创…...
Android15源码编译问题处理
最近想在Raspberry Pi5上面运行自己编译的Android15镜像,参考如下链接来处理: GitHub - raspberry-vanilla/android_local_manifest GitHub - raspberry-vanilla/android_kernel_manifest 代码同步完后,编译就出问题了,总是提示: FAILED: analyzing Android.bp files and…...
Transformer架构和Transformers 库和Hugging Face
Transformer架构 和 Hugging Face 之间的关系非常紧密,Hugging Face 是推动 Transformer 架构普及和应用的重要力量。以下是两者的关系及其具体联系: 1. Transformer 架构 背景: Transformer 是由 Google 在 2017 年提出的革命性架构,基于自…...
【机器学习 | 数据挖掘】离群点检测
【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈智能大数据分析 ⌋ ⌋ ⌋ 智能大数据分析是指利用先进的技术和算法对大规模数据进行深入分析和挖掘,以提取有价值的信息和洞察。它结合了大数据技术、人工智能(AI)、机器学习(ML&a…...
【极速版 -- 大模型入门到进阶】除了 Prompting, 大模型还能如何被应用?
文章目录 大模型应用 -- Generative AI Projects🌊 大模型应用的时效优势🌊 大模型应用的方式 - Technology Options应用方式一 🐟 Prompting:最简单快速应用方式二🐟 Retrieval augmented generation (RAG)࿱…...
[Unity]发包前遇到的坑之GridLayoutGroup
发包前禁用了UI上面一个调试页面A后,发现无法正确获取某一个用了GridLayoutGroup组件的所有子物体的世界坐标。 一顿研究之后发现,在Start的时候想要正确获取其坐标,需要强制刷新一次布局,方法如下: UnityEngine.U…...
【C++】IO 流
文章目录 👉C 语言的输入与输出👈👉流是什么👈👉C IO 流👈C 标准 IO 流C 和 C 语言的输入格式问题C 的多次输入内置类型和自定义类型的转换日期的多次输入C 文件 IO 流文本文件和二进制文件的读写 …...
Public Key Retrieval is not allowed 解决方法
如图:我的报错是Public Key Retrieval is not allowed,我的前后端都能正常加载,但是在请求数据库时就会报错如下: 解决办法: 在 application.yaml 中的数据库设置地方加上allowPublicKeyRetrievaltrue,然后…...
大数据原生集群 (Hadoop3.X为核心) 本地测试环境搭建二
本篇安装软件版本 mysql5.6 spark3.2.1-hadoop3.2 presto0.272 zeppelin0.11.2 kafka_2.13_3.7.2 mysql 安装步骤见-》 https://blog.csdn.net/dudadudadd/article/details/110874570 spark 安装步骤见-》https://blog.csdn.net/dudadudadd/article/details/109719624 安装…...
服务器引导异常,Grub报错: error: ../../grub-core/fs/fshelp.c:258:file xxxx.img not found.
服务器引导异常,Grub报错: error: ../../grub-core/fs/fshelp.c:258:file xxxx.img not found. 1. 故障现象2. 解决思路3. 故障分析4. 案件回溯5. 解决问题 1. 故障现象 有一台服务器业务报无法连接. 尝试用Ping命令发现无法ping通. 通过控制台查看发现有以下报错: error: ..…...
RabbitMQ-消息入队
1 分布式异步的问题 对于一个业务线的处理,如果是一个完整的处理,应该是消息正 常进入队列,同时消息正常被消费掉。 问题来了: 生产者发送消息,在传输过程中,消息丢失了,咋办? 消息发…...
Angular-生命周期及钩子函数
什么是生命周期 Angular 创建和渲染组件及其子组件,当它们绑定的属性发生变化时检查它们,并在从 DOM 中移除它之前销毁它们。生命周期函数通俗的讲就是组件创建、组件更新、组件销毁的时候会触发的一系列的方法。当 Angular 使用构造函数新建一个组件或…...
算法-高精度问题(带图详细解读~)
今天来分享四道大数运算的模板题. 目录 1. 大数相加2. 大数相减3. 大数相乘4. 大数相除 1. 大数相加 题目链接: LINK 基本思路: 存入数组, 模拟运算. 逆序字符串补零操作依次取数据, 依次相加 3-1 加: (t-ret s1[i] s2[i] carry) % 10; 3-2 进: (t-ret s1[i] s2[i] car…...
MC1.12.2 macOS高清修复OptiFine运行崩溃
最近在玩RLCraft,在windows中运行正常的,移植到macOS中发现如果加载OptiFine模组就会崩溃 报错日志 报错日志如下,其中已经包含了各种版本信息,我就不单独说明了。这里说一下,报错的时候用的是oracle jdk x64的&…...
Spring Boot教程之五十六:用 Apache Kafka 消费 JSON 消息
Spring Boot | 如何使用 Apache Kafka 消费 JSON 消息 Apache Kafka 是一个流处理系统,可让您在进程、应用程序和服务器之间发送消息。在本文中,我们将了解如何使用 Apache Kafka 在 Spring Boot 应用程序的控制台上发布 JSON 消息。 为了了解如何创建 …...
远程和本地文件的互相同步
文章目录 1、rsync实现类似git push pull功能1. 基础概念2. 示例操作3. 定制化和进阶用法4. 定时同步(类似自动化) 2 命令简化1. 动态传参的脚本2. Shell 函数支持动态路径3. 结合环境变量和参数(更简洁)4. Makefile 支持动态路径…...
在ES6模块中导入和导出
在ES6模块中导入和导出 以最简单的例子举例 //shoppingCart.js //导出模块 console.log(导出模块);//script.js //导出模块 import ./shoppingCart.js; console.log(导入模块);所以要导入其他模块必须指定类型 <script type"Modules" defer src"script.js&…...
centos使用dpdk库
yum -y install dpdk dpdk-devel 在 C 中使用 DPDK(Data Plane Development Kit)库通常涉及到以下几个步骤:安装 DPDK、配置编译环境、编写 C 代码并链接 DPDK 库。以下是如何在 C 中引用和使用 DPDK 的详细步骤。 1. 安装 DPDK 首先&#…...
ChatGLM:从GLM-130B到GLM-4全系列大语言模型
摘要 我们介绍了ChatGLM,这是一个不断进化的大语言模型系列,我们一直在持续开发中。本报告主要聚焦于GLM-4语言系列,包括GLM-4、GLM-4-Air和GLM-4-9B。它们代表了我们从ChatGLM前三代中汲取的所有见解和经验教训所训练出的最强大模型。迄今为…...
EF Core分页
Skip(3).Take(8) 最好显式指定排序规则需要知道满足条件的数据的总条数: 用IQueryable的复用 LongCount和Count页数:long pageCount (long)Math.Ceiling(count * 1.0 / pageSize); class Program {static async Task Main(string[] args){using (MyDbC…...
一种ESP8266+OLED时间天气显示
在当今这个信息爆炸的时代,人们对于获取实时信息的需求日益增长,尤其是在时间与天气这两个与日常生活息息相关的方面。而将 ESP8266 与 OLED 显示屏相结合制作的时钟兼天气显示设备,凭借其便携性、实时性以及低成本等优势,成为了众…...
LabVIEW光流跟踪算法
1. 光流跟踪算法的概述 光流(Optical Flow)是一种图像处理技术,用于估算图像中像素点的运动。通过比较连续帧图像,光流算法可以分析图像中的运动信息,广泛用于目标跟踪、运动检测和视频处理等场景。该示例使用了NI Vi…...