当前位置: 首页 > news >正文

第 6 篇 自定义 Helm Chart

文章目录

  • 第 1 步:创建 chart
    • Chart.yaml
    • values.yaml
    • templates 模板文件
      • _helpers.tpl 模板辅助文件
      • serviceaccount.yaml
      • service.yaml
      • deployment.yaml
      • hpa.yaml
      • ingress.yaml
      • NOTES.txt
      • tests/test-connection.yaml
  • 第 2 步:检查 chart 格式
  • 第 3 步:模拟运行
  • 第 4 步:打包并上传到仓库
    • 打包并上传
    • 生成 index.yaml 并上传
      • 生成仅一个 chart 的 index.yaml
      • 合并生成 index.yaml
  • 相关博文

🚀 本文内容:如何创建一个属于自己的 chart。

⭐ 详细步骤:

  • 使用 helm create mychart 创建 chart,chart 名称为 mychart,默认为 nginx
  • 修改 chart,以满足实际的自定义需求
  • 使用 helm lint mychart 检查格式
  • 使用 helm install 模拟运行/实际运行 chart,验证是否满足功能要求
  • 打包并生成 index.yaml

下面的例子,创建一个 Nginx chart。默认创建的 chart 是以 nginx 为例的。

第 1 步:创建 chart

使用 helm create mychart 创建 chart:

helm create mychart
# Creating mychart

查看创建的目录及文件:

mychart/Chart.yamlvalues.yamltemplates/deployment.yamlhpa.yamlingress.yamlserviceaccount.yamlservice.yaml_helpers.tpl          # 可被复用的 chart 模板辅助对象NOTES.txttests/test-connection.yamlcharts/

Chart.yaml

内容不多:

apiVersion: v2
name: mychart
description: A Helm chart for Kubernetes
type: application
# chart 版本
version: 0.1.0
# nginx 版本
appVersion: "1.16.0"

values.yaml

可以看到,有很多是默认就存在的配置。

  • replicaCount:副本数量
  • image:容器镜像相关
  • serviceAccount:服务账号
  • podAnnotations、podSecurityContext:Pod 相关
  • securityContext:安全上下文
  • service、ingress
  • resources、autoscaling
  • nodeSelector、tolerations、affinity
# Default values for mychart.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.replicaCount: 1image:repository: nginxpullPolicy: IfNotPresent# Overrides the image tag whose default is the chart appVersion.tag: ""imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""serviceAccount:# Specifies whether a service account should be createdcreate: true# Annotations to add to the service accountannotations: {}# The name of the service account to use.# If not set and create is true, a name is generated using the fullname templatename: ""podAnnotations: {}podSecurityContext: {}# fsGroup: 2000securityContext: {}# capabilities:#   drop:#   - ALL# readOnlyRootFilesystem: true# runAsNonRoot: true# runAsUser: 1000service:type: ClusterIPport: 80ingress:enabled: falseclassName: ""annotations: {}# kubernetes.io/ingress.class: nginx# kubernetes.io/tls-acme: "true"hosts:- host: chart-example.localpaths:- path: /pathType: ImplementationSpecifictls: []#  - secretName: chart-example-tls#    hosts:#      - chart-example.localresources: {}# We usually recommend not to specify default resources and to leave this as a conscious# choice for the user. This also increases chances charts run on environments with little# resources, such as Minikube. If you do want to specify resources, uncomment the following# lines, adjust them as necessary, and remove the curly braces after 'resources:'.# limits:#   cpu: 100m#   memory: 128Mi# requests:#   cpu: 100m#   memory: 128Miautoscaling:enabled: falseminReplicas: 1maxReplicas: 100targetCPUUtilizationPercentage: 80# targetMemoryUtilizationPercentage: 80nodeSelector: {}tolerations: []affinity: {}

templates 模板文件

_helpers.tpl 模板辅助文件

_helpers.tpl 是一个模板辅助文件,比如最常见的 chart 名称的处理。

