devops(后端)

1.前言

该devpos架构为gitlab+jenkins+harbor+k8s,项目是java项目,流程为从gitlab拉取项目代码到jenkins,jenkins通过maven将项目代码打成jar包,通过dockerfile构建jdk环境的镜像并把jar包放到镜像中启动,构建好的镜像通过docker上传到harbor镜像仓库中,最后k8s通过更新镜像的方式去发布新的服务,此套流程通过jenkins的pipeline实现,其中还涉及多分支、回滚操作

2.部署环境

gitlab部署参考:gitlab部署_Apex Predator的博客-CSDN博客

jenkins部署参考:jenkins部署_Apex Predator的博客-CSDN博客

harbor部署参考:k8s harbor镜像仓库搭建_k8s镜像仓库_Apex Predator的博客-CSDN博客

k8s部署参考:kubeadm部署k8s 1.26.0版本高可用集群_Apex Predator的博客-CSDN博客

3.配置环境

jenkins主机配置

在部署jnekins环境的时候已经安装了jdk、maven、git环境,现在还需要在安装docker、kubectl,docker用于构建镜像和推送镜像到harbor仓库,kubectl用于操作k8s发布新版本

docker部署参考:部署docker-ce_Apex Predator的博客-CSDN博客

部署完成后需要配置一下docker的daemon.json文件(因为是私有仓库,docker是不允许拉取不安全仓库的镜像

vi /etc/docker/daemon.json

{"registry-mirrors": ["https://sudzwtcw.mirror.aliyuncs.com"],"insecure-registries": ["harbor.apex.com"]      #配置该项,使得docker允许访问不安全的镜像仓库
}

重启docker服务

systemctl restart docker 

部署kubectl

配置阿里云的k8s yum源

cat > /etc/yum.repos.d/kubernetes.repo << EOF

[kubernetes]

name=Kubernetes

baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64

enabled=1

gpgcheck=0

repo_gpgcheck=0

gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg

EOF

安装kubectl

yum -y install kubectl-1.26.0

在jenkins上引用安装的环境

 

 

在jenkins中安装以下插件

Git
Git plugin
Git Parameter
GitLab
Credentials
Credentials Binding
CloudBees Docker Build and Publish plugin
Build With Parameters
Dynamic Extended Choice Parameter Plug-In
Dynamic Parameter Plug-in
Extended Choice Parameter
List Git Branches Parameter
Pipeline
Pipeline: Declarative
kubernetes
Kubernetes plugin
Kubernetes CLI Plugin
Kubernetes Credentials Plugin

 

在jenkins上配置ssh密钥(一路回车即可)

ssh-keygen

查看公钥并拷贝到gitlba上

cat ~/.ssh/id_rsa.pub

 将以上公钥填入以下gitlab配置中即可 

配置jenkins Credentials

创建gitlab凭据

查看jenkins的私钥

cat ~/.ssh/id_rsa      #复制输出的所有内容

 

 

 

 

 

创建harbor凭据

 

创建k8s凭据

先在k8s下载密钥文件(就是集群的配置文件,里面包含有密钥和请求集群的接口等配置)

ls .kube/config

 

sz .kube/config 

harbor配置

配置harbor仓库项目信息

分别创建两个项目,一个存放基础镜像叫base_image,一个存放后端服务镜像叫jdk

 

gitlab配置

创建项目

 创建完成后上传项目代码

k8s集群配置 

 在k8s的node节点上配置docker的daemon.json文件

vi /etc/docker/daemon.json

{"registry-mirrors": ["https://sudzwtcw.mirror.aliyuncs.com"],"insecure-registries": ["harbor.apex.com"],  #配置该项,使得docker允许访问不安全的镜像仓库"exec-opts": ["native.cgroupdriver=systemd"]
}

重启docker服务

systemctl restart docker

4.构建发布

使用jenkins的pipeline和webhook实现ci/cd自动化发布

jenkins配置

新建流水线项目

 配置Choice Parameter,直接在Jenkins file中写parameter不手动配置parameter的话,第一次执行会失败,执行完后会自动生成parameter,所以还是手动也配置一下

 

 配置webhook tigger用于触发自动构建

 

 

 

 配置流水线脚本

选择pipeline script模式

填入以下脚本

pipeline {        #配置pipelineagent any       #客户端配置,jenkins可以使用k8s作为agent环境去发布,这里使用any为任意环境environment {             #配置环境变量参数,用来给下面调用registry = "harbor.apex.com"     #配置harbor仓库地址harbor_auth = "a1e2c627-dc62-4599-a035-8e98d74665ab"   #配置harbor credentials凭据idproject = "jdk"      #配置harbor仓库镜像项目app_name = "k8s-cs"     #配置k8s的pod名称namespace = "k8s-cs"    #配置k8s的命名空间k8s_auth = "k8s-kubeconfig"   #配置k8s credentials凭据id     }parameters {     #配置parameters功能choice(choices: ['','master', 'apex'], description: '''choice branch''', name: 'branch')       #配置分支选择的choice,用于回滚和手动发布的分支选择,此处默认时空值,避免下面阶段使用branch变量判断出现问题choice(choices: ['deploy', 'rollback'], description: '''deploy ---部署  rollback  ---回滚''', name: 'status')    #配置发布回滚选择的choice,用于选择发布还是回滚,此处默认时deploy发布}stages {         #配置构建的每个阶段stage('Checkout code') {        #配置从gitlab拉取代码parallel {     #配置以下两个阶段的操作并行执行stage('webhook tigger') {    #配置自动触发执行的操作when {    #使用when判断env.gitlabBranch的值是否为空,使用webhook自动构建,是通过env.gitlabBranch变量来赋予分支值,判断该值是否为空,就能判断是通过webhook构建还是手动构建的expression { params.status == 'deploy' && env.gitlabBranch != null }}    #params的值用来判断,是否执行的是发布操作,如果是发布操作才执行该操作,使用&&是需要两个条件都为true才执行steps {     #以上判断通过后执行从gitlab对应的分支拉取代码的操作checkout([$class: 'GitSCM', branches: [[name: '${env.gitlabBranch}']], extensions: [], userRemoteConfigs: [[credentialsId: 'gitlab_auth', url: 'git@10.1.60.114:gitlab-instance-c484dcfc/java-project.git']]])  #可以看到branch使用的是env.gitlabBranch这个变量,因为webhook自动构建是将分支的值赋予到这个变量中,credentialsId就配置gitlab的credentials凭据idsh "git branch"     #这里是测试是否能获取到分支的值echo "Current branch: ${env.gitlabBranch}"   #这里是输出分支的值script {   #提取gitlab的项目id,用来制作镜像tagcommit_id = sh(returnStdout: true, script: "git log -n 1 --pretty=format:'%h'").trim()tag = BUILD_TAG + '-' + commit_id  #使用jenkins的构建标签和gitlab的项目id作为镜像标签的tag}}}stage('jenkins scm') {   #此处就是判断是否用的手动构建when {   #使用when判断env.gitlabBranch是否等于空值,是空值就证明是通过手动构建的expression { params.status == 'deploy' && env.gitlabBranch == null }}  #params的值用来判断,是否执行的是发布操作steps {    #执行拉取gitlab代码操作checkout([$class: 'GitSCM', branches: [[name: '${branch}']], extensions: [], userRemoteConfigs: [[credentialsId: 'gitlab_auth', url: 'git@10.1.60.114:gitlab-instance-c484dcfc/java-project.git']]])   #这里和上面自动构建的命令没有什么区别就除了branches使用branch作为变量,因为我们上面配置parameters,手动构建需要选择名为branch的choice去选择分支,所以我们就通过该变量获取到选择的分支名称sh "git branch"echo "Current branch: ${branch}"script {commit_id = sh(returnStdout: true, script: "git log -n 1 --pretty=format:'%h'").trim()tag = BUILD_TAG + '-' + commit_id}}}}  #到这里parallel并行操作就结束了}    #到这里上面的拉取代码操作就结束了stage('Build jar') {   #接下来就是编译代码打包的操作步骤when {   #使用when判断是否是发布操作,回滚是不用执行这个阶段的,上面的拉代码操作也是expression { params.status == 'deploy' }}steps {  #when判断通过后执行以下命令打包,打包命令可能会不一样,可以咨询一下开发sh "mvn clean install -DskipTests"  #编译打包命令sh "ls target/"      #查看是否有打出来jar包}}stage('docker image build and push') {   #构建镜像和推送镜像到harbor仓库步骤when {expression { params.status == 'deploy' }}steps {withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {  #使用harbor的credentials凭据,因为推镜像和拉基础镜像都是需要访问harbor仓库的sh "docker build -t ${registry}/${project}/${app_name}:${tag} ."sh "docker push ${registry}/${project}/${app_name}:${tag}"} #可能生产、测试环境打包的镜像名称要求不一样,这时就需要跟上面一样使用when去判断是哪个环境构建镜像}}stage('k8s update iamge version') {  #发布版本操作parallel {   #以上有讲解此参数stage ('to apex') {when {   #判断分支,决定发布到哪个环境中expression { params.status == 'deploy' && ( env.gitlabBranch == 'apex' || params.branch == 'apex' ) }}   #后面用了一个|| 或的判断,即两个获取分支的变量只要有一个成立即可,主要是自动构建和手动构建的分支变量不一样,所以必须得使用两个分支变量判断steps {  #配置k8s集群得credentials凭据,通过凭据调用k8s集群的apiserverwithCredentials([file(credentialsId: "${k8s_auth}", variable: 'KUBECONFIG')]) {sh "kubectl --kubeconfig ${KUBECONFIG} set image deployment -l app=${app_name} ${app_name}=${registry}/${project}/${app_name}:${tag} -n ${namespace} --record"}   #使用kubectl命令指定k8s集群的配置文件执行更新镜像命令的操作,更新镜像操作即发布版本,并记录该操作用于回滚}}stage('to master') {when {  #判断分支,决定发布到哪个环境中expression { params.status == 'deploy' && ( env.gitlabBranch == 'master' || params.branch == 'master' ) }}steps {withCredentials([file(credentialsId: "${k8s_auth}", variable: 'KUBECONFIG')]) {sh "kubectl --kubeconfig ${KUBECONFIG} get pod -n ${namespace}"sh "echo ${params.branch}"sh "echo ${env.gitlabBranch}"}  #以上命令是测试用的,要是发版命令改为以上的set命令即可}}}}stage('rollback version') {  #回滚操作,当发布的版本有问题时,会需要使用到回滚操作parallel {stage('to  apex') {when {  #判断params.status变量是否为rollback,且判断分支,因为回滚操作都是手动操作的所以使用branch变量判断分支即可expression { params.status == 'rollback' && params.branch == 'apex' }}steps {   #此处也是配置k8s集群的credentials凭据withCredentials([file(credentialsId: "${k8s_auth}", variable: 'KUBECONFIG')]) {sh "kubectl --kubeconfig ${KUBECONFIG} rollout undo deployment ${app_name} -n ${namespace}"}  #使用rollout命令并指定deployment回滚版本}    }stage('to  master') {when {expression { params.status == 'rollback' && params.branch == 'master' }}steps {withCredentials([file(credentialsId: "${k8s_auth}", variable: 'KUBECONFIG')]) {sh "kubectl --kubeconfig ${KUBECONFIG} get deployment ${app_name} -n ${namespace}"}  #此处也是测试命令,回滚命令参照上面写即可}    }}}}
}

制作基础镜像(打包的时候直接使用基础镜像会更快)

vim dockerfile

FROM alpine:latest      #拉取系统镜像
ENV TZ="Asia/Shanghai"  #这个环境变量用于下面配置时区
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \  #配置源
&& apk add --upgrade --no-cache openjdk8 tzdata ttf-dejavu fontconfig \    #安装jdk环境、字体等工具
&& cp /usr/share/zoneinfo/${TZ} /etc/localtime \    #配置时区
&& echo ${TZ} > /etc/timezone

构建镜像

docker build -t harbor.apex.com/base_image/jdk8_image:latest .

上传镜像

docker push  harbor.apex.com/base_image/jdk8_image:latest

gitlab配置

在项目代码仓库中创建dockerfile用于构建发布镜像

 

dockerfile内容如下

FROM harbor.apex.com/base_image/jdk8_image:latest   #使用harbor仓库中的基础镜像
ENV JVM_OPTS="-Xms512m -Xms512m"   #配置关于java的环境变量
ENV HEAP_DUMP_OPTS="-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/java_jar/log"
RUN mkdir -p /opt/java_jar/log   #创建存放jar包目录还有日志目录
WORKDIR /opt/java_jar/    #设置存放jar包目录为工作目录,即相当于cd到这个目录上
COPY ./target/*.jar ./    #拷贝jar包到镜像中,target目录是在jenkins上打包后,jar包的生成目录
EXPOSE 8761        #配置需要暴露的端口
ENTRYPOINT java ${JVM_POST} ${HEAP_DUMP_OPTS} -jar *.jar  #配置启动jar包服务

配置webhook用于触发jenkins自动化构建

 

 

 

k8s集群 配置(在master节点执行

创建namespace

kubectl create namespace k8s-cs

创建secret用于拉取harbor仓库的镜像使用

kubectl create secret docker-registry harbor-secret --namespace=k8s-cs --docker-server=https://harbor.apex.com --docker-username=admin --docker-password=Harbor12345

查看secret

kubectl get secret -n k8s-cs

 

创建yaml

 vim k8s-cs.yaml

apiVersion: apps/v1
kind: Deployment
metadata: labels:app: k8s-csname: k8s-csnamespace: k8s-cs
spec:replicas: 5progressDeadlineSeconds: 600minReadySeconds: 10strategy:         #配置滚动更新策略rollingUpdate:maxSurge: 1maxUnavailable: 0type: RollingUpdateselector:matchLabels:app: k8s-cstemplate:metadata:labels:app: k8s-csspec:containers:- name: k8s-csimage: harbor.apex.com/jdk/k8s-cs   #填写harbor仓库的镜像地址imagePullPolicy: IfNotPresent       ports:- containerPort: 8761readinessProbe:      #配置就绪探针httpGet:path: /port: 8761scheme: HTTPinitialDelaySeconds: 30periodSeconds: 10timeoutSeconds: 2successThreshold: 1failureThreshold: 2livenessProbe:     #配置存活探针tcpSocket:port: 8761initialDelaySeconds: 30periodSeconds: 10successThreshold: 1timeoutSeconds: 2failureThreshold: 2 imagePullSecrets:         #配置拉取镜像使用的secret- name: harbor-secretrestartPolicy: Always
---
apiVersion: v1
kind: Service          #配置service映射端口
metadata:name: k8s-csnamespace: k8s-cs
spec:selector:app: k8s-cstype: NodePort   clusterIP:ports:- port: 8761targetPort: 8761nodePort: 30002protocol: TCP

执行yaml创建pod

kubectl apply -f k8s-cs.yaml

5.测试发布、回滚

手动构建

 

 

回滚 

 

自动化构建

更改一下分支合并到master看看会不会触发自动化构建

更改的过程我就省略了,更改好之后创建合并请求

 批准且合并后触发Jenkins构建

 

 

 这个也是多分支的发布,合并其它分支也是可以触发,我就不演示了

6.补充

pipeline有两种模式,还有一种是pipeline script from scm,就是在流水线配置界面就编辑好从gitlab仓库拉代码的信息,并且把jenkinsfile放到gitlab的仓库中,跟着代码一起拉下来,接下来也说一下这种方式的使用

创建pipeline项目,这里就不贴图了

配置git parameter,用来选择发布时的分支

 

 

 

在gitlab的项目上创建jenkinsfile文件

 

 

jenkinsfile脚本如下

pipeline {agent anyenvironment {registry = "harbor.apex.com"harbor_auth = "a1e2c627-dc62-4599-a035-8e98d74665ab"project = "jdk"app_name = "k8s-cs"namespace = "k8s-cs"image_url = "${registry}/${project}/${app_name}:${tag}"k8s_auth = "k8s-kubeconfig"k8s_name = "kubernetes"}   #这里和之前的pipeline不同,因为配置了scm后在jenkinsfile中就不需要再配置拉取代码的步骤了,其它的配置都是一样的,不过我这是一个简化版的适合单分支stages {stage('Build jar') {steps {sh "mvn clean install -DskipTests"sh "ls target/"}}stage('docker image build and push') {steps {withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {sh "docker build -t ${image_url} ."sh "docker push ${image_url}"}}}stage('push yaml to k8s') {steps {withCredentials([file(credentialsId: "${k8s_auth}", variable: 'KUBECONFIG')]) {sh "kubectl --kubeconfig ${KUBECONFIG} set image deployment -l app=${app_name} ${app_name}=${image_url} -n ${namespace} --record"}}}}
}

去执行构建就可以了,这里是jenkins项目通过scm的gitlab拉取项目代码,拉取了项目后再去执行流水线的jenkinsfile脚本,所以jenkinsfile里是不需要配置拉代码这个动作的

以下再 讲解一下通过jenkins agent来执行流水线,这里讲诉使用k8s集群的pod作为jenkins agent去发布,大概流程就是使用k8s插件连接k8s集群,调用k8s的api server去创建jenkins agent,流水线的所有步骤都在jenkins agent上执行,期间还需要配置所有需要用的环境的pod,这里就不详细介绍,就说一下踩到的坑

jenkins agent使用的jnlp镜像的jdk环境需要和jenkins的jdk环境一致,不然是没办法连接的

使用jenkins agent除了要打开jenkins 50000端口与Jenkins agent通信外,还需要配置Git Host Key Verification Configuration项,不然的话在从gitlab拉代码的适合会一直报错

 

里面填写的密钥在 known_hosts文件中,配置的是gitlab主机的密钥 ,一定要配置此项不然pod拉不到gitlab的项目代码

cat /root/.ssh/known_hosts 

 还有就是使用docker镜像,镜像里的docker是没办法配置daemon.json的,所以访问不到harbor的私有仓库,除非harbor使用的是公有证书和公有域名

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

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

相关文章

【Quartus FPGA】EMIF DDR3 读写带宽测试

在通信原理中&#xff0c;通信系统的有效性用带宽来衡量&#xff0c;带宽定义为每秒传输的比特数&#xff0c;单位 b/s&#xff0c;或 bps。在 DDR3 接口的产品设计中&#xff0c;DDR3 读/写带宽是设计者必须考虑的指标。本文主要介绍了 Quartus FPGA 平台 EMIF 参数配置&#…

DB-GPT:强强联合Langchain-Vicuna的应用实战开源项目,彻底改变与数据库的交互方式

今天看到 蚂蚁科技 Magic 开源的DB-GPT项目&#xff0c;觉得创意很好&#xff0c;集成了当前LLM的主流技术&#xff0c;主要如下 Langchain&#xff1a; 构建在LLM之上的应用开发框架HuggingFace: 模型标准&#xff0c;提供大模型管理功能Vicuna: 一个令GPT-4惊艳的开源聊天机…

[NLP]使用Alpaca-Lora基于llama模型进行微调教程

Stanford Alpaca 是在 LLaMA 整个模型上微调&#xff0c;即对预训练模型中的所有参数都进行微调&#xff08;full fine-tuning&#xff09;。但该方法对于硬件成本要求仍然偏高且训练低效。 [NLP]理解大型语言模型高效微调(PEFT) 因此&#xff0c; Alpaca-Lora 则是利用 Lora…

#systemverilog# 说说Systemverilog中《automatic》那些事儿

前面我们学习了有关systemverilog语言中有关《static》的一些知识,同static 关系比较好的哥们,那就是 《automatic》。今天,我们了解认识一下。 在systemveriog中,存在三种并发执行语句,分别是fork..join,fork...join_any和fork..join_none,其中只有fork...join_none不…

【Spring AOP学习】AOP的组成 SpringAOP的实现和实现原理

目录 一、认识SpringAOP 1、AOP是什么&#xff1f; 2、AOP的功能 3、AOP的组成&#xff08;重要&#xff09; 二、SpringAOP的实现 &#x1f337;1、添加Spring AOP框架支持 &#x1f337;2、定义切面和切点 &#x1f337; 3、定义通知 3.1 完成代码实现 3.2 具体通知…

抽象工厂模式——产品族的创建

1、简介 1.1、简介 抽象工厂模式为创建一组对象提供了一种解决方案。与工厂方法模式相比&#xff0c;抽象工厂模式中的具体工厂不只是创建一种产品&#xff0c;它负责创建一族产品 1.2、定义 抽象工厂模式&#xff08;Abstract Factory Pattern&#xff09;&#xff1a;提供…

Acwing.898 数字三角形(动态规划)

题目 给定一个如下图所示的数字三角形&#xff0c;从顶部出发&#xff0c;在每一结点可以选择移动至其左下方的结点或移动至其右下方的结点&#xff0c;一直走到底层&#xff0c;要求找出─条路径&#xff0c;使路径上的数字的和最大。 输入格式 第一行包含整数n&#xff0…

螺旋矩阵 II

给你一个正整数 n &#xff0c;生成一个包含 1 到 n2 所有元素&#xff0c;且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;[[1,2,3],[8,9,4],[7,6,5]] 示例 2&#xff1a; 输入&#xff1a;n 1 输出&a…

零信任网络架构与实现技术的研究与思考

目前&#xff0c;国外已有较多有关零信任网络的研究与实践&#xff0c;包括谷歌的 BeyondCorp、BeyondProd&#xff0c;软件定义边界&#xff08;Software Defined Perimeter&#xff0c;SDP&#xff09; 及盖特提出的“持续自适应风险与信任评估”等。国内也有不少安全厂商积极…

vue中预览静态pdf文件

方法 // pdf预览 viewFileCompare() { const pdfUrl "/static/wjbd.pdf"; window.open(pdfUrl); }, // 下载 downloadFile(){ var a document.createElement("a"); a.href "/static/wjbd.pdf"; a.…

关于Anaconda环境配置的一些问题

文章目录 一、关于package文件安装位置二、关于尝试下载Python包时出现的CondaSSLError三、配置环境的整个流程 一、关于package文件安装位置 package 文件安装在envs目录底下的Lib中&#xff0c;可以参考一下。 在对应的Python脚本文件中&#xff0c;选择Parameters&#xff0…

【Spring】Spring 总览

一、简单介绍一下 Spring Spring是一个全面的、企业应用开发的一站式解决方案&#xff0c;贯穿表现层、业务层、持久层&#xff0c;可以轻松和其他框架整合&#xff0c;具有轻量级、控制反转、面向切面、容器等特征。 轻量级 &#xff1a; 空间开销和时间开销都很轻量 控制反…

蓝桥杯单片机第十二届国赛 真题+代码

iic.c /* # I2C代码片段说明1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。2. 参赛选手可以自行编写相关代码或以该代码为基础&#xff0c;根据所选单片机类型、运行速度和试题中对单片机时钟频率的要求&#xff0c;进行代码调试和修改。 */ #include <STC1…

java springBoot 整合日志

1.在Spring Boot项目的resources目录下创建一个新的logback.xml文件。 2.logback.xml中&#xff0c;配置 代码 <?xml version"1.0" encoding"UTF-8"?> <!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL…

了解Unity编辑器之组件篇Physics 2D(十二)

一、Area Effector 2D区域施加力&#xff09;&#xff1a;用于控制区域施加力的行为 Use Collider Mask&#xff08;使用碰撞器遮罩&#xff09;&#xff1a;启用后&#xff0c;区域施加力仅会作用于特定的碰撞器。可以使用Collider Mask属性选择要作用的碰撞器。 Collider Ma…

vmware中windows操作系统虚拟机安装

1.win10中安装 1.1 虚拟机向导 文件-新建虚拟机 典型-下一步 稍后安装操作系统-下一步 window10 64x -下一步 修改虚拟机名称及位置-下一步 默认60g,至少大于40g-将虚拟磁盘拆分成多个文件夹-下一步 点击完成 1.2 编辑虚拟机设置 移除打印机 设置虚拟机&#xff0c;加入iso映…

【隐式动态求解】使用非线性纽马克方法的隐式动态求解研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

小程序 获取用户头像、昵称、手机号的组件封装(最新版)

在父组件引入该组件 <!-- 授权信息 --><auth-mes showModal"{{showModal}}" idautnMes bind:onConfirm"onConfirm"></auth-mes> 子组件详细代码为: authMes.wxml <!-- components/authMes/authMes.wxml --> <van-popup show…

CompletableFuture生产中使用问题

CompletableFuture生产中使用问题 1 背景2 测试3 原因4. 总结 1 背景 接到一个任务,需要优化下单接口,查看完业务逻辑后发现有一些可以并行或异步查询的地方,于是采用CompletableFuture来做异步优化,提高接口响应速度,伪代码如下 //查询用户信息CompletableFuture<JSONObj…

安全测试国家标准解读——数据库管理和文件管理

下面的系列文章主要围绕《GB/T 38674—2020 信息安全技术 应用软件安全编程指南》进行讲解&#xff0c;该标准是2020年4月28日&#xff0c;由国家市场监督管理总局、国家标准化管理委员会发布&#xff0c;2020年11月01日开始实施。我们对该标准中一些常见的漏洞进行了梳理&…