【云原生•监控】基于Prometheus实现自定义指标弹性伸缩(HPA)

【云原生•监控】基于Prometheus实现自定义指标弹性伸缩(HPA)

什么是弹性伸缩

「Autoscaling即弹性伸缩,是Kubernetes中的一种非常核心的功能,它可以根据给定的指标(例如 CPU 或内存)自动缩放Pod副本,从而可以更好地管理和利用计算资源,提高系统的可用性和性能,同时减少开销和成本。弹性伸缩可以解决服务负载存在较大波动或资源实际使用与预估之间的差距。」

在Kubernetes集群中提供了三种弹性伸缩技术:

  • 「CA(Cluster Autoscaler)」:Node级别自动扩/缩容

  • 「HPA(Horizontal Pod Autoscaler)」:Pod个数自动扩/缩容

  • 「VPA(Vertical Pod Autoscaler)」:Pod配置自动扩/缩容,主要是CPU、内存配置

「Node自动扩/缩容」

Cluster AutoScaler定期检测是否有充足的资源来调度新创建的Pod,当资源不足时会调用Cloud Provider创建新的Node。Cluster AutoScaler也会定期监测 Node的资源使用情况,当一个Node长时间资源利用率都很低时(低于50%)自动将其所在虚拟机从集群中删除。此时,原来的Pod会自动调度到其他Node上面。

Node的增减可能会影响整个kubernetes集群的稳定性,一旦出现问题会影响整个集群上部署的所有业务程序,所以,生产中针对Node节点的扩缩容一般还是谨慎使用,当确实需要对Node进行扩缩容时,往往通过人工执行脚本完成。

「Pod的垂直扩/缩容(VPA)」

VPA全称Vertical Pod Autoscaler,即Pod的垂直自动伸缩,它根据容器资源使用率自动设置CPU和内存的requests,从而允许在节点上进行适当的调度,以便为每个Pod提供适当的资源。它既可以缩小过度请求资源的容器,也可以根据其使用情况随时提升资源不足的容量。

「目前,VPA技术成熟度还不够,是Kubernetes比较新的功能,更新正在运行的Pod资源配置是VPA的一项试验性功能,会导致Pod的重建和重启,而且有可能被调度到其他的节点上。」

「Pod的水平扩/缩容(HPA)」

HPA全称Horizontal Pod Autoscaler,即Pod的水平自动伸缩,根据资源利用率或者自定义指标自动调整Pod的副本数,实现Pod的扩容、缩容,让部署的规模接近于实际服务的负载。

HPA弹性伸缩原理

Horizontal Pod Autoscaler功能最初是在Kubernetes 1.1中引入并不断发展,目前HPA已经支持了autoscaling/v1autoscaling/v2beta1autoscaling/v2beta2三个大版本。

常规场景下,比如晚上业务压力较小情况下,可以使用kubectl scale指令将Pod副本数设置为1;当白天上班高分期业务压力大时使用kubectl scale指令将Pod的副本数设置为3,但这些操作都是人为介入执行的。而HPA控制器则是基于业务的指标判断业务忙闲自动基于算法计算出当前多少Pod副本数运行比较合适,自动调整Pod的副本数。

8366363f74e827cd2723dd45c7862989.png

Kubernetes HPA v2相对于v1版本进行了一些重大改进。其中最显著的改进是引入了「多指标」自动扩缩容,即可以同时根据多种指标(如 CPU使用率、内存使用率、网络负载等)来进行自动扩缩容决策。此外,HPA v2还增加了支持「自定义指标」的能力,使得用户可以根据自己的需求定义和使用自己的指标。总的来说,Kubernetes HPA v2是一个更加成熟、更加灵活和可定制的自动扩缩容机制。

「HPA弹性伸缩的核心机制:自动根据业务忙闲来调整业务工作负载的副本数。这里主要涉及到两个关键点:」

  • 「如何识别业务的忙闲程度」

  • 「使用控制Pod副本数调整」

e72f53ede7e5d0aeea35baa4d57f9af0.png

「我们先来看下第一个问题:如何识别业务的忙闲程度?」

之前介绍kubernetes集群监控时介绍过metrics-server组件可以从集群中所有节点的kubelet组件中cAdvisor上获取到底层容器运行时指标,然后聚合后就可以通过kubectl top node/pod查看CPU、内存资源使用情况,也可以通过kubectl get --raw /apis/metrics.k8s.io/v1beta1/nodes 接口访问访问获取。所以,HPA控制器可以通过metrics-server组件获取Pod的CPU、内存使用率识别业务忙闲。