{{/*
Expand the name of the chart.
*/}}
{{- define "mychart.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "mychart.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "mychart.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}{{/*
Common labels
*/}}
{{- define "mychart.labels" -}}
helm.sh/chart: {{ include "mychart.chart" . }}
{{ include "mychart.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}{{/*
Selector labels
*/}}
{{- define "mychart.selectorLabels" -}}
app.kubernetes.io/name: {{ include "mychart.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}{{/*
Create the name of the service account to use
*/}}
{{- define "mychart.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "mychart.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}

serviceaccount.yaml

创建 ServiceAccount:

{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:name: {{ include "mychart.serviceAccountName" . }}labels:{{- include "mychart.labels" . | nindent 4 }}{{- with .Values.serviceAccount.annotations }}annotations:{{- toYaml . | nindent 4 }}{{- end }}
{{- end }}

service.yaml

创建 Service:

apiVersion: v1
kind: Service
metadata:name: {{ include "mychart.fullname" . }}labels:{{- include "mychart.labels" . | nindent 4 }}
spec:type: {{ .Values.service.type }}ports:- port: {{ .Values.service.port }}targetPort: httpprotocol: TCPname: httpselector:{{- include "mychart.selectorLabels" . | nindent 4 }}

deployment.yaml

创建 Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:name: {{ include "mychart.fullname" . }}labels:{{- include "mychart.labels" . | nindent 4 }}
spec:{{- if not .Values.autoscaling.enabled }}replicas: {{ .Values.replicaCount }}{{- end }}selector:matchLabels:{{- include "mychart.selectorLabels" . | nindent 6 }}template:metadata:{{- with .Values.podAnnotations }}annotations:{{- toYaml . | nindent 8 }}{{- end }}labels:{{- include "mychart.selectorLabels" . | nindent 8 }}spec:{{- with .Values.imagePullSecrets }}imagePullSecrets:{{- toYaml . | nindent 8 }}{{- end }}serviceAccountName: {{ include "mychart.serviceAccountName" . }}securityContext:{{- toYaml .Values.podSecurityContext | nindent 8 }}containers:- name: {{ .Chart.Name }}securityContext:{{- toYaml .Values.securityContext | nindent 12 }}image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"imagePullPolicy: {{ .Values.image.pullPolicy }}ports:- name: httpcontainerPort: 80protocol: TCPlivenessProbe:httpGet:path: /port: httpreadinessProbe:httpGet:path: /port: httpresources:{{- toYaml .Values.resources | nindent 12 }}{{- with .Values.nodeSelector }}nodeSelector:{{- toYaml . | nindent 8 }}{{- end }}{{- with .Values.affinity }}affinity:{{- toYaml . | nindent 8 }}{{- end }}{{- with .Values.tolerations }}tolerations:{{- toYaml . | nindent 8 }}{{- end }}

hpa.yaml

创建 HorizontalPodAutoscaler:

{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:name: {{ include "mychart.fullname" . }}labels:{{- include "mychart.labels" . | nindent 4 }}
spec:scaleTargetRef:apiVersion: apps/v1kind: Deploymentname: {{ include "mychart.fullname" . }}minReplicas: {{ .Values.autoscaling.minReplicas }}maxReplicas: {{ .Values.autoscaling.maxReplicas }}metrics:{{- if .Values.autoscaling.targetCPUUtilizationPercentage }}- type: Resourceresource:name: cputargetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}{{- end }}{{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}- type: Resourceresource:name: memorytargetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}{{- end }}
{{- end }}

ingress.yaml

创建 Ingress:

{{- if .Values.ingress.enabled -}}
{{- $fullName := include "mychart.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}{{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }}{{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}{{- end }}
{{- end }}
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1beta1
{{- else -}}
apiVersion: extensions/v1beta1
{{- end }}
kind: Ingress
metadata:name: {{ $fullName }}labels:{{- include "mychart.labels" . | nindent 4 }}{{- with .Values.ingress.annotations }}annotations:{{- toYaml . | nindent 4 }}{{- end }}
spec:{{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}ingressClassName: {{ .Values.ingress.className }}{{- end }}{{- if .Values.ingress.tls }}tls:{{- range .Values.ingress.tls }}- hosts:{{- range .hosts }}- {{ . | quote }}{{- end }}secretName: {{ .secretName }}{{- end }}{{- end }}rules:{{- range .Values.ingress.hosts }}- host: {{ .host | quote }}http:paths:{{- range .paths }}- path: {{ .path }}{{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }}pathType: {{ .pathType }}{{- end }}backend:{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}service:name: {{ $fullName }}port:number: {{ $svcPort }}{{- else }}serviceName: {{ $fullName }}servicePort: {{ $svcPort }}{{- end }}{{- end }}{{- end }}
{{- end }}

NOTES.txt

1. Get the application URL by running these commands:
{{- if .Values.ingress.enabled }}
{{- range $host := .Values.ingress.hosts }}{{- range .paths }}http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}{{- end }}
{{- end }}
{{- else if contains "NodePort" .Values.service.type }}export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "mychart.fullname" . }})export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")echo http://$NODE_IP:$NODE_PORT
{{- else if contains "LoadBalancer" .Values.service.type }}NOTE: It may take a few minutes for the LoadBalancer IP to be available.You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "mychart.fullname" . }}'export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "mychart.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")echo http://$SERVICE_IP:{{ .Values.service.port }}
{{- else if contains "ClusterIP" .Values.service.type }}export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "mychart.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")echo "Visit http://127.0.0.1:8080 to use your application"kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
{{- end }}

