ArgoWorkflow教程(三)---使用 Artifacts 实现步骤间文件共享

argoworkflow-3-artifacts.png

上一篇我们分析了 Workflow、WorkflowTemplate、template 之间的关系。本篇主要分析如何在 argo-workflow 中使用 S3 存储 artifact 实现步骤之间的文件共享。

本文主要解决两个问题:

  • 1)artifact-repository 如何配置
  • 2)Workflow 中如何使用

1. artifact-repository 配置

ArgoWorkflow 对接 S3 实现持久化,依赖于 artifact-repository 配置。

有三种方式设置相关配置:

  • 1)全局配置:在 workflow-controller deploy 中直接通过配置文件方式写入 S3 相关配置,指定全局使用的artifactRepository, 该方式优先级最低,可以被后续两种方式替换。
  • 2)命名空间默认配置:ArgoWorkflow 会在 Workflow 所在命名空间寻找当前命名空间的默认配置,该方式配置优先级第二,可以覆盖全局指定的配置。
    • 规定:会在 Workflow 所在命名空间寻找名为 artifact-repositories 的 Configmap 作为配置。
  • 3)Workflow 中指定配置:还可以在 Workflow 中显式指定使用哪个 artifact-repository,该方式优先级最高。

注意📢不管什么方式指定 artifact-repository,其中存储 S3 AKSK 信息的 Secret 都必须同步到 Workflow 所在的命名空间才行

优先级 InWorkflowConfig > Namespace > Global

全局配置

以 helm 方式部署的 ArgoWorkflow 的话默认就会以这种形式指定配置。

workflow-controller 的 deployment yaml 如下:

apiVersion: apps/v1
kind: Deployment
metadata:name: argo-workflow-argo-workflows-workflow-controllernamespace: argo-dev
spec:template:metadata:spec:containers:- args:- --configmap- argo-workflow-argo-workflows-workflow-controller-configmap- --executor-image- quay.io/argoproj/argoexec:v3.4.11- --loglevel- info- --gloglevel- "0"- --log-format- text

可以看到在启动命令中以 --configmap argo-workflow-argo-workflows-workflow-controller-configmap 方式指定了配置文件来源的 Configmap。

这个 Configmap 的内容如下:

apiVersion: v1
data:# ... 省略artifactRepository: |s3:endpoint: minio.default.svc:9000bucket: argoinsecure: trueaccessKeySecret:name: my-s3-secretkey: accessKeysecretKeySecret:name: my-s3-secretkey: secretKey
kind: ConfigMap
metadata:name: argo-workflows-workflow-controller-configmapnamespace: argo

包括了 S3 的 endpoint、bucket、aksk 等信息,借助这些信息 Workflow 就可以访问 S3 了。

命名空间默认配置

根据当前实现,ArgoWorkflow 会优先使用 Workflow 所在命名空间下的默认 artifactRepository 配置

默认会使用名为 artifact-repositories 的 Configmap 作为当前命名空间下 Workflow 的 artifactRepository 配置,Configmap 中的内容大概长这样:

注意:Configmap 名必须是 artifact-repositories

apiVersion: v1
kind: ConfigMap
metadata:# If you want to use this config map by default, name it "artifact-repositories". Otherwise, you can provide a reference to a# different config map in `artifactRepositoryRef.configMap`.name: artifact-repositoriesannotations:# v3.0 and after - if you want to use a specific key, put that key into this annotation.workflows.argoproj.io/default-artifact-repository: my-artifact-repository
data:my-artifact-repository: |s3:bucket: lixd-argoendpoint: minio.argo-dev.svc:9000insecure: trueaccessKeySecret:name: my-s3-secretkey: accessKeysecretKeySecret:name: my-s3-secretkey: secretKey# 可以写多个 Repositorymy-artifact-repository2: ...

Data 中的每一个 Key 对应一个 Repository, 然后使用 workflows.argoproj.io/default-artifact-repository annotation 来指定默认使用哪个 artifactRepository

比如这里就指定了 my-artifact-repository 为默认 artifactRepository.

Workflow 中指定配置

除此之外,还可以直接在 Workflow 中指定具体要使用哪个 artifactRepository。

spec:artifactRepositoryRef:configMap: my-artifact-repository # default is "artifact-repositories"key: v2-s3-artifact-repository # default can be set by the `workflows.argoproj.io/default-artifact-repository` annotation in config map.

需要指定 Configmap 以及具体的 Key 来找到唯一的 artifactRepository。