Kubernestes 1.7引入了聚合层(Aggregator),允许第三方应用程序通过注册自己为API插件来扩展Kubernestes API。metrics-server组件注册到聚合层然后就可以像访问kube-apiserver接口一样访问metrics-server后端服务的接口。

Kubernetes在kube-apiserver服务中引入了一个API聚合层,用于将扩展API的访问请求转发到用户服务的功能。比如,当你访问apis/metrics.k8s.io/v1beta1的时候,aggregator组件会基于groupversion转发到后端metrics-server服务上,聚合层只是相当于代理层。通过这种方式,我们就可以很方便地扩展KubernetesAPI

从metrics-server获取CPU、内存指标比较单一,kubernetes集群监控事实标准是prometheus,如果可以从prometheus获取指标用来识别业务忙闲程度,弹性伸缩灵活性就会大大增加。prometheus-adapter组件就可以实现这个功能,它从prometheus拉取指标转换成kubernetes api接口识别的数据格式,并将其注册到聚合层,这样kubernetes集群中其它服务就可以通过/apis/访问。

「再来看第二个问题:如何控制Pod副本数调整?」

HPA控制器会定期执行每个HPA对象的reconcile方法,主要包含如何操作:

  • 获取当前指标数据:从metrics-server获取CPU使用率、内存使用率或从prometheus-adapter获取自定义指标数据;

  • Pod副本数计算:将获取的指标数据和目标期望比较,判断是要扩容、缩容还是不变,若不需要要进行扩缩容调整就直接返回当前副本数,否则才使用HPA metrics 目标类型对应的算法来计算出deployment的目标副本数;

  • 更新Pod副本数:如果上步骤计算出的Pod目标副本数与当前副本数量不一致时,即需要进行扩/缩容的情况,则HPA控制器就向Deploymen发起scale操作,调整当前副本数,完成扩/缩容操作;

  • 监控调整效果:最终实现尽可能将deployment下的每个pod的最终metrics指标(平均值)基本维持到用户期望的水平,HPA会继续监控新的Pod副本数量对指标数据的影响,并根据需要进行进一步的调整。

reconcile定时间隔默认15秒,可以通过horizontal-pod-autoscaler-sync-period配置。

基于CPU指标的HPA

HPA v1版本支持CPU使用率、内存使用率的弹性伸缩,内存使用率一般缓存影响很难真实反映系统负载,所以,一般使用CPU使用率指标来进行弹性伸缩。容器的CPU使用率可以通过聚合层API代理到后端metrics-server服务,metrics-server向所有的kubelet组件发送请求,通过cAdvisor收集到所有容器的CPU、内存运行信息,这样HPA控制器就可以获取到Pod的CPU使用率,然后基于CPU使用率进行弹性伸缩。

2dc24d9cf5f4bc1e403ce6fcba3960f3.png

「1、基于Deployment创建Pod:」

#vi deploy-for-hpa_cpu.yml
apiVersion: apps/v1
kind: Deployment
metadata:name: web
spec:replicas: 1selector:matchLabels:app: nginx-phptemplate:metadata:labels:app: nginx-phpspec:containers:- image: lizhenliang/nginx-phpname: javaresources: requests:memory: "300Mi"cpu: "250m"
---
apiVersion: v1
kind: Service
metadata:name: web
spec:ports:- port: 80protocol: TCPtargetPort: 80selector:app: nginx-php

「2、创建:」

[root@k8s-01 autoscaling]# kubectl apply -f deploy-for-hpa_cpu.yml -n demo01
[root@k8s-01 autoscaling]# kubectl get pod -n demo01
NAME                                  READY   STATUS    RESTARTS   AGE
web-84885d5959-fbtxt                 1/1     Running   0          29s

「3、HPA策略文件:」

# vi hpa_for_cpu.yml
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:name: web
spec:#扩/缩容副本范围maxReplicas: 3minReplicas: 1#指定扩容的DeploymentscaleTargetRef: apiVersion: apps/v1kind: Deploymentname: webtargetCPUUtilizationPercentage: 60

targetCPUUtilizationPercentage: 60 表示:当Pod整体的资源利用率超过60%的时候,会进行扩容。

「4、创建HPA:」

