K8s部署高可用Jenkins

小伙伴们大家好呀!断更了近一个月,XiXi去学习了一下K8sJenkins的相关技术。学习内容有些庞杂,近一个月的时间里我只学会了一些皮毛,更多的内容还需要后面不断学习,不断积累。最主要的是云主机真得很贵,为了写这篇文章,我花了近200块😭
491599167.jpg

回到正题,这里我分享的成果是:在K8s上部署一套Jenkins环境,可以基于Pod实现动态的Jenkins-Slave的扩展,下面记录着我的整个搭建过程。

环境介绍

  • K8s1.28.2集群
  • 一台可以连接外网的云主机:用于下载一些Docker镜像

准备NFS制备器

在创建Jenkins之前,我们需要先在K8s集群上创建一个NFS制备器。创建NFS制备器后,我们只需要声明PVC,NFS制备器便会自动地基于NFS文件系统创建相应的PV。

NFS文件系统搭建

我们需要先搭建起一个NFS文件系统,搭建流程相当简单

  1. 每台主机上执行安装
# 安装 nfs
yum install nfs-utils -y
# 启动 nfs
systemctl start nfs-server
# 查看 nfs 版本
cat /proc/fs/nfsd/versions
  1. 选择某一台主机创建共享目录

这里我选择了内网ip:172.24.12.240的一台云主机

# 创建共享目录
mkdir -p /data/nfs/jenkins
# 设置共享目录 export
vim /etc/exports
/data/nfs/jenkins *(rw,sync,no_subtree_check,no_root_squash)
# 重新加载
exportfs -f
systemctl reload nfs-server
# 查看
showmount -e 172.24.12.240
  1. 其他机器可以挂载共享目录
mkdir -p /data/nfs/jenkins
# 注意执行mount时的目录,不要是挂载目录
mount -t nfs 172.24.12.240:/data/nfs/jenkins /data/nfs/jenkins
  1. 最终效果

最终,可以实现,在任意一台主机的 /data/nfs/jenkins中操作,都会同步到其他主机上

image.png

NFS制备器

参考官方GitHub:https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner

官方为我们提供了3种NFS制备器的创建方式:

  • Helm
  • Kustomize
  • 手动方式

下面我采取手动的方式给大家做个演示

步骤一:克隆官方项目

# 不管用什么方式大家将项目克隆下来就好
git clone https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner.git

主要是需要使用项目中deploy文件夹中的yaml文件
image.png

步骤二:修改deploy目录中的yaml的内容
注:如果制备器想创建在default命名空间,配置文件中namespace的相关内容不用改

image.png

  • class.yaml:用于创建StorageClass
  • deployment.yaml:用于创建Deployment
  • rbac.yaml:创建ServiceAccount和绑定角色
  1. class.yaml文件
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-jenkins-client
provisioner: xixi.io/nfs-subdir-external-provisioner
  archiveOnDelete: "false"