只会在当前命名空间下找,因此需要确保这个 Configmap 存在。

或者直接把 S3 配置写到 Workflow 里(不推荐),就像这样:

  templates:- name: artifact-exampleinputs:artifacts:- name: my-input-artifactpath: /my-input-artifacts3:endpoint: s3.amazonaws.combucket: my-aws-bucket-namekey: path/in/bucket/my-input-artifact.tgzaccessKeySecret:name: my-aws-s3-credentialskey: accessKeysecretKeySecret:name: my-aws-s3-credentialskey: secretKeyoutputs:artifacts:- name: my-output-artifactpath: /my-output-artifacts3:endpoint: storage.googleapis.combucket: my-gcs-bucket-name# NOTE that, by default, all output artifacts are automatically tarred and# gzipped before saving. So as a best practice, .tgz or .tar.gz# should be incorporated into the key name so the resulting file# has an accurate file extension.key: path/in/bucket/my-output-artifact.tgzaccessKeySecret:name: my-gcs-s3-credentialskey: accessKeysecretKeySecret:name: my-gcs-s3-credentialskey: secretKeyregion: my-GCS-storage-bucket-regioncontainer:image: debian:latestcommand: [sh, -c]args: ["cp -r /my-input-artifact /my-output-artifact"]

只会在当前命名空间下找,因此需要确保这个 Configmap 存在。

小结

包括三种方式:

  • 1)全局配置
  • 2)命名空间默认配置
  • 3)Workflow 中指定配置

注意📢:由于 S3 AKSK 以 Secret 方式存储,因此三种配置方式都需要将该 Secret 同步到 Workflow 所在命名空间,否则无法在 Pod 中使用,导致 Workflow 无法正常运行。

如果 ArgoWorkflow 能自动接管就好了,可以使用 https://github.com/mittwald/kubernetes-replicator 来自动同步

三种方式的区别

  • 全局配置全局只需要一个 Configmap 来指定 S3 信息即可,所有 Workflow 都使用该 S3 配置,简单,但是不够灵活。
  • 命名空间默认配置:该方式可以为不同命名空间配置不同的 S3,但是需要在每个命名空间都创建一个 Configmap。
  • Workflow 中指定配置:这种方式最灵活,可以为不同 Workflow 指定不同 S3,但是需要创建很多 Configmap。

使用场景

如果全局只有一个 S3 配置,那就使用 全局配置方式,最简单。

如果租户间使用命名空间隔离,使用不同 S3,那使用命名空间默认配置方式就刚好

以上都不满足的时候,才建议使用 Workflow 中指定配置方式。

2. Workflow 中使用 artifact

key-only-artifacts

当 Workflow 中不显式指定 S3 配置信息时,argo 会按照前面的优先级自动寻找 artifact-repository 配置。

优先使用 Namespace 下的配置,没有则使用全局配置

一个完整的 Demo 如下:

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:generateName: artifact-passing-
spec:entrypoint: artifact-exampletemplates:- name: artifact-examplesteps:- - name: generate-artifacttemplate: whalesay- - name: consume-artifacttemplate: print-messagearguments:artifacts:# bind message to the hello-art artifact# generated by the generate-artifact step- name: messagefrom: "{{steps.generate-artifact.outputs.artifacts.hello-art}}"- name: whalesaycontainer:image: docker/whalesay:latestcommand: [sh, -c]args: ["cowsay hello world | tee /tmp/hello_world.txt"]outputs:artifacts:# generate hello-art artifact from /tmp/hello_world.txt# artifacts can be directories as well as files- name: hello-artpath: /tmp/hello_world.txt- name: print-messageinputs:artifacts:# unpack the message input artifact# and put it at /tmp/message- name: messagepath: /tmp/messagecontainer:image: alpine:latestcommand: [sh, -c]args: ["cat /tmp/message"]

第一个步骤,通过

第一个步骤,通过 tee 命令创建了一个文件并通过 outputs 进行输出,由于指定的是 artifacts,因此这个文件会被存储到 S3。

然后第二个步骤指定 inputs.artifacts 从 S3 读取名为 message 的 artifact 并存储到 /tmp/message 目录。

问题来了第二步中读取的 artifact 是从哪儿来的呢,就是 steps 中通过 arguments.artifacts 指定的,通过 name 进行关联。