[root@k8s-01 autoscaling]# kubectl apply -f hpa_for_cpu.yml -n demo01
horizontalpodautoscaler.autoscaling/web created
[root@k8s-01 autoscaling]# kubectl get hpa -n demo01
NAME              REFERENCE                       TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
web               Deployment/web                  0%/60%    1         3         1          44s

TARGETS一栏显示指标情况,前面0%表示当前Pod得到整体CPU资源使用率,因为没有任何HTTP请求,所以是0%;60%则是扩/缩容阈值。

MINPODS、MAXPODS:指定hpa扩/缩容

「5、压测:」

[root@k8s-01 autoscaling]# yum install httpd-tools
[root@k8s-01 autoscaling]# kubectl get svc -n demo01
NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
web                  ClusterIP   10.96.237.204   <none>        80/TCP     5d20h
[root@k8s-01 autoscaling]# ab -n 100000 -c 100  http://10.96.237.204/status.php

「6、观察扩/缩容:」

压测几十秒后,查看hpa后发现整体CPU使用率173%,超过60%目标值,但是replicas还是1,并没有扩容:

[root@k8s-01 autoscaling]# kubectl get hpa -n demo01
NAME              REFERENCE                       TARGETS    MINPODS   MAXPODS   REPLICAS   AGE
metrics-app-hpa   Deployment/sample-httpserver2   200m/2     1         3         1          46h
web               Deployment/web                  173%/60%   1         3         1          75s

再等会查看到replicas=3,触发了扩容操作:

[root@k8s-01 autoscaling]# kubectl get hpa -n demo01
NAME              REFERENCE                       TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
metrics-app-hpa   Deployment/sample-httpserver2   200m/2    1         3         1          46h
web               Deployment/web                  15%/60%   1         3         3          76s

查看Pod信息:

[root@k8s-01 autoscaling]# kubectl get pod -n demo01
NAME                                 READY   STATUS    RESTARTS   AGE
web-84885d5959-d9l4h                 1/1     Running   0          90s
web-84885d5959-fbtxt                 1/1     Running   0          6m9s
web-84885d5959-xgn4n                 1/1     Running   0          90s

kubectl describe hpa信息,可以看到有一条副本数扩到3的消息事件:

198c1adbd66c3202aaab4d34cef185ff.png

停止压测后,CPU使用率压力会降下来,大概等个几分钟后,又会触发缩容操作,replicas又会被设置成1:

[root@k8s-01 autoscaling]# kubectl get hpa -n demo01         
NAME              REFERENCE                       TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
web               Deployment/web                  0%/60%    1         3         1          7m59s

kubectl describe hpa查看hpa信息,会发现有两条缩容消息事件,一条显示是副本数从3缩容到2消息事件,另一条显示副本数从2缩容到1消息事件:

54c0e34e74c688ec30d826663a3c76d0.png

基于Prometheus自定义指标的HPA

基于metrics-server组件获取的CPU使用率、内存使用率弹性伸缩灵活性稍差,如果想根据自定义指标,如HTTP请求的QPS、5XX错误数等,在云原生领域监控基本就是Prometheus。自定义指标由Prometheus来提供,再利用prometheus-adpater聚合到apiserver,实现从metric-server组件获取CPU、内存同样的效果。

基于Prometheus自定义指标的HPA核心流程如下图:

c361fe82a97a53f5fc15290e8e797daa.png

prometheus-adapter组件部署

「1、安装prometheus-adapter组件:」

[root@k8s-01 ~]# helm repo add stable http://mirror.azure.cn/kubernetes/charts
"prometheus-community" has been added to your repositories
[root@k8s-01 ~]# helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "prometheus-community" chart repository
Update Complete. ⎈ Happy Helming!⎈ 
[root@k8s-01 ~]# helm repo list
NAME                    URL                                               
stable                  http://mirror.azure.cn/kubernetes/charts   [root@k8s-01 ~]# helm install prometheus-adapter stable/prometheus-adapter --namespace monitoring --set prometheus.url=http://prometheus,prometheus.port=9090
NAME: prometheus-adapter
LAST DEPLOYED: Tue Aug  1 23:44:08 2023
NAMESPACE: monitoring
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
prometheus-adapter has been deployed.
In a few minutes you should be able to list metrics using the following command(s):kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1

curl http://192.168.31.160:32478/metrics

「2、查看组件安装是否成功:」