tests/test-connection.yaml

Chart Test,用于测试验证 chart 是否按预期运行。也可以具体划分下,放在 tests 目录下【这样可以定义更多的 Test,且能更好的与模板隔离开】。

test 放在 templates/ 目录下,其会指定容器并执行特定的任务,任务的定义必须包含测试钩子的注释:"helm.sh/hook": test

test 本质就是一个 Helm 钩子,所以类似于 helm.sh/hook-weighthelm.sh/hook-delete-policy的注释也可用于 test。

apiVersion: v1
kind: Pod
metadata:name: "{{ include "mychart.fullname" . }}-test-connection"labels:{{- include "mychart.labels" . | nindent 4 }}annotations:"helm.sh/hook": test
spec:containers:- name: wgetimage: busyboxcommand: ['wget']args: ['{{ include "mychart.fullname" . }}:{{ .Values.service.port }}']restartPolicy: Never

运行方式:

helm install demo demo --namespace default# 执行 Chart 测试
helm test demo

第 2 步:检查 chart 格式

helm lint mychart/
# ==> Linting mychart/
# [INFO] Chart.yaml: icon is recommended
# 
# 1 chart(s) linted, 0 chart(s) failed

第 3 步:模拟运行

helm install 时添加 – dry-run,即可模拟运行。命令如下:

helm install --debug --dry-run goodly-guppy ./mychart

运行日志如下:

  • 重点1:Release 基本信息
  • 重点2:Values 数据,用户提供的 Values + 最终计算得出的 Values
  • 重点3:helm hooks,这里是 test 钩子,执行连接测试的
  • 重点4:实际运行的 Kubernetes manifest
  • 重点5:打印出的 NOTES.txt (已使用模板渲染过)
install.go:173: [debug] Original chart version: ""
install.go:190: [debug] CHART PATH: /home/userlocal/mychart#### 重点1:Release 基本信息
NAME: goodly-guppy
LAST DEPLOYED: Mon May 27 14:28:22 2024
NAMESPACE: default
STATUS: pending-install
REVISION: 1#### 重点2:Values 数据,用户提供的 Values + 最终计算得出的 Values
USER-SUPPLIED VALUES:
{}COMPUTED VALUES:
affinity: {}
autoscaling:enabled: falsemaxReplicas: 100minReplicas: 1targetCPUUtilizationPercentage: 80
fullnameOverride: ""
image:pullPolicy: IfNotPresentrepository: nginxtag: ""
imagePullSecrets: []
ingress:annotations: {}className: ""enabled: falsehosts:- host: chart-example.localpaths:- path: /pathType: ImplementationSpecifictls: []
nameOverride: ""
nodeSelector: {}
podAnnotations: {}
podSecurityContext: {}
replicaCount: 1
resources: {}
securityContext: {}
service:port: 80type: ClusterIP
serviceAccount:annotations: {}create: truename: ""
tolerations: []#### 重点3:helm hooks,这里是 test 钩子,执行连接测试的
HOOKS:
---
# Source: mychart/templates/tests/test-connection.yaml
apiVersion: v1
kind: Pod
metadata:name: "goodly-guppy-mychart-test-connection"labels:helm.sh/chart: mychart-0.1.0app.kubernetes.io/name: mychartapp.kubernetes.io/instance: goodly-guppyapp.kubernetes.io/version: "1.16.0"app.kubernetes.io/managed-by: Helmannotations:"helm.sh/hook": test
spec:containers:- name: wgetimage: busyboxcommand: ['wget']args: ['goodly-guppy-mychart:80']restartPolicy: Never#### 重点4:实际运行的 Kubernetes manifest
MANIFEST:
---
# Source: mychart/templates/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:name: goodly-guppy-mychartlabels:helm.sh/chart: mychart-0.1.0app.kubernetes.io/name: mychartapp.kubernetes.io/instance: goodly-guppyapp.kubernetes.io/version: "1.16.0"app.kubernetes.io/managed-by: Helm
---
# Source: mychart/templates/service.yaml
apiVersion: v1
kind: Service
metadata:name: goodly-guppy-mychartlabels:helm.sh/chart: mychart-0.1.0app.kubernetes.io/name: mychartapp.kubernetes.io/instance: goodly-guppyapp.kubernetes.io/version: "1.16.0"app.kubernetes.io/managed-by: Helm
spec:type: ClusterIPports:- port: 80targetPort: httpprotocol: TCPname: httpselector:app.kubernetes.io/name: mychartapp.kubernetes.io/instance: goodly-guppy
---
# Source: mychart/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: goodly-guppy-mychartlabels:helm.sh/chart: mychart-0.1.0app.kubernetes.io/name: mychartapp.kubernetes.io/instance: goodly-guppyapp.kubernetes.io/version: "1.16.0"app.kubernetes.io/managed-by: Helm
spec:replicas: 1selector:matchLabels:app.kubernetes.io/name: mychartapp.kubernetes.io/instance: goodly-guppytemplate:metadata:labels:app.kubernetes.io/name: mychartapp.kubernetes.io/instance: goodly-guppyspec:serviceAccountName: goodly-guppy-mychartsecurityContext:{}containers:- name: mychartsecurityContext:{}image: "nginx:1.16.0"imagePullPolicy: IfNotPresentports:- name: httpcontainerPort: 80protocol: TCPlivenessProbe:httpGet:path: /port: httpreadinessProbe:httpGet:path: /port: httpresources:{}#### 重点5:打印出的 NOTES.txt (已使用模板渲染过)
NOTES:
1. Get the application URL by running these commands:export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=mychart,app.kubernetes.io/instance=goodly-guppy" -o jsonpath="{.items[0].metadata.name}")export CONTAINER_PORT=$(kubectl get pod --namespace default $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")echo "Visit http://127.0.0.1:8080 to use your application"kubectl --namespace default port-forward $POD_NAME 8080:$CONTAINER_PORT