整个逻辑和 parameter 基本一致

  • 1)whalesay template 通过 outputs.artifacts 来申明当前 template 会输出一个 artifact。

  • 2)print-message 中通过 inputs.artifacts 申明需要一个 artifact,并指定存储位置

  • 3)steps 在使用该 template 时,通过 arguments.artifacts 来指定一个 artifact,这个 artifact 来源就是 1 中的 output,通过{{steps.generate-artifact.outputs.artifacts.$name}} 语法引用。

	artifact-passing-vzp2r-1469537892:boundaryID: artifact-passing-vzp2rdisplayName: generate-artifactfinishedAt: "2024-03-29T08:42:34Z"hostNodeName: lixd-argoid: artifact-passing-vzp2r-1469537892message: 'Error (exit code 1): You need to configure artifact storage. Moreinformation on how to do this can be found in the docs: https://argo-workflows.readthedocs.io/en/release-3.5/configure-artifact-repository/'name: artifact-passing-vzp2r[0].generate-artifact

artifact 压缩

默认情况下,所有的 artifact 会被打成 tar 包并 gzip 压缩,可以通过archive 字段来配置压缩情况:

  • 默认行为:tar + gzip
  • 可选关闭 tar+ gzip
  • 或者配置 gzip 压缩等级
<... snipped ...>outputs:artifacts:# default behavior - tar+gzip default compression.- name: hello-art-1path: /tmp/hello_world.txt# disable archiving entirely - upload the file / directory as is.# this is useful when the container layout matches the desired target repository layout.   - name: hello-art-2path: /tmp/hello_world.txtarchive:none: {}# customize the compression behavior (disabling it here).# this is useful for files with varying compression benefits, # e.g. disabling compression for a cached build workspace and large binaries, # or increasing compression for "perfect" textual data - like a json/xml export of a large database.- name: hello-art-3path: /tmp/hello_world.txtarchive:tar:# no compression (also accepts the standard gzip 1 to 9 values)compressionLevel: 0
<... snipped ...>

Artifact 垃圾回收

所有 Artifact 都会上传到 S3,为了保证 S3 不被填满,垃圾清理是个问题。

好消息是,argo-workflow 3.4 开始,可以在 Workflow 中添加配置来实现自动删除不需要的 Artifacts。

当前提供两种回收策略,分别是:

  • OnWorkflowCompletion:工作流运行完成后就删除
  • OnWorkflowDeletion:工作流被删除时才删除

同时可以统一为 Workflow 中的所有 artifact 配置回收策略,也可以单独为每一个 artifact 配置回收策略。

Demo 如下:

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:generateName: artifact-gc-
spec:entrypoint: mainartifactGC:strategy: OnWorkflowDeletion  # default Strategy set here applies to all Artifacts by defaulttemplates:- name: maincontainer:image: argoproj/argosay:v2command:- sh- -cargs:- |echo "can throw this away" > /tmp/temporary-artifact.txtecho "keep this" > /tmp/keep-this.txtoutputs:artifacts:- name: temporary-artifactpath: /tmp/temporary-artifact.txts3:key: temporary-artifact.txt- name: keep-thispath: /tmp/keep-this.txts3:key: keep-this.txtartifactGC:strategy: Never   # optional override for an Artifact

核心部分如下:

spec:entrypoint: main# 为 Workflow 中的所有 artifact 统一配置artifactGC:strategy: OnWorkflowDeletion  # default Strategy set here applies to all Artifacts by default
# 单独指定 artifact 的回收策略outputs:artifacts:- name: temporary-artifactartifactGC:strategy: Never   # optional override for an Artifact

注意事项:为了避免相同工作流并发运行时,artifact 被误删除的问题,可以为不同工作流配置不同的 artifact repository。

forceFinalizerRemoval

argo-workflow 会启动一个 <wfName>-artgc-* 格式命名的 Pod 来执行垃圾回收工作,如果执行失败,整个 Workflow 也会被标记为失败。

同时由于finalizers 没有被删除掉

apiVersion: argoproj.io/v1alpha1
kind: Workflowfinalizers:- workflows.argoproj.io/artifact-gc

会导致这个 Workflow 无法删除,可以执行以下命令移除

kubectl patch workflow my-wf \--type json \--patch='[ { "op": "remove", "path": "/metadata/finalizers" } ]'

为了优化体验,argo-workflow 3.5 版本新增了 forceFinalizerRemoval 参数

spec:artifactGC:strategy: OnWorkflowDeletion forceFinalizerRemoval: true