[root@k8s-01 ~]# kubectl get pod -n monitoring
NAME                                      READY   STATUS    RESTARTS   AGE
prometheus-adapter-76d8fb4549-6vzzg       1/1     Running   0          3m25s[root@k8s-01 ~]# kubectl get apiservices                                                 
NAME                                   SERVICE                          AVAILABLE   AGE
...
v1beta1.custom.metrics.k8s.io          monitoring/prometheus-adapter   True        2m28s[root@k8s-01 ~]# kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1 |jq|more
{"kind": "APIResourceList","apiVersion": "v1","groupVersion": "custom.metrics.k8s.io/v1beta1","resources": [{"name": "namespaces/file_descriptors","singularName": "","namespaced": false,"kind": "MetricValueList","verbs": ["get"]},{"name": "namespaces/kube_ingress_annotations","singularName": "","namespaced": false,"kind": "MetricValueList","verbs": ["get"]},
...

查看prometheus-adapter组件的日志,注意不要出现类似http://prometheus:9090/api/v1/series?match%5B%5D=%7B__name__%3D~%22%5Econtainer_.%2A%22%2Ccontainer%21%3D%22POD%22%2Cnamespace%21%3D%22%22%2Cpod%21%3D%22%22%7D&start=1690905427.938  timeout 这样错误。

helm卸载操作如下:

[root@k8s-01 ~]# helm ls -n kube-system
NAME                    NAMESPACE       REVISION        UPDATED                                 STATUS          CHART                           APP VERSION
prometheus-adapter      kube-system     1               2023-08-01 23:44:08.027994527 +0800 CST deployed        prometheus-adapter-4.3.0        v0.11.0    
[root@k8s-01 ~]# helm uninstall prometheus-adapter -n kube-system
release "prometheus-adapter" uninstalled

部署golang应用

「1、初始化golang项目工程:」

[root@swarm-manager ~]# mkdir metrics
[root@swarm-manager ~]# cd metrics/
[root@swarm-manager metrics]# go mod init metrics

「2、编写metrics.go:」

package mainimport ("github.com/prometheus/client_golang/prometheus""github.com/prometheus/client_golang/prometheus/promhttp""net/http""strconv"
)func main() {metrics := prometheus.NewCounterVec(prometheus.CounterOpts{Name: "http_requests_total",Help: "Number of total http requests",},[]string{"status"},)prometheus.MustRegister(metrics)http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {path := r.URL.PathstatusCode := 200switch path {case "/metrics":promhttp.Handler().ServeHTTP(w, r)default:w.WriteHeader(statusCode)w.Write([]byte("Hello World!"))}metrics.WithLabelValues(strconv.Itoa(statusCode)).Inc()})http.ListenAndServe(":3000", nil)
}

该go项目主要通过/metrics端点暴露http_requests_total指标。

「3、本地编译打包:」

[root@swarm-manager metrics]# go mod tidy
[root@swarm-manager metrics]# go build -o metrics metrics.go

「4、创建镜像,并推送docker hub上:」

编写Dockerfile:

FROM golang:latest
MAINTAINER simon "30743905@qq.com"
RUN mkdir -p /app
WORKDIR /app
COPY ./metrics /app
EXPOSE 3000RUN chmod +x ./metrics
ENTRYPOINT ["./metrics"]

构建镜像:

docker build -t metrics .

「5、k8s部署:」

# sample-httpserver-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: sample-httpservername: sample-httpservernamespace: default
spec:replicas: 1selector:matchLabels:app: sample-httpserverstrategy: {}template:metadata:annotations:prometheus.io/scrape: "true"prometheus.io/path: /metricsprometheus.io/port: "3000"labels:app: sample-httpserverspec:containers:- image: addozhang/httpserver-n-metrics:latestname: httpserver-n-metricsports:- containerPort: 3000resources:requests:memory: '300Mi'
---
apiVersion: v1
kind: Service
metadata:name: sample-httpserverlabels:app: sample-httpserver
spec:ports:- name: webport: 3000targetPort: 3000selector:app: sample-httpserver

「6、接口获取指标正常:」

[root@k8s-01 demo01]# kubectl get svc -n demo01     
NAME                TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
nginx-service       ClusterIP   None            <none>        80/TCP     249d
sample-httpserver   ClusterIP   10.96.153.13    <none>        3000/TCP   32s
tomcat-service      ClusterIP   None            <none>        8080/TCP   249d
web                 ClusterIP   10.96.237.204   <none>        80/TCP     47h
[root@k8s-01 demo01]# curl 10.96.153.13:3000/metrics
# HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 3.5147e-05
go_gc_duration_seconds{quantile="0.25"} 3.8423e-05
go_gc_duration_seconds{quantile="0.5"} 4.1267e-05
go_gc_duration_seconds{quantile="0.75"} 5.0566e-05
go_gc_duration_seconds{quantile="1"} 9.0761e-05
go_gc_duration_seconds_sum 0.001240037
go_gc_duration_seconds_count 25
......

「7、prometheus配置抓取job:」

- job_name: 'app'kubernetes_sd_configs:- role: podrelabel_configs:- action: keepsource_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]regex: true- source_labels: [__meta_kubernetes_namespace]target_label: namespace- source_labels: [__meta_kubernetes_pod_name]target_label: pod

「8、指标抓取验证:」

在prometheus target可以查看到部署的应用指标接入成功:

91f52114846051b040c282a73c2eef89.png

使用PromQL查询:sum(rate(http_requests_total[30s])) by (pod)

9332f9b415918a2e72d3379d04458dcd.png

hpa资源创建

「1、创建hpa:」

# vi app-hpa-v2.yml
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:name: metrics-app-hpa namespace: demo01
spec:scaleTargetRef:apiVersion: apps/v1kind: Deploymentname: sample-httpserverminReplicas: 1maxReplicas: 3metrics:- type: Podspods:metric:name: http_requests_qpstarget:type: AverageValueaverageValue: 2000m   # 2000m 即2个/秒

「2、prometheus-adapter组件配置自定义指标的计算规则,告诉prometheus-adapter如何从prometheus获取指标并计算出我们需要的指标:kubectl edit cm prometheus-adapter -n monitoring

02a429fd2f3a377398f4569c11f05584.png

prometheus-adapter不能动态加载配置,需要kubectl delete pod prometheus-adapter-xx,让Pod重启加载最新配置。

「3、可以访问api-server获取到prometheus-adapter计算生成的新指标:」

[root@k8s-01 ~]# kubectl get --raw '/apis/custom.metrics.k8s.io/v1beta1/namespaces/demo01/pods/*/http_requests_qps' | jq         
{"kind": "MetricValueList","apiVersion": "custom.metrics.k8s.io/v1beta1","metadata": {"selfLink": "/apis/custom.metrics.k8s.io/v1beta1/namespaces/demo01/pods/%2A/http_requests_qps"},"items": [{"describedObject": {"kind": "Pod","namespace": "demo01","name": "sample-httpserver-695f994dbd-s2s2g","apiVersion": "/v1"},"metricName": "http_requests_qps","timestamp": "2023-08-02T15:32:56Z","value": "66m","selector": null}]
}

「注意:这里的 value: 66m,值的后缀“m” 标识 milli-requests per seconds,所以这里的 66m 的意思是 0.06/s 每秒0.06个请求。」

「4、prometheus-adapter有了指标数据,就可以创建hpa基于该指标:kubectl apply -f app-hpa-v2.yml

# vi app-hpa-v2.yml
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:name: metrics-app-hpanamespace: demo01
spec:scaleTargetRef:apiVersion: apps/v1kind: Deploymentname: sample-httpserverminReplicas: 1maxReplicas: 3metrics:- type: Podspods:metric:name: http_requests_qpstarget:type: AverageValueaverageValue: 2000m   # 2000m 即2个/秒

「5、查看hpa从prometheus-adapter组件获取指标正常:」

b00a55bd5ab1c9a174b890851e13289b.png

当前Pod副本数为1:

e41825a97e333b6c93f74d934a5ac76a.png

「6、接口压测:」

[root@k8s-01 ~]# kubectl get svc -n demo01
NAME                TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
nginx-service       ClusterIP   None            <none>        80/TCP     249d
sample-httpserver   ClusterIP   10.96.153.13    <none>        3000/TCP   8m11s
[root@k8s-01 ~]# ab -n 100000 -c 30  http://10.96.153.13:3000/metrics
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/Benchmarking 10.96.153.13 (be patient)
Completed 10000 requests
Completed 20000 requests

「7、弹性伸缩验证:」

查看hpa状态,targets一栏显示当前指标到达10900m左右,斜杠后面2表示到达2就要弹性伸缩,10900m/1000=10左右,明显超过2,则replicas一栏显示当前进行扩容到最大副本数3:

c0d1ee3e13dd8020d14faecff26015a7.png

查看hpa描述信息,可以看到有条Event清晰描述出有图http_requests_qps指标超过target设置的2,副本数设置为3:

acc6137b7849f980d0d50c4407362bc8.png

再来看pod信息,发现副本数确实扩容到3个:

94fc76122bee05b7b6005f7a8e5ffd20.png

「8、弹性缩容验证:」

停止接口压测后,hpa指标下降,200m明显小于2,当大概平稳5分钟后,hpa开始进行缩容,将副本数从3降到1:

00748c1582b01ceb6dda671dfa734330.png

查看hpa描述信息,同样印证了hpa发生缩容:

6bc8dee56ef174e56aeadb62d7ebfda7.png

再来确认下Pod已经变成1个了:

a2937dd117994b64784a29cc5544b49a.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/82092.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

应用在多媒体手机中的低功率立体声编解码器

多媒体手机一般是指可以录制或播放视频的手机。多媒体的定义是多种媒体的综合&#xff0c;一般是图像、文字、声音等多种结合&#xff0c;所以多媒体手机是可以处理和使用图像文字声音相结合的移动设备。目前流行的多媒体概念&#xff0c;主要是指文字、图形、图像、声音等多种…

一文搞定接口幂等性架构设计方案

幂等性介绍 现如今很多系统都会基于分布式或微服务思想完成对系统的架构设计。那么在这一个系统中&#xff0c;就会存在若干个微服务&#xff0c;而且服务间也会产生相互通信调用。那么既然产生了服务调用&#xff0c;就必然会存在服务调用延迟或失败的问题。当出现这种问题&a…

STM32 低功耗-睡眠模式

STM32 睡眠模式 文章目录 STM32 睡眠模式第1章 低功耗模式简介第2章 睡眠模式简介2.1 进入睡眠模式2.1 退出睡眠模式 第3章 睡眠模式代码示例总结 第1章 低功耗模式简介 在 STM32 的正常工作中&#xff0c;具有四种工作模式&#xff1a;运行、睡眠、停止和待机模式。 在系统或…

谷歌推出Flax:JAX的神经网络库

在优化理论中&#xff0c;损失或成本函数测量拟合或预测值与实际值之间的距离。对于大多数机器学习模型&#xff0c;提高性能意味着最小化损失函数。 但对于深度神经网络&#xff0c;执行梯度下降以最小化每个参数的损失函数可能会消耗大量资源。传统方法包括手动推导和编码&a…

nginx部署以及反向代理多域名实现HTTPS访问

nginx部署以及反向代理多域名实现 1.nginx部署 1.1 编写nginx部署文件 docker-compose.yml version: 3 services: nginx:restart: always image: nginx:1.20container_name: nginx-mainports:- 80:80- 443:443volumes: # 基础配置- /opt/nginx_main/nginx-info/nginx.conf:/…

【枚举】CF1706 C

有人一道1400写了一个小时 Problem - C - Codeforces 题意&#xff1a; 思路&#xff1a; 首先先去观察样例&#xff1a; 很显然&#xff0c;对于n是奇数的情况&#xff0c;只有一种情况&#xff0c;直接操作偶数位就好了 主要是没搞清楚n是偶数的情况 其实有个小技巧&…

SQL 相关子查询 和 不相关子查询、Exists 、Not Exists、 多表连接(包含自连接)

不相关子查询 子查询的查询条件不依赖于父查询&#xff0c;称不相关子查询。子查询可以单独运行的 select stu_id,sex,age from student t where sex(select sexfrom studentwhere stu_id10023 )相关子查询 关联子查询 子查询的查询条件依赖于父查询&#xff0c;称为 相关子…

protobuf 2定义string常量

背景 protobuf 2中定义的enum枚举值必须为数字类型&#xff0c;故不支持string类型&#xff0c;但有些业务场景又确实需要定义string常量。 目标 在protobuf 2中定义string常量。 方案 思路&#xff1a;通optional default实现string常量。 细节&#xff1a; 1、protobu…

冠达管理:创新药概念强势拉升,康希诺大涨超15%

立异药概念9日盘中强势拉升&#xff0c;到发稿&#xff0c;昊帆生物“20cm”涨停&#xff0c;康希诺大涨超15%&#xff0c;翰宇药业涨近13%&#xff0c;德展健康涨停&#xff0c;泰格医药、药石科技涨超7%。 康希诺昨日晚间公告&#xff0c;8月7日&#xff0c;公司与 AstraZene…