模拟运行或实际运行符合预期后,即可打包上传到仓库了。

第 4 步:打包并上传到仓库

打包并上传

先进行打包,打包后手动将 mychart-0.1.0.tgz 上传到 chart 仓库。

# 第 1 步:打包:未做签名哦
helm package mychart/
# Successfully packaged chart and saved it to: /home/userlocal/mychart-0.1.0.tgz# 第 2 步:移动到 mychart/:不移动的话,后面生成的 index.yaml 是空的!!!
mv mychart-0.1.0.tgz mychart/

生成 index.yaml 并上传

生成 index.yaml 有两种方式:

  • 直接生成,index.yaml 里只有一个 chart
  • 合并生产,根据现有仓库的 index.yaml,添加当前 chart 进去

生成仅一个 chart 的 index.yaml

命令如下:

# 生成 index.yaml 
helm repo index mychart/ --url http://nexus.hengtiansoft.space/repository/helm-repo/# 查看 index.yaml
cat mychart/index.yaml 
# apiVersion: v1
# entries:
#   mychart:
#   - apiVersion: v2
#     appVersion: 1.16.0
#     created: "2024-05-27T15:01:22.810201593+08:00"
#     description: A Helm chart for Kubernetes
#     digest: 0a07369207529008da67a724dda35b86b4721b3dfe9dffcabb2ce767c2267b9d
#     name: mychart
#     type: application
#     urls:
#     - http://nexus.hengtiansoft.space/repository/helm-repo/mychart-0.1.0.tgz
#     version: 0.1.0
# generated: "2024-05-27T15:01:22.808723439+08:00"

合并生成 index.yaml

# 跳转到 chart 目录
cd mychart/# 下载仓库 index.yaml
wget http://nexus.xxx.space/repository/helm-repo/index.yaml# 合并生成 index.yaml
helm repo index . --merge index.yaml# 查看合并生成的 index.yaml
cat index.yaml | grep -A 5  mychart
#   mychart:
#   - apiVersion: v2
#     appVersion: 1.16.0
#     created: "2024-05-27T15:09:00.3621419+08:00"
#     description: A Helm chart for Kubernetes
#     digest: 0a07369207529008da67a724dda35b86b4721b3dfe9dffcabb2ce767c2267b9d
#     name: mychart
#     type: application
#     urls:
#     - mychart-0.1.0.tgz
#     version: 0.1.0
#   mysql:
#   - apiVersion: v1
#     appVersion: 8.0.33
#     created: "2023-10-30T02:54:37.437Z"

如果你使用 Nexus 作为 chart 仓库,则直接上传 chart tgz 包,然后 Rebuild Index 即可刷新 index.yaml 文件。