只要forceFinalizerRemoval 设置为 true,即时 GC 失败也会移除 finalizers。

常用 Artifacts 扩展

除了 S3 Artifacts 之外,为了便于使用, argo-workflow 还内置了 git、http 方式来获取 artifact。

可以直接从指定 git 仓库 clone 代码,或者从指定 url 下载文件,就像这样:

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:generateName: hardwired-artifact-
spec:entrypoint: hardwired-artifacttemplates:- name: hardwired-artifactinputs:artifacts:# Check out the main branch of the argo repo and place it at /src# revision can be anything that git checkout accepts: branch, commit, tag, etc.- name: argo-sourcepath: /srcgit:repo: https://github.com/argoproj/argo-workflows.gitrevision: "main"# Download kubectl 1.8.0 and place it at /bin/kubectl- name: kubectlpath: /bin/kubectlmode: 0755http:url: https://storage.googleapis.com/kubernetes-release/release/v1.8.0/bin/linux/amd64/kubectl# Copy an s3 compatible artifact repository bucket (such as AWS, GCS and MinIO) and place it at /s3- name: objectspath: /s3s3:endpoint: storage.googleapis.combucket: my-bucket-namekey: path/in/bucketaccessKeySecret:name: my-s3-credentialskey: accessKeysecretKeySecret:name: my-s3-credentialskey: secretKeycontainer:image: debiancommand: [sh, -c]args: ["ls -l /src /bin/kubectl /s3"]

3. Demo

测试点:

  • 1)创建到 Workflow 对应 Namespace 是否能正常使用
  • 2)将S3 配置创建到 Argo 部署的 Namespace 是不是可以不需要进行同步了。

Configmap:

  • Name:argo-workflow-argo-workflows-workflow-controller-configmap
  • Namespace:argo-dev
  • Key:artifactRepository

Minio 准备

部署一个 local-path-storage csi,如果有别的 csi 也可以跳过这一步

kubectl apply -f https://raw.githubusercontent.com/rancher/local-path-provisioner/v0.0.24/deploy/local-path-storage.yaml

然后部署 minio

helm install minio oci://registry-1.docker.io/bitnamicharts/minio
    my-release-minio.default.svc.cluster.localexport ROOT_USER=$(kubectl get secret --namespace default my-release-minio -o jsonpath="{.data.root-user}" | base64 -d)export ROOT_PASSWORD=$(kubectl get secret --namespace default my-release-minio -o jsonpath="{.data.root-password}" | base64 -d)

配置 artifact-repository

cm.yaml 完整内容如下:

apiVersion: v1
kind: ConfigMap
metadata:name: artifact-repositoriesannotations:workflows.argoproj.io/default-artifact-repository: my-artifact-repository
data:my-artifact-repository: |s3:bucket: argoendpoint: minio.default.svc.cluster.local:9000insecure: trueaccessKeySecret:name: my-s3-secretkey: accessKeysecretKeySecret:name: my-s3-secretkey: secretKey

secret.yaml 完整内容如下:

apiVersion: v1
stringData:accessKey: adminsecretKey: minioadmin
kind: Secret
metadata:name: my-s3-secret
type: Opaque

创建 artifact repository 配置

kubectl apply -f cm.yaml
kubectl apply -f secret.yaml

Workflow 中使用artifact

两个步骤:

  • generate:生成一个文件,并通过 outputs.artifact 写入 S3
  • consume:使用 inputs.artifact 从 S3 读取文件并打印内容

workflow.yaml 完整内容如下:

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:generateName: key-only-artifacts-
spec:entrypoint: maintemplates:- name: maindag:tasks:- name: generatetemplate: generate- name: consumetemplate: consumedependencies:- generate- name: generatecontainer:image: argoproj/argosay:v2args: [ echo, hello, /mnt/file ]outputs:artifacts:- name: filepath: /mnt/files3:key: my-file- name: consumecontainer:image: argoproj/argosay:v2args: [cat, /tmp/file]inputs:artifacts:- name: filepath: /tmp/files3:key: my-file

创建 Workflow

kubectl create -f workflow.yaml 

等待运行完成

[root@lixd-argo artiface]# kubectl get wf
NAME                                  STATUS      AGE     MESSAGE
key-only-artifacts-9r84h              Succeeded   2m30s

S3 查看文件

到 S3 中查看文件是否存在

可以看到,在 argo bucket 下有一个名为 my-file的文件存在,而且 context-type 是 application/gzip,这也验证了 argo 会对 artifact 执行 tar+gzip。