机器学习笔记 - 使用 YOLOv5、O​​penCV、Python 和 C++ 检测物体

一、YOLO v5简述 YOLO v5虽然已经不是最先进的对象检测器,但是YOLOv5 使用了一个简单的卷积神经网络 CNN架构(相对YOLO v8来讲,不过v8精度是更高了一些),更易理解。这里主要介绍如何轻松使用 YOLO v5来识别图像中的对象。将使用 OpenCV、Python 和 C++ 来加载和调用我们的…

Flowable-结束事件-错误结束事件

目录 定义图形标记XML内容界面操作使用示例视频教程 定义 错误结束事件会在流程到达错误结束事件的时候抛出错误&#xff0c;并结束当前的流程分支。异常结束 事件是有抛出结果的&#xff0c;它需要定义抛出错误码&#xff0c;如果找到了异常开始事件错误码&#xff0c;就会触…

Linux中安装Node

安装 先从 官方网站 下载安装包&#xff0c;有时 node 版本太新会导致失败&#xff0c;详见下方的常见问题第2点 cd /home // 创建目录&#xff0c;将下载好的 node 安装包上传到此目录 mkdir Download mkdir /usr/local/lib/node解压 // 解压&#xff0c;前面是文件当前路径…

在excel调用SAP函数执行SAP数据查找或提交

1、下载插件 2、安装插件 3、执行函数 3.1 第一步 通过SAPRegister连接SAP服务器 var reg SAPRegister("10.10.14.15", "00", "mes", "AQ123456", "800") 需要改为实际的连接信息 "10.10.14.15" 为SAP服务器I…

IDEA 指定spring.profiles.active本地启动

spring.profiles.activedev spring.profiles.activepro

20230809在WIN10下使用python3将DOCX文件转换为TXT文件

20230809在WIN10下使用python3将DOCX文件转换为TXT文件 2023/8/9 11:38 python docx txt https://blog.51cto.com/u_16175446/6620474 如何实现Python读取word内容转为TXT的具体操作步骤 如何实现Python读取word内容转为TXT的具体操作步骤 原创 mob649e81576de12023-07-04 14:0…

为什么会觉得CSS比JavaScript难?

前言 是的&#xff0c;就像你问题中描述的&#xff0c;“用起来没有底&#xff0c;有填不完的坑”&#xff0c;这大概就是css难的地方&#xff0c;因为css关乎的是页面整体的一个ui设计&#xff0c;暂且不说本身关于css的内容是非常繁杂的&#xff0c;主要是页面的设计是考验创…

flutter开发实战-实现首页分类目录入口切换功能

。 在开发中经常遇到首页的分类入口&#xff0c;如美团的美食团购、打车等入口&#xff0c;左右切换还可以分页更多展示。 一、使用flutter_swiper_null_safety 在pubspec.yaml引入 # 轮播图flutter_swiper_null_safety: ^1.0.2二、实现swiper分页代码 由于我这里按照一页8…

Element的el-select下拉框多选添加全选功能

先看效果图 全选&#xff1a; 没有选中时&#xff1a; 选中部分&#xff1a; 作者项目使用的是vue3写法&#xff0c;如果是vue2的自己转换一下 html代码&#xff1a; js代码&#xff1a; 拓展 另一种方法&#xff0c;如果不想使用勾选框&#xff0c;可以试试下面的方…

PPG心率血氧检测健康型沙发方案

《中国心血管健康与疾病报告2021》数据显示&#xff0c;我国心血管病患病人数已达 3.3 亿。目前&#xff0c;心脑血管病 死亡占城乡居民总死亡原因的首位&#xff0c;农村为46.7%&#xff0c;城市为44%。老年人是心脑血管病的主要发病体&#xff0c;老年 人患心脑血管病的几率较…

2023牛客暑期多校训练营7-c-Beautiful Sequence

思路&#xff1a; &#xff0c;则有&#xff0c;也就是说只要知道A1就可以求任意A。由于A是升序排列&#xff0c;所以对于任意&#xff0c;二进制所包含1的最高位第k位来说&#xff0c;表明与第k位相反&#xff0c;要大一些&#xff0c;所以它的第k位为1&#xff0c;的第k位为…