相关博文

1.第 1 篇 Helm 简介及安装
2.第 2 篇 Helm 部署 MySQL【入门案例】
3.第 3 篇 Helm 命令、环境变量、相关目录
4.第 4 篇 Chart 仓库详解
5.第 5 篇 Chart 文件结构详解
6.第 6 篇 自定义 Helm Chart
7.第 7 篇 Helm 部署 Nacos【详细步骤】
8.第 8 篇 Chart 修改入门示例:Nacos
9.第 9 篇 Helm 部署 Seata Server
10.第 10 篇 Chart 修改完美示例:Seata Server
11.第 11篇 Helm 部署 RabbitMQ
12.第 12 篇 Helm 部署 Redis
13.第13 篇 Helm 部署 ElasticSearch

相关文章:

第 6 篇 自定义 Helm Chart

文章目录 第 1 步:创建 chartChart.yamlvalues.yamltemplates 模板文件_helpers.tpl 模板辅助文件serviceaccount.yamlservice.yamldeployment.yamlhpa.yamlingress.yamlNOTES.txttests/test-connection.yaml 第 2 步:检查 chart 格式第 3 步&#xff1a…...

Jenkis部署vue前端项目提示:sh: vue-cli-service: command not found

解决方法: 1. 进入到/var/lib/jenkins/workspace/项目名下,查看是否有node_modules,如果没有执行 npm install 2. 如果执行npm intall的过程中提示:npm ERR! 407 Proxy Authentication Required - GET http://registry.npm.taob…...

中介者模式mediator

学习笔记,原文链接 https://refactoringguru.cn/design-patterns/mediator 减少对象之间混乱无序的依赖关系。 该模式会限制对象之间的直接交互, 迫使它们通过一个中介者对象进行合作。...

GO语言性能分析

Go语言基准测试与pprof工具性能分析详解 在现代软件开发中,性能优化是一个重要的环节。Go语言提供了强大的工具来进行基准测试和性能分析,其中 testing 包用于基准测试,而 pprof 工具用于性能分析。本文将详细讲解如何使用这些工具来进行性能…...

关于 PreparedStatement

Mysql 层面的语法也支持 prepare 这个确实第一次见 PREPARE prepares a statement for execution (see Section 13.5.1, “PREPARE Statement”).EXECUTE executes a prepared statement (see Section 13.5.2, “EXECUTE Statement”).DEALLOCATE PREPARE releases a prepared…...

漫谈设计模式 [9]:外观模式

引导性开场 菜鸟:老鸟,我最近在做一个项目,感觉代码越来越复杂,我都快看不懂了。尤其是有好几个子系统,它们之间的调用关系让我头疼。 老鸟:复杂的代码确实让人头疼。你有没有考虑过使用设计模式来简化你…...

多进程编程

基本概念 进程是一个具有单独功能的程序对某个数据集在处理机上的执行过程,进程也是作为资源分配的一个单位。 进程和程序是相辅相成的,进程是一个动态概念。 进程具有并行性特征。进程具有独立性和异步性。 进程的描述 进程分为三部分:…...

7-Zip压缩包如何添加密码,加密后如何取消

压缩包文件大家经常使用,最熟悉的肯定是RAR、ZIP格式压缩文件,但是7z压缩文件格式也很好用,它是三种压缩文件格式中压缩率最大的。想要将文件压缩到最小,使用7z格式可以达到最大化。那么在使用7z压缩格式的时候,我们可…...

HarmonyOS---应用测试概述

一、应用质量要求 应用质量要求分为应用体验质量建议和应用内容合规要求两大部分。 1、应用体验质量建议 功能数据完备、基础体验要求、HarmonyOS特征增强体验要求。 (1)功能数据完备 (2)基础体验要求 (3)增…...

密码学---真题演练

✨Base加密:题目-base? 靶场网址:https://polarctf.com/ Base100加密!!! 得到的新的一串密码是 rot47 密码,属于凯撒密码的一种变体. ✨斐波那契:题目-FB 从第三项开始,每一项都等…...

时间日期工具类