argo-artifact-s3

4. 小结


**【ArgoWorkflow 系列】**持续更新中,搜索公众号【探索云原生】订阅,文章。


本文主要分析了 argo 中的 artifact 使用,包括如何配置 artifact-repository:

包括三种方式:

  • 1)全局配置
  • 2)命名空间默认配置
  • 3)Workflow 中指定配置

以及如何在 Workflow 中使用 artifact 并通过一个 Demo 进行演示。

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

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

相关文章

用AppleScript做macOS UI自动化

用AppleScript做macOS UI自动化 一、定位到System Setting → General → Login Items& Extensions 页面1. 获取页面锚点&#xff0c;以便直接滑动到锚点区域2. 滑动到Extensions 区域 二、根据名称找到元素&#xff0c;再点击元素的按钮三、获取元素位置并点击 一、定位到…

Datawhale X 李宏毅苹果书 AI夏令营 Task2笔记

Datawhale X 李宏毅苹果书 向李宏毅学深度学习&#xff08;进阶&#xff09; 是 Datawhale 2024 年 AI 夏令营第五期的学习活动&#xff08;“深度学习 进阶”方向&#xff09; 往期task1链接&#xff1a;深度学习进阶-Task1 我做的task1的笔记博客&#xff1a;传送门 Datawhal…

【C语言】宏定义详解

目录 C语言宏定义详解1. 宏定义关键词总览2. #define3. #undef4. #ifdef5. #ifndef6. #if7. #else8. #elif9. #endif10. #include11. #error12. #pragma12.1 #pragma once12.2 #pragma pack12.3 #pragma warning12.4 #pragma GCC 13. #line14. 字符串化和标识符连接14.1 字符串…

C# 对桌面快捷方式的操作设置开机启动项

首先在项目中引入Windows Script Host Object Model&#xff0c;引入方式如下图。 对于桌面快捷方式的修改无非就是将现有的快捷方式修改和添加新的快捷方式。 1、遍历桌面快捷方式&#xff0c;代码如下。 string desktopPath Environment.GetFolderPath(Environment.Special…

LLM 应用开发入门 - 实现 langchain.js ChatModel 接入火山引擎大模型和实现一个 CLI 聊天机器人(上)

前言 Langchain 是一个大语言模型(LLM)应用开发的框架,提供了 LLM 开发中各个阶段很多非常强大的辅助工具支持。对于进行 LLM 开发是必不可少的工具库。 本文将通过一个实际的开发例子来入门 LLM 开发基础工具链,并实现 langchain.js ChatModel 接入火山引擎大模型和基于…

【亲测有效】linux抓包http协议分析,分析header和body

linux抓包http协议分析&#xff0c;分析header和body 安装&#xff1a; 执行抓包命令&#xff0c;这里ip要换成你想抓包的目标ip&#xff1a; ngrep -q -W byline -d any "^Host:|^GET|^POST|^HTTP/" tcp and host 183.2.172.42 and port 80 触发抓包&#xff0c;…

FPGA实现多功能SDI视频采集卡,基于GTX+RIFFA架构,提供2套工程源码和技术支持

目录 1、前言工程概述免责声明 2、相关方案推荐我已有的PCIE方案本博已有的 SDI 编解码方案 3、详细设计方案设计框图SDI 输入设备Gv8601a 均衡器GTX 解串与串化SMPTE SD/HD/3G SDI IP核BT1120转RGBFDMA图像缓存RIFFA用户数据控制RIFFA架构详解Xilinx 7 Series Integrated Bloc…

94522

springboot 广州应用科技学院的教室管理系统 摘 要 科技进步的飞速发展引起人们日常生活的巨大变化&#xff0c;电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用。信息时代的到来已成为不可阻挡的时尚潮流&#xff0c;人类发展的历史正进入一个新时…

详细分析Ubuntu中的ufw基本知识

目录 前言1. 基本知识2. 基本使用 前言 由于命令行比较简单&#xff0c;此处主要以表格的形式呈现&#xff0c;还有实战中遇到的一个注意点 1. 基本知识 Ubuntu 中一种用户友好的防火墙配置工具&#xff0c;简化 iptables 的使用&#xff0c;适合那些不熟悉复杂防火墙配置的…

页面内容---复制粘贴【收藏版】【H5 web端亲测有效】