name:nfs-jenkins-client(可以保持原样)
provisioner: xixi.io/nfs-subdir-external-provisioner(可以保持原样,在下面的deployment.yaml文件中用到)

  1. deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfs-jenkins-client-provisioner
  labels:
    app: nfs-jenkins-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: kube-system
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: nfs-jenkins-client-provisioner
  template:
    metadata:
      labels:
        app: nfs-jenkins-client-provisioner
    spec:
      serviceAccountName: nfs-client-provisioner
      containers:
        - name: nfs-jenkins-client-provisioner
          image: registry.k8s.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              # class.yaml 中的 provisioner保持一致
              value: xixi.io/nfs-subdir-external-provisioner
            - name: NFS_SERVER
              value: 172.24.12.240
            - name: NFS_PATH
              value: /data/nfs/jenkins
      volumes:
        - name: nfs-client-root
          nfs:
            server: 172.24.12.240
            path: /data/nfs/jenkins
  • nfs的地址目录路径必改,其他的可以保持原样
  1. rbac.yaml文件
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: kube-system
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: nfs-client-provisioner-runner
rules:
  - apiGroups: [""]
    resources: ["nodes"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["persistentvolumes"]
    verbs: ["get", "list", "watch", "create", "delete"]
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["get", "list", "watch", "update"]
  - apiGroups: ["storage.k8s.io"]
    resources: ["storageclasses"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["events"]
    verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: run-nfs-client-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    # replace with namespace where provisioner is deployed
    namespace: kube-system
roleRef:
  kind: ClusterRole
  name: nfs-client-provisioner-runner
  apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: kube-system
rules:
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: kube-system
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    # replace with namespace where provisioner is deployed
    namespace: kube-system
roleRef:
  kind: Role
  name: leader-locking-nfs-client-provisioner
  apiGroup: rbac.authorization.k8s.io

步骤三:执行创建

kubectl apply -f ./rbac.yaml
kubectl apply -f ./class.yaml
kubectl apply -f ./deployment.yaml

## 验证
kubectl get storageclass
kubectl get deploy -n kube-system
kubectl get sa -n kube-system | grep nfs

image.png
image.png
image.png

步骤四:测试

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: test-jenkins-claim
spec:
  storageClassName: nfs-jenkins-client
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Mi
kubectl apply -f test-jenkins-claim.yaml
kubectl get pv,pvc

image.png
image.png

Jenkins-Master部署

GitHub供参考的Yaml:https://github.com/scriptcamp/kubernetes-jenkins
GitHub供参考的搭建流程:https://devopscube.com/setup-jenkins-on-kubernetes-cluster/
官方搭建流程:https://www.jenkins.io/doc/book/installing/kubernetes/

K8s上搭建Jenkins,官方提供的yaml比较老,里面的Jenkins镜像很老,所以得改。

步骤一:克隆官方的yaml

git clone https://github.com/scriptcamp/kubernetes-jenkins

image.png

步骤二:创建命名空间

kubectl create namespace devops-tools

步骤三:执行serviceAccount.yaml

kubectl apply -f serviceAccount.yaml
kubectl get sa -n devops-tools

image.png

步骤四:创建pvc(官方的volume.yaml就不用了)

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: xixi-jenkins-pvc
  namespace: devops-tools
spec:
  storageClassName: nfs-jenkins-client
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
kubectl apply -f xixi-jenkins-pvc.yaml
kubectl get pv,pvc -n devops-tools

image.png
image.png

步骤五:修改deployment.yaml并执行

apiVersion: apps/v1
kind: Deployment
metadata:
  name: xixi-jenkins
  namespace: devops-tools
spec:
  replicas: 1
  selector:
    matchLabels:
      app: xixi-jenkins-server
  template:
    metadata:
      labels:
        app: xixi-jenkins-server
    spec:
      securityContext:
            fsGroup: 1000 
            runAsUser: 1000
      serviceAccountName: jenkins-admin
      containers:
        - name: xixi-jenkins
          image: jenkins/jenkins:2.452.2-jdk17
          imagePullPolicy: IfNotPresent
          resources:
            limits:
              memory: "2Gi"
              cpu: "1000m"
            requests:
              memory: "500Mi"
              cpu: "500m"
          ports:
            - name: httpport
              containerPort: 8080
            - name: jnlpport
              containerPort: 50000
          livenessProbe:
            httpGet:
              path: "/login"
              port: 8080
            initialDelaySeconds: 125
            periodSeconds: 10
            timeoutSeconds: 5
            failureThreshold: 5
          readinessProbe:
            httpGet:
              path: "/login"
              port: 8080
            initialDelaySeconds: 120
            periodSeconds: 10
            timeoutSeconds: 5
            failureThreshold: 3
          volumeMounts:
            - name: xixi-jenkins-data
              mountPath: /var/jenkins_home         
      volumes:
        - name: xixi-jenkins-data
          persistentVolumeClaim:
              claimName: xixi-jenkins-pvc

我这边把探针的时间放的久了一点,等待Jenkins启动,大家可以自己调整

kubectl apply -f deployment.yaml
kubectl get pods -n devops-tools -o wide

image.png

步骤六:暴露服务(这里直接用Service的NodePort方式)

apiVersion: v1
kind: Service
metadata:
  name: xixi-jenkins-service
  namespace: devops-tools
  annotations:
      prometheus.io/scrape: 'true'
      prometheus.io/path:   /
      prometheus.io/port:   '8080'
spec:
  selector: 
    app: xixi-jenkins-server
  type: NodePort  
  ports:
    - name: http
      port: 8080
      targetPort: 8080
      nodePort: 32001
    - name: channel
      port: 50000
      targetPort: 50000
kubectl apply -f service.yaml
kubectl get svc -n devops-tools

image.png

步骤六:获取秘钥,登录Jenkins

kubectl logs xixi-jenkins-c879b6b69-6s5pq -n devops-tools

image.png
访问:ip:32001(32001就是步骤六中service.yaml文件中指定暴露的端口)
image.png
输入pod日志打印的秘钥,安装插件,创建用户的过程就不贴图了,最后要设置一个Jenkins_URL需要注意下,需要设置成下图方式(如果设置错了,后面也可以改,不用担心)
image.png

Jenkins-Master测试

官方Jenkins镜像提供了OpenJDK17的环境、Git环境,但是没有安装Maven,大家如果有需要可以自己重新构建Jenkins镜像、或者Jenkins的UI界面的工具配置中可以选择自动安装Maven,再或者可以在Pod中配置另一个容器(容器配置好构建环境)用于构建代码。
这里我先简单展示下默认的情况

kubectl get pods -n devops-tools
kubectl exec -it  xixi-jenkins-c879b6b69-6s5pq -n devops-tools /bin/bash

image.png

测试一个简单的FreeStyle任务

  1. 配置Gitee仓库

image.png

  1. shell命令打印“hello world”

image.png

  1. 执行构建,查看结果

image.png

Jenkins-Slave部署

部署步骤

  1. Jenkins中安装K8s插件

image.png

  1. Jenkins中配置云服务

image.png

  1. 新建云

image.png
image.png

  1. 配置K8s地址

image.png

这里什么都不填也可以

  1. 配置Jenkins地址

image.png

http://svc名称.命名空间:8080/

  1. 添加一个Pod标签,并点击保存

image.png

  1. 再次进入配置的云

image.png

  1. 进入PodTemplate,新增Pod模版

image.png

  1. 配置PodTemplate并保存

image.png

PodTemplate后面还会更改

  1. 构建Jenkins任务测试

image.png

限制项目运行节点,填写在PodTemplate中标签列表的内容(见9

image.png
image.png

  1. 查看任务执行结果

image.png
image.png

  1. 查看Jenkins-Slave的Pod
kubectl get pods -n devops-tools
kubectl exec -it jnlp-q90n6 /bin/sh

image.png
image.png

自定义构建环境的镜像

Jenkins-Slave部署完成后,发现Pod中默认启动的容器jnlp,只能满足我们拉取代码的任务,我们要通过Maven构建项目,并且我们项目是JDK8的,需要一个JDK8的环境,因此,我们可以构建一个自己的用于代码打包的镜像,然后添加到Jenkins-Slave的Pod中
image.png

FROM centos:7
ADD ./apache-maven-3.9.0-bin.tar.gz /usr/local/
RUN yum -y update \
    && yum -y install vim \
    && yum -y install git \
    && yum -y install java-1.8.0-openjdk-devel.x86_64
WORKDIR /usr/local/
ENV MAVEN_HOME=/usr/local/apache-maven-3.9.0
ENV PATH=$MAVEN_HOME/bin:$PATH
CMD ["/bin/bash","-c","while true; do echo hello world; sleep 1; done"]

解释下Dockerfile

  • maven的tar包中,我已经将settings.xml的中央仓库镜像换成了阿里云
  • 通过yum的方式安装了OpenJDK8和git
docker build -t my-env-build:2.0 .

修改PodTemplate,添加自定义构建环境容器

接下来我们需要将自己的镜像,也启动个容器放在Jenkins-Slave的Pod中

  1. 配置PodTemplate,添加容器

image.png

选择添加容器

image.png

输入自己构建环境的镜像名称:版本号。配置完成后,保存退出

  1. 构建一个pipeline项目
// Uses Declarative syntax to run commands inside a container.
pipeline {
     agent {
      label 'xixi-jnlp'
    }
    stages {
        stage('拉取代码') {
            steps {
                container('xixi-build') {
                    // some block
                    git credentialsId: '7e0d3d6a-2fd8-4f9e-b170-5dc351e3dc92', url: 'https://gitee.com/gao_xi/k8s-devops'
                    sh "mvn clean install"
                }
            }
        }
        
    }
}

Pipeline脚本中,通过**container(‘容器名称’),**可以切换到指定容器中执行

  1. 执行构建

image.png
image.png

可以看到已经可以执行mvn了

  1. 查看Pod情况

image.png

kubectl get pod jnlp-l20bs -o=jsonpath='{.spec.containers[*].name}' -n devops-tools

image.png

可以看到此时Pod已经有两个容器了

  • jnlp:是默认启动的容器,里面运行Jenkins-Slave的agent程序
  • xixi-build:是我们自定义的构建环境容器

甚至我们可以继续向Pod中添加容器,比如可以将Docker放入

  1. jnlp容器xixi-build容器有共享目录

image.png
image.png

可以看到两个容器中的**/home/jenkins/agent**是共享的。具体原因是,在Pod模版中配置了Empty Dir
image.pngimage.png

修改PodTemplate,添加Docker容器

添加了自己的容器后,我们再向Pod中添加一个Docker容器,用于执行一些Docker命令

  1. 添加Docker容器

image.png
image.png

这里需要将宿主机的**/var/run/docker.sock**挂载进去

  1. pipeline脚本
// Uses Declarative syntax to run commands inside a container.
pipeline {
    agent {
        label 'xixi-jnlp'
    }
    stages {
        stage('拉取代码') {
            steps {
                container('xixi-build') {
                    sh "echo hello world"
          
                }
                container('xixi-docker') {
                    sh "docker ps"
                }
            }
        }

    }
}

  1. 结果

image.png

  1. 查看Pod情况

image.png
image.png

目录也是通过EmptyDir方式,实现Pod内3个容器jnlp、xixi-build、xixi-docker中目录共享

Jenkins-Slave创建的Pod原理图

image.png

部署一个微服务项目

基于前面的Pod模板,里面有自己构建的一套JDK8+Maven+Git环境、Docker环境(分别在xixi-build容器中和xixi-docker容器中),在构建项目前,我们在K8s中部署一套Nacos,并且Jenkins中再配置一些内容。

Nacos部署

这里由于仅仅是为了演示,我使用的是官方的quick-start

git clone https://github.com/nacos-group/nacos-k8s.git
cd nacos-k8s
sh quick-startup.sh

image.png
image.png

项目中的Nacos地址配置:nacos-headless.default:8848

修改PodTemplate,挂载kubectl

image.png

继续修改Jenkins中的Pod模板,增添kubectl挂载。
Maven仓库可以也挂载出来,最好是声明个PVC,这里我就直接挂载到HostPath上

Jenkins-配置K8s凭证

image.png

将K8s集群Master节点的/root/.kube/config上传这里

Jenkins-安装K8s CLI插件

image.png

安装此插件后,可以通过Pipeline,执行kubectl命令

pipeline {
    agent {
        label 'xixi-jnlp'
    }

    stages {
        stage('测试kubectl'){
            steps{
                withKubeConfig(caCertificate: '', clusterName: '', contextName: '', credentialsId: 'k8s-config', namespace: 'default', restrictKubeConfigAccess: false, serverUrl: '') {
                    sh "kubectl get pods"
                }
            }
        }
    }
}

项目结构和Pipeline脚本

image.png

引入了dockerfile-maven-plugin插件,自动为我们打包镜像

<plugin>
  <groupId>com.spotify</groupId>
  <artifactId>dockerfile-maven-plugin</artifactId>
  <version>1.3.6</version>
  <configuration>
    <repository>${project.artifactId}</repository>
    <buildArgs>
      <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
    </buildArgs>
  </configuration>
</plugin>

pipeline

pipeline {
    agent {
      label 'xixi-jnlp'
    }

    environment {
        harbor_url = "registry.cn-hangzhou.aliyuncs.com"
        harbor_namespace = "aliyun_gx"
        gateway_project_name = "xixi-mall-gateway"
    }

    parameters {
      extendedChoice multiSelectDelimiter: ',', name: 'selectedProjects', quoteValue: false, saveJSONParameterToFile: false, type: 'PT_CHECKBOX', value: 'mall-order-service,mall-product-service,xixi-mall-gateway', visibleItemCount: 3
    }

    stages {
        stage('环境准备'){
            steps{
                script{
                    selectedProjects = selectedProjects.split(',')
                }
            }
        }
        
        stage('拉取代码'){
            steps{
              checkout scmGit(branches: [[name: '*/k8s-devops']], extensions: [], userRemoteConfigs: [[credentialsId: '7e0d3d6a-2fd8-4f9e-b170-5dc351e3dc92', url: 'https://gitee.com/gao_xi/xixi-mall-devops.git']])
            }
        }

        stage('构建整体'){
            steps{
                container('xixi-build'){
                    sh "mvn clean install"
                }
            }
        }

        stage('构建项目镜像'){
            steps{
                script{
                    for(int i=0;i<selectedProjects.size();i++){
                        def currentProject = selectedProjects[i];
                        echo "项目名称: ${currentProject}"
                        if( gateway_project_name == currentProject){
                            echo "发布网关"
                            container("xixi-build"){
                                sh "mvn -f ${currentProject} dockerfile:build"
                            }
                        } else {
                            container("xixi-build"){
                                sh "mvn -f xixi-mall-service/${currentProject} dockerfile:build"
                            }
                        }

                        //上传镜像
                        container("xixi-docker"){
                             sh "docker tag ${currentProject}:latest ${harbor_url}/${harbor_namespace}/${currentProject}:latest"
                             withCredentials([usernamePassword(credentialsId: 'aliyun-image-repo', passwordVariable: 'password', usernameVariable: 'username')]) {
                                 sh "docker login -u ${username} -p ${password} ${harbor_url}"
                                 sh "docker push ${harbor_url}/${harbor_namespace}/${currentProject}:latest"
                                 sh "docker rm -f ${currentProject}:latest"
                                 sh "docker rm -f ${harbor_url}/${harbor_namespace}/${currentProject}:latest"
                             }
                        }
                    }
                }
            }
        }

        stage('项目发布'){
            steps{
               script{
                  for(int i=0;i<selectedProjects.size();i++){
                     def currentProject = selectedProjects[i];
                     echo "发布项目: ${currentProject}"
                     withKubeConfig(caCertificate: '', clusterName: '', contextName: '', credentialsId: 'k8s-config', namespace: 'default', restrictKubeConfigAccess: false, serverUrl: '') {
                         sh "kubectl apply -f deploy/${currentProject}-deploy.yaml"
                     }
                  }
               }
            }
        }
    }
}

成果展示

image.png
image.png
image.png

通过网关访问服务
curl 10.102.58.6:18000/order/getOrder

image.png

可以为Gateway配置一个Ingress,这里就不演示了。

总结

好了,兄弟们,这就是XiXi最近探索的内容,中间过程相当曲折,镜像下载问题就把整个人整崩溃了,还好在水群的时候以前同学给了方案,阿里云租台美国主机,通过docker save 和 docker load -i的方式下载镜像。
如果大家想要我文档中一些配置的yaml和项目源码,可以私信,我尽量给到大家。

参考资料

  • 【完整版Kubernetes(K8S)全套入门+微服务实战项目,带你一站式深入掌握K8S核心能力】 https://www.bilibili.com/video/BV1MT411x7GH/?share_source=copy_web&vd_source=48905e7be046ec712a8d80b099294b80
  • 《Jenkins持续集成从入门到精通》(需要公众号推的,阿里的)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL----利用Mycat配置读写分离

首先确保主从复制是正常的&#xff0c;具体步骤在MySQL----配置主从复制。MySQL----配置主从复制 环境 master(CtenOS7)&#xff1a;192.168.200.131 ----ifconfig查看->ens33->inetslave(win10)&#xff1a;192.168.207.52 ----ipconfig查看->无线局域网适配器 WLA…

java的输出流File OutputStream

一、字节输出流FileOutput Stream 1、定义 使用OutputStream类的FileOutput Stream子类向文本文件写入的数据。 2.常用构造方法 3.创建文件输出流对象的常用方式 二、输出流FileOutputStream类的应用示例 1.示例 2、实现步骤 今天的总结就到此结束啦&#xff0c;拜拜&#x…

基于STM32的智能家居安防系统

目录 引言环境准备智能家居安防系统基础代码实现&#xff1a;实现智能家居安防系统 4.1 数据采集模块4.2 数据处理与分析4.3 控制系统实现4.4 用户界面与数据可视化应用场景&#xff1a;智能家居安防管理与优化问题解决方案与优化收尾与总结 1. 引言 智能家居安防系统通过使…

如何看待鸿蒙HarmonyOS?

鸿蒙系统&#xff0c;自2019年8月9日诞生就一直处于舆论风口浪尖上的系统&#xff0c;从最开始的“套壳”OpenHarmony安卓的说法&#xff0c;到去年的不再兼容安卓的NEXT版本的技术预览版发布&#xff0c;对于鸿蒙到底是什么&#xff0c;以及鸿蒙的应用开发的讨论从来没停止过。…

SpringBootWeb 篇-入门了解 Vue 前端工程的创建与基本使用

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 基于脚手架创建前端工程 1.1 基于 Vue 开发前端项目的环境要求 1.2 前端工程创建的方式 1.2.1 基于命令的方式来创建前端工程 1.2.2 使用图形化来创建前端工程 1.…

【计算机网络篇】数据链路层(13)共享式以太网与交换式以太网的对比

文章目录 &#x1f354;共享式以太网与交换式以太网的对比&#x1f50e;主机发送单播帧的情况&#x1f50e;主机发送广播帧的情况&#x1f50e;多对主机同时通信 &#x1f6f8;使用集线器和交换机扩展共享式以太网的区别 &#x1f354;共享式以太网与交换式以太网的对比 下图是…

异地局域网纯软件组网如何设置?

在现代社会中&#xff0c;随着企业的不断扩张和分布&#xff0c;异地办公成为一种常见的工作模式。随之而来的是&#xff0c;如何实现异地局域网的组网设置成为了一个挑战。在这种情况下&#xff0c;采用纯软件组网方案是一种有效的解决方案。本文将介绍异地局域网纯软件组网设…

Qt——系统

目录 概述 事件 鼠标事件 进入、离开事件 按下事件 释放事件 双击事件 移动事件 滚轮事件 按键事件 单个按键 组合按键 定时器 QTimerEvent QTimer 窗口事件 文件 输入输出设备 文件读写类 文件和目录信息类 多线程 常用API 线程安全 互斥锁 条件变量…

vuex的深入学习[基于vuex3]----篇(二)

store对象的创建 store的传递图 创建语句索引 创建vuex的语句为new Vuex.Store({…})Vuex的入口文件是index.js,store是index.js导出的store类store类是store.js文件中定义的。 Store的构造函数constructor 判断vuex是否被注入&#xff0c;就是将vue挂载在window对象上&am…

【database2】redis:优化/备份/订阅

文章目录 1.redis安装&#xff1a;加载.conf2.操作&#xff1a;set/get&#xff0c;push/pop&#xff0c;add/rem3.Jedis&#xff1a;java程序连接redis&#xff0c;拿到jedis4.案例_好友列表&#xff1a;json om.4.1 前端&#xff1a;index.html4.2 web&#xff1a;FriendSer…

GIM: Learning Generalizable Image Matcher From Internet Videos

【引用格式】&#xff1a;Shen X, Yin W, Mller M, et al. GIM: Learning Generalizable Image Matcher From Internet Videos[C]//The Twelfth International Conference on Learning Representations. 2023. 【网址】&#xff1a;https://arxiv.org/pdf/2402.11095 【开源代…

使用 axios 进行 HTTP 请求

使用 axios 进行 HTTP 请求 文章目录 使用 axios 进行 HTTP 请求1、介绍2、安装和引入3、axios 基本使用4、axios 发送 GET 请求5、axios 发送 POST 请求6、高级使用7、总结 1、介绍 什么是 axios axios 是一个基于 promise 的 HTTP 库&#xff0c;可以用于浏览器和 Node.js 中…

高职人工智能专业实训课之“图像识别基础”

一、前言 随着人工智能技术的迅猛发展&#xff0c;高职院校对人工智能专业实训课程的需求日益迫切。唯众人工智能教学实训平台作为一所前沿的教育技术平台&#xff0c;致力于为学生提供高效、便捷的人工智能实训环境&#xff0c;特别在“图像识别基础”这一关键课程中&#xf…

JVM 相关知识整理

文章目录 前言JVM 相关知识整理1. 新生代和老年代2. 对象的分配过程3. Full GC /Major GC 触发条件4. 逃逸分析4.1.示例4.2. 使用逃逸分析&#xff0c;编译器可以对代码做如下优化 5. 对象的内存分配6. Minor GC 与 Major GC/Full GC的比较:7. 什么对象进入老年代7.1. 大对象直…

(4) cmake编译静态库和动态库

文章目录 静态库整体代码动态库编译整体代码执行结果(静态) 静态库整体代码 static.h #pragma onecevoid static_demo();static.cpp #include "static.h" #include <iostream>void static_demo(){std::cout<<"static demo"<<std::end…

深度学习增强的非线性光纤单像素成像系统

1、光子器件的逆向设计&#xff1a;通过机器学习&#xff0c;特别是深度学习&#xff0c;可以高效地进行光子器件的逆向设计&#xff0c;这在传统的多参数优化问题中尤为重要。 2、超构表面和超材料设计&#xff1a;机器学习被用于设计具有特定光学特性的超构表面和超材料&…

上位机图像处理和嵌入式模块部署(mcu和swd接口)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 最近学习mcu的时候&#xff0c;接触了不少调试器&#xff0c;这里面有daplink、st-link v2、j-link v9。虽然模块的形状可能不太一样&#xff0c;但…

力扣SQL50 销售分析III having + 条件计数

Problem: 1084. 销售分析III &#x1f468;‍&#x1f3eb; 参考题解 Code select s.product_id,p.product_name from sales s left join product p on s.product_id p.product_id group by product_id having count(if(sale_date between 2019-01-01 and 2019-03-31,1,nu…

OpenAPI

大家好我是苏麟 , 今天带来一个前端生成接口的工具 . 官网 : GitHub - ferdikoomen/openapi-typescript-codegen: NodeJS library that generates Typescript or Javascript clients based on the OpenAPI specification 安装命令 npm install openapi-typescript-codegen --sa…

对接Shopify电商平台的流程

对接Shopify平台的流程通常包括以下关键步骤&#xff0c;在整个对接过程中&#xff0c;需要密切关注Shopify的API使用限制、认证机制、数据隐私政策等&#xff0c;确保应用的安全性和合规性。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合…