时间日期工具类 import java.time.*; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit;public class DateTimeUtils {private static final String DEFAULT_DATE_FORMAT "yyyy-MM-dd";private static final String DEFAULT_TIME_…...

linux中vim常用命令大全

前言 Linux有大量的配置文件,所以 Linux的文本处理工具也是比较多的,其中编辑一些配置文件时,常用的工具就是 vim。在Linux中,Vim编辑器是一个非常强大的文本编辑工具,它提供了多种模式和命令来满足不同的编辑需求。以…...

计算机的错误计算(八十九)

摘要 探讨反双曲余切函数 acoth(x) 在 附近的计算精度问题。 Acoth(x) 函数的定义为: 其中 x 的绝对值大于 1 . 例1. 计算 acoth(1.000000000002) . 不妨在 Excel 的单元格中计算,则有: 若在Python中用定义直接计算,则有几乎…...

深入理解java并发编程之aqs框架

跟synchronized 相比较,可重入锁ReentrankLock其实原理有什么不同? 所得基本原理是为了达到一个目的;就是让所有线程都能看到某种标记。synchronized通过在对象头中设置标记实现了这一目的,是一种JVM原生的锁实现方式。而Reentran…...

ubuntu配置tftp、nfs

tftp配置 tftp是简单文件传输协议,基于udp实现传输。这里的简单文件,指的是不复杂、开销不大的文件。 先在ubuntu中安装tftp,输入命令:sudo apt-get install tftp-hpa tftpd-hpa。 接着配置tftp。 输入命令:sudo v…...

Sklearn的datasets模块与自带数据集介绍

datasets 模块 用 dir() 函数查看 datasets 模块的所有属性和函数 import sklearn.datasets as datasets# 列出 sklearn.datasets 模块中的所有属性和函数 print(dir(datasets)) datasets 模块下的数据集有三种类型: (1)load系列的经典数…...

css 个人喜欢的样式 速查笔记

起因&#xff0c; 目的: 记录自己喜欢的&#xff0c; 觉得比较好看的 css. 下次用的时候&#xff0c;直接复制&#xff0c;很方便。 1. 个人 html 模板&#xff0c; 导入常用的 link 设置英语字体: Noto导入默认的 css使用网络 icon 图标导入 Bootstrap css 框架 html <…...

C/C++ let __DATE__ format to “YYYY-MM-DD“

C/C let DATE format to “YYYY-MM-DD” code&#xff1a; #include <iostream> #include <string>class compileDate {// 静态函数&#xff0c;用来格式化并返回编译日期 static std::string formatCompileDate() {// 编译时的日期&#xff0c;格式为 "MMM…...

git如何灵活切换本地账号对应远程github的两个账号

git如何灵活切换本地账号对应远程github的两个账号 问题&#xff1a; 有时候我们会同时维护两个github的账号里面的仓库内容&#xff0c;这时候本地git需要频繁的切换ssh&#xff0c;以方便灵活的与两个账号的仓库可以通信。这篇日记将阐述我是怎么解决这个问题的。1. 第一个账…...

Python中实现函数的递归调用

在Python中&#xff0c;函数的递归调用是一种非常强大且常用的编程技巧&#xff0c;它允许函数在其执行过程中调用自身。递归调用在解决许多问题时都显得尤为方便&#xff0c;比如遍历树形结构、计算阶乘、实现快速排序等。然而&#xff0c;递归也需要谨慎使用&#xff0c;因为…...

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…...

测试微信模版消息推送

进入“开发接口管理”--“公众平台测试账号”&#xff0c;无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息&#xff1a; 关注测试号&#xff1a;扫二维码关注测试号。 发送模版消息&#xff1a; import requests da…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上&#xff0c;开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识&#xff0c;在 vs 2017 平台上&#xff0c;进行 ASP.NET 应用程序和简易网站的开发&#xff1b;初步熟悉开发一…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具

第2章 虚拟机性能监控&#xff0c;故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令&#xff1a;jps [options] [hostid] 功能&#xff1a;本地虚拟机进程显示进程ID&#xff08;与ps相同&#xff09;&#xff0c;可同时显示主类&#x…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

Mobile ALOHA全身模仿学习

一、题目 Mobile ALOHA&#xff1a;通过低成本全身远程操作学习双手移动操作 传统模仿学习&#xff08;Imitation Learning&#xff09;缺点&#xff1a;聚焦与桌面操作&#xff0c;缺乏通用任务所需的移动性和灵活性 本论文优点&#xff1a;&#xff08;1&#xff09;在ALOHA…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比

在机器学习的回归分析中&#xff0c;损失函数的选择对模型性能具有决定性影响。均方误差&#xff08;MSE&#xff09;作为经典的损失函数&#xff0c;在处理干净数据时表现优异&#xff0c;但在面对包含异常值的噪声数据时&#xff0c;其对大误差的二次惩罚机制往往导致模型参数…...