js中的复制粘贴 . 页面内容—复制粘贴【收藏版】【H5 web端亲测有效】 navigator.clipboard.writeText(copyText) 是 Web API 中的一个方法&#xff0c;用于将指定的文本内容复制到用户的剪贴板。这个方法属于 Clipboard API&#xff0c;它使得网页能够读取和写入剪贴板的内容…

开放式耳机哪种好用又实用?优质开放式耳机种草测评

在开放式耳机领域&#xff0c;目前有几款表现尤为突出的产品。作为一名专业的音乐制作人和评测专家&#xff0c;我深知一款出色的耳机对于音乐创作和鉴赏的重要性。 最近&#xff0c;我亲自评测了市面上一些颇受欢迎的开放式耳机&#xff0c;发现它们不仅在音质上有着令人满意…

winXP下构建python开发环境

近期车间有个动平衡检测仪数采的需求&#xff0c;工控机是xp系统&#xff0c;原理也很简单&#xff0c;监控文件变化&#xff0c;发现有新的检测数据就调用远程接口传输到服务器上去。 通常python监控文件变化会用watchdog这个库&#xff0c; 可是xp太老了&#xff0c;测试了一…

Jenkins服务安装配置

目录 Jenkins 配置环境 配置 中文插件 配置 Maven 插件 配置 JDK 配置 Git 配置 SSH 远程服务器 Jenkins 配置项目 构建 maven 项目 构建 pipeline 流水线项目 什么是 Jenkins Jenkins 是一个开源的自动化服务器&#xff0c;主要用于持续集成&#xff08;CI&#xff…

代码随想录刷题day15丨110.平衡二叉树,257. 二叉树的所有路径, 404.左叶子之和 ,222.完全二叉树的节点个数

代码随想录刷题day15丨110.平衡二叉树&#xff0c;257. 二叉树的所有路径&#xff0c; 404.左叶子之和 &#xff0c;222.完全二叉树的节点个数 1.题目 1.1平衡二叉树&#xff08;优先掌握递归&#xff09; 题目链接&#xff1a;110. 平衡二叉树 - 力扣&#xff08;LeetCode&a…

以小搏大:Salesforce 十亿参数模型表现超过ChatGPT

小模型的强势崛&#xff1a;轻量化AI如何以高效表现撼动大型模型的统治&#xff01; ©作者|DWT 来源|神州问学 导读 近年来&#xff0c;人工智能领域的迅猛发展使得大型语言模型&#xff08;LLM&#xff09;成为了焦点。这些模型&#xff0c;如OpenAI的GPT-4和Google的…

讲透一个强大的算法模型,Transformer

Transformer 模型是一种基于注意力机制的深度学习模型&#xff0c;广泛应用于自然语言处理&#xff08;NLP&#xff09;任务&#xff0c;如机器翻译、文本生成和语义理解。 它最初由 Vaswani 等人在2017年的论文《Attention is All You Need》中提出。它突破了传统序列模型&am…

CSRF 概念及防护机制

概述 CSRF&#xff08;Cross-Site Request Forgery&#xff09;&#xff0c;即跨站请求伪造&#xff0c;是一种网络攻击方式。在这种攻击中&#xff0c;恶意用户诱导受害者在不知情的情况下执行某些操作&#xff0c;通常是利用受害者已经登录的身份&#xff0c;向受害者信任的…

微纳芯:如何利用CRM实现渠道分销管理的数字化转型

MINCHIP由联想控股投资,是一家专注于快速体外诊断产品的研发、生产、销售、服务的高科技企业,拥有多项自主知识产权及技术专利。致力于用专业的微流控临床检验产品,为全球大众提供触手可及、负担得起的健康服务。其系列全自动生化分析仪持续为医师、兽医师的机构运营提供解决方…

C++对C的扩充(8.28)

1.使用C手动封装一个顺序表&#xff0c;包括成员数组1个&#xff0c;成员变量n个 代码&#xff1a; #include <iostream>using namespace std;//类型重命名 using datatype int; #define MAX 30struct seqList { private: //私有权限datatype *data; //相当于 …

Java中的java.lang.ArithmeticException: null问题详解与解决方案

个人名片 &#x1f393;作者简介&#xff1a;java领域优质创作者 &#x1f310;个人主页&#xff1a;码农阿豪 &#x1f4de;工作室&#xff1a;新空间代码工作室&#xff08;提供各种软件服务&#xff09; &#x1f48c;个人邮箱&#xff1a;[2435024119qq.com] &#x1f4f1…