当前位置:首页 > 科技  > 软件

用代码实现流水线部署,像诗一般优雅

来源: 责编: 时间:2024-04-03 17:44:17 140观看
导读你好,我是悟空。本文目录如下:图片这次我们要接着上面的话题聊下如何通过通过编写代码的方式实现自动化部署 Java 项目。而用代码方式其实就是使用 Jenkins 强大的 pipeline 功能来实现的。通过本篇你可以学习到如下内

你好,我是悟空。Kgk28资讯网——每日最新资讯28at.com

本文目录如下:Kgk28资讯网——每日最新资讯28at.com

图片图片Kgk28资讯网——每日最新资讯28at.com

这次我们要接着上面的话题聊下如何通过通过编写代码的方式实现自动化部署 Java 项目。Kgk28资讯网——每日最新资讯28at.com

而用代码方式其实就是使用  Jenkins 强大的 pipeline 功能来实现的。Kgk28资讯网——每日最新资讯28at.com

通过本篇你可以学习到如下内容:Kgk28资讯网——每日最新资讯28at.com

  • Pipeline 的概念、优点、缺点。
  • 实战:通过编写 pipeline 来部署一个完整的后端项目。
  • pipeline 传参的合理利用。
  • 多选插件、远程传输文件、远程执行命令的使用。

一、Pipeline

1.1 流水线

要了解什么是Pipeline,就必须知道什么是流水线。类似于食品工厂包装食品,食品被放到传送带上,经过一系列操作后,包装完成,这种工程就是流水线工程。Kgk28资讯网——每日最新资讯28at.com

1.2 Pipeline 是什么

在自动化部署中,开发完成的代码经过一系列顺序操作后被部署完成,这个就是部署过程中的流水线,我们通常称作 pipeline。Kgk28资讯网——每日最新资讯28at.com

之前我们的部署步骤都是通过在 Jenkins 的 UI 界面上配置出来的,但其实 Jenkisn 2.x 版本已经可以支持编写代码的方式来启动自动化部署了,通过“代码”来描述部署流水线。Kgk28资讯网——每日最新资讯28at.com

Jenkins pipeline其实就是基于一种声明式语言,用于描述整条流水线是如何进行的。流水线的内容包括执行编译、打包、测试、输出测试报告等步骤。Kgk28资讯网——每日最新资讯28at.com

1.3 为什么要用 Pipeline

Pipeline 通过代码来实现,其实就具有很多代码的优势了,比如:Kgk28资讯网——每日最新资讯28at.com

  • 支持传参:可以在 Pipeline 代码里面配置用户要输入或选择的参数,这个功能真的太棒了。比如可以传 Gitlab 分支名、部署哪个服务等。
  • 更好地版本化:将 pipeline 代码提交到软件版本库中进行版本控制。
  • 更好地协作:pipeline 的每次修改对所有人都是可见的。除此之外,还可以对pipeline进行代码审查
  • 更好的重用性:手动操作没法重用,但是代码可以重用。

当然 pipeline 的缺点也是有的:Kgk28资讯网——每日最新资讯28at.com

  • 学习成本高:需要熟悉 pipeline 的语法规则。
  • 复杂:代码不够直观,编写的逻辑可能很复杂,容易出错。

1.4 如何使用 Pipeline

在之前的文章中,我是通过创建一个自由风格的项目来实现自动化部署,其实还可以通过创建一个Pipeline 来实现,如下图所示:Kgk28资讯网——每日最新资讯28at.com

创建 Pipeline 任务创建 Pipeline 任务Kgk28资讯网——每日最新资讯28at.com

然后就可以在配置流水线的地方编写代码了。如下图所示:Kgk28资讯网——每日最新资讯28at.com

编写流水线代码编写流水线代码Kgk28资讯网——每日最新资讯28at.com

1.5 Pipeline 基础结构

Pipeline 基础结构如下所示:Kgk28资讯网——每日最新资讯28at.com

pipeline{//指定运行此流水线的节点agent any//流水线的阶段stages{    //阶段1 获取代码    stage("CheckOut") {        steps {            script {                echo "获取代码"            }        }    }}
  • pipeline 部分:代表整条流水线,包含整条流水线的逻辑。
  • stage 部分:代表流水线的某个阶段。每个阶段都必须有名称,本例中,"CheckOut" 就是此阶段的名称。
  • stages 部分:流水线中多个stage的容器。stages 部分至少包含一个 stage。steps 部分:代表阶段中的一个或多个具体步骤(step)的容器。steps 部分至少包含一个步骤,本例中,echo就是一个步骤。在一个 stage 中有且只有一个steps。
  • agent 部分:指定流水线的执行位置(Jenkins agent)。流水线中的每个阶段都必须在某个地方(物理机、虚拟机或Docker容器)执行,agent 部分即指定具体在哪里执行。

以上每一个部分都不能少,否则 Jenkins 会报错。Kgk28资讯网——每日最新资讯28at.com

二、部署思路

2.1 Jenkins 承担的角色

Jenkins 承担的角色如下图所示:Kgk28资讯网——每日最新资讯28at.com

图片图片Kgk28资讯网——每日最新资讯28at.com

Jenkins 打包部署原理图Kgk28资讯网——每日最新资讯28at.com

  • (1)Jenkins 部署在一台服务器上,然后安装了很多必备的 Jenkins 插件。比如拉取 Gitlab 仓库代码的插件、远程执行命令和拷贝文件的插件。
  • (2)Jenkins 开始运行一个任务时,通过 Git 插件从 Gitlab 仓库拉取代码到本地目录。
  • (3)Jenkins 通过 JDK 和 Maven 工具对 Java 代码进行打包部署。
  • (4)Jenkins 将 JAR 包拷贝到远程服务器的固定目录下。
  • (5)Jenkins 通过 SSH 插件执行远程命令,将包进行备份操作。
  • (6)Jenkins 通过执行远程命令,更新 JAR 包。
  • (7)Jenkins 通过执行远程命令,重启容器。

2.2 通过流水线来部署项目

我们项目是 Java 项目,所以通过流水线来部署项目的步骤如下图所示:Kgk28资讯网——每日最新资讯28at.com

流水线部署步骤流水线部署步骤Kgk28资讯网——每日最新资讯28at.com

三、获取 Gitlab 分支代码

Pipeline 的强大之处是可以支持传参以及获取参数,为了让用户可以选择获取不同的分支代码,我在 pipeline 代码中配置了一个参数:获取指定的 Gitlab 分支代码。Kgk28资讯网——每日最新资讯28at.com

3.1 Gitlab 分支配置

在 流水线代码中添加 parameters 节点,指定类型为 string,配置相关的属性。Kgk28资讯网——每日最新资讯28at.com

pipeline {      parameters {          string (            name: 'GIT_BRANCH', // 参数名,后面 steps 中会用到            defaultValue: 'dev-01.30', // 默认值,会显示在界面上,用户可以改。            description: '请选择部署的分支' // 说明        )    }    // 其他代码    ...}

通过参数部分,定义了一个名为GIT_BRANCH的参数,它允许用户在构建过程中选择要构建的分支。默认情况下,分支被设置为dev-01.30,用户可以选择不同的分支。Kgk28资讯网——每日最新资讯28at.com

在脚本中,这个参数可以通过params.GIT_BRANCH 获取到。Kgk28资讯网——每日最新资讯28at.com

保存配置后,需要先运行一次这个项目才能看到参数配置。如下图所示:右边就是参数配置。Kgk28资讯网——每日最新资讯28at.com

Build with ParametersKgk28资讯网——每日最新资讯28at.com

3.2 配置环境参数

接着我们还需要定义一些常用的环境变量信息,比如 Gitlab 的仓库地址,代码如下所示:Kgk28资讯网——每日最新资讯28at.com

pipeline {    parameters {      // 配置信息      ...    }    // 环境变量:定义 GitLab 仓库的 URL 和分支      environment {          GIT_URL = 'https://xxx/xxx.git'             }    // 其他代码    ...}

environment 节点为环境变量信息,GIT_URL 变量代表 Gitlab 的仓库地址。在脚本中,这个变量可以通过${GIT_URL}使用。Kgk28资讯网——每日最新资讯28at.com

3.3 获取 Gitlab 分支代码

接下来我们来看下如何在 pipeline 中添加一个获取 gitlab 仓库代码的步骤。Kgk28资讯网——每日最新资讯28at.com

pipeline {      agent any      parameters {          string(            name: 'GIT_BRANCH',             defaultValue: 'dev-01.30',             description: '请选择部署的分支')    }    // 定义 GitLab 仓库的 URL 和分支      environment {          GIT_URL = 'https://XXX/xxx.git'    }       stages {          stage('获取最新代码') {              steps {                  script {                      // 使用 params 对象获取参数值                      def branchName = params.GIT_BRANCH                      echo "Building branch: ${branchName}"                      // 使用 git 插件检出仓库的特定分支                      checkout([                          $class: 'GitSCM',                          branches: [[name: "${branchName}"]],                          doGenerateSubmoduleConfigurations: false,                          extensions: [],                          submoduleCfg: [],                          userRemoteConfigs: [[                              credentialsId: '211583e9-8ee1-4fa2-9edd-d43a963de8f2', // 在 Jenkins 凭据中定义的 GitLab 凭据 ID                              url: "${GIT_URL}"                          ]]                      ])                  }              }          }    }}
  1. 参数定义:通过参数部分,定义了一个名为GIT_BRANCH的参数,它允许用户在构建过程中选择要构建的分支。默认情况下,分支被设置为dev-01.30,用户可以选择不同的分支。
  2. 环境变量定义:在环境部分,设置了GIT_URL变量,它是GitLab仓库的URL。在脚本中,这个变量可以通过${GIT_URL}使用。
  3. 阶段定义:在stages部分,定义了一个名为"获取最新代码"的阶段。
  4. 步骤定义:在阶段内,使用了script块来执行Groovy脚本。这个脚本首先获取了GIT_BRANCH参数的值,然后使用Jenkins的Git插件检出指定的分支。
  5. 检出代码:checkout步骤是用来从GitLab仓库检出代码的关键部分。它使用了GitSCM类,并传递了相应的参数,包括分支名、GitLab凭据等。

注意:获取分支的凭证是一个 ID,这个凭证信息是在 Jenkins 系统配置中加的。可以按照如下页面路径添加凭证:Dashboard->Manage Jenkins->Credentials->System->Add domain。也可以通过如下 URL 访问Kgk28资讯网——每日最新资讯28at.com

http://<你的服务器 IP>:8080/manage/credentials/store/system/

图片图片Kgk28资讯网——每日最新资讯28at.com

3.4  测试 pipeline 执行

我们可以运行一下这个项目来测试 pipeline 代码。运行结果如下图所示,可以看到右侧的阶段视图,整体耗时和每个步骤的耗时,以及每个步骤的成功与否都显示出来了,非常直观。Kgk28资讯网——每日最新资讯28at.com

图片图片Kgk28资讯网——每日最新资讯28at.com

四、编译代码

本篇主要讲解的是部署 Java 项目,所以编译项目也是采用 Maven 打包的方式。在 pipeline 脚本中执行 mvn 打包命令即可。Kgk28资讯网——每日最新资讯28at.com

stage('编译代码') {     steps {       script {         echo "--------------- 步骤:开始编译 --------------- "       bat 'mvn clean package'       echo "--------------- 步骤:编译完成 --------------- "     }  }  }

核心代码:bat 'mvn clean package'Kgk28资讯网——每日最新资讯28at.com

因为我的 Jenkins 是部署在 Windows 机器上,所以执行命令用的 windows 自带的 bat 工具来执行的。Kgk28资讯网——每日最新资讯28at.com

关于 maven 工具的配置可以看之前写的第二篇内容:Kgk28资讯网——每日最新资讯28at.com

喝杯咖啡,一键部署完成!(建议收藏)Kgk28资讯网——每日最新资讯28at.com

五、上传 JAR 包

编译完成后,就可以将 Jenkins 工作空间的 JAR 包上传到服务器的 temp 目录下。Kgk28资讯网——每日最新资讯28at.com

如果你想部署指定的某些微服务,可以通过传参的方式来上传和更新指定的微服务。原理图如下所示:Kgk28资讯网——每日最新资讯28at.com

图片图片Kgk28资讯网——每日最新资讯28at.com

5.1 支持勾选多个服务

为了实现可以选择部署哪些微服务,需要安装一个多选插件:Extended Choice Parameter。Kgk28资讯网——每日最新资讯28at.com

图片图片Kgk28资讯网——每日最新资讯28at.com

Extended Choice Parameter  插件Kgk28资讯网——每日最新资讯28at.com

接下来是编写的参数配置代码:Kgk28资讯网——每日最新资讯28at.com

parameters {    extendedChoice (         defaultValue: 'All',         description: '需要部署的微服务',         multiSelectDelimiter: ',',         name: 'SERVICE_NAME',         quoteValue: false,         saveJSONParameterToFile: false,         type: 'PT_CHECKBOX',         value:'All, passjava-account, passjava-file',        visibleItemCount: 10    )}
  • defaultValue: 参数的默认值。在这里,默认值为 'All'。
  • description: 参数的描述或提示。这里描述为 '需要部署的微服务',表示选择需要部署的微服务。
  • multiSelectDelimiter: 多选时的分隔符。这里设置为 ',',表示使用逗号作为分隔符。
  • name: 参数的名称。这里是 'SERVICE_NAME'。
  • quoteValue: 确定是否对值加上引号。这里设置为 false,表示不加引号。
  • saveJSONParameterToFile: 是否将 JSON 参数保存到文件。
  • type: 参数的类型。这里是 'PT_CHECKBOX',表示复选框类型。
  • value: 可选的值列表。在这里,可选的值有 'All'、'passjava-account'、'passjava-file'。
  • visibleItemCount: 可见的选项数量。这里设置为 10。

配置保存后并运行一次后,就可以在 pipeline 中看到配置选项:Kgk28资讯网——每日最新资讯28at.com

图片图片Kgk28资讯网——每日最新资讯28at.com

实现的效果如下图右下角所示,可以支持多选。Kgk28资讯网——每日最新资讯28at.com

图片图片Kgk28资讯网——每日最新资讯28at.com

5.2 上传 JAR 包

上传需要使用 sshPublisher 插件,在第二篇文章中已介绍了。Kgk28资讯网——每日最新资讯28at.com

下面上传代码的作用是遍历 filesToCopy 列表中的文件,然后通过 SSH 将这些文件上传到远程服务器的指定目录中。Kgk28资讯网——每日最新资讯28at.com

filesToCopy.eachWithIndex { file, index ->     echo "开始上传 JAR 包 ${file} ..."    sshPublisher(        failOnError: true,        publishers: [            sshPublisherDesc(                configName: "${SSH_URL}",                verbose: true,                transfers: [                    sshTransfer(                        execCommand: '',                         execTimeout: 120000,                         flatten: false,                         makeEmptyDirs: false,                         noDefaultExcludes: false,                         patternSeparator: '[, ]+',                         remoteDirectory: 'apps/temp/',                         remoteDirectorySDF: false,                         removePrefix: removePrefixs[index],                         sourceFiles: file                    )                ]            )        ]    )    echo "完成上传 JAR 包 ${file}"}
  1. filesToCopy.eachWithIndex { file, index -> ... }: 这是一个 Groovy 中的迭代循环,对列表 filesToCopy 中的每个文件执行相应的操作。file 是当前迭代的文件,index 是该文件在列表中的索引。
  2. echo "开始上传 JAR 包 ${file} ...": 这是一个打印语句,用于输出日志,显示当前正在上传的 JAR 包的文件名。
  3. sshPublisher { ... }: 这是一个 SSH 发布器,用于通过 SSH 连接到远程服务器并执行相应的操作。
  4. failOnError: true: 如果 SSH 连接或传输过程中出现错误,将会终止流水线执行。
  5. configName: "${SSH_URL}": 这是 SSH 配置的名称,${SSH_URL} 是一个变量,指定 SSH 连接的配置信息。
  6. transfers: [sshTransfer { ... }]: 这是 SSH 传输操作的列表,包含了将要执行的文件传输任务。
  7. remoteDirectory: 'apps/temp/': 远程服务器上的目标目录,这里设置为 apps/temp/,表示将文件上传到远程服务器的 apps/temp/ 目录下。
  8. removePrefix: removePrefixs[index]: 这是一个用于移除文件路径前缀的设置,根据当前文件在列表中的索引,从相应的 removePrefixs 数组中获取相应的前缀进行移除。
  9. sourceFiles: file: 要传输的源文件,即当前迭代的文件。
  10. echo "完成上传 JAR 包 ${file}": 这是另一个打印语句,用于输出日志,表示当前文件的上传已经完成。

filesToCopy 就是通过用户勾选的服务名转成了对应的本地 JAR 包路径。Kgk28资讯网——每日最新资讯28at.com

switch(service) {    case 'passjava-account':        filesToCopy.add("passjava-modules/passjava-module-account/passjava-module-account-core/target/passjava-account.jar")        removePrefixs.add("passjava-modules/passjava-module-account/passjava-module-account-core/target")        break     case ...  }

六、备份服务器 JAR 包

备份的思路:逐个处理 serviceNameList 中的服务名称,然后通过 SSH 连接到远程服务器执行备份操作。serviceNameList 就是用户勾选的服务名的集合。原理图如下所示:Kgk28资讯网——每日最新资讯28at.com

备份服务器 JAR 包备份服务器 JAR 包Kgk28资讯网——每日最新资讯28at.com

核心代码如下:Kgk28资讯网——每日最新资讯28at.com

serviceNameList.each { service ->   echo "开始备份微服务 ${service} 包"  sshPublisher(      failOnError: true,      publishers: [          sshPublisherDesc(              configName: "${SSH_URL}",              verbose: true,              transfers: [                  sshTransfer(                      execCommand: "mkdir -p /nfs-data/wukong/apps/bak/${timestamp} && cd /nfs-data/wukong/apps && mv ${service}.jar ./bak/${timestamp}/${service}-${timestamp}.jar"                  )              ]          )      ]  )
  1. serviceNameList.each { service -> ... }: 这是一个 Groovy 中的迭代循环,对列表 serviceNameList 中的每个服务名称执行备份操作。service 是当前迭代的服务名称。
  2. echo "开始备份微服务 ${service} 包": 这是一个打印语句,用于输出日志,显示当前正在备份的微服务的名称。
  3. sshPublisher { ... }: 这是一个 SSH 发布器,用于通过 SSH 连接到远程服务器并执行相应的操作。
  4. failOnError: true: 如果 SSH 连接或执行过程中出现错误,将会终止流水线执行。
  5. configName: "${SSH_URL}": 这是 SSH 配置的名称,${SSH_URL} 是一个变量,用于指定 SSH 连接的配置信息。
  6. transfers: [sshTransfer { ... }]: 这是 SSH 传输操作的列表,包含了将要执行的文件传输任务。
  7. execCommand: "...": 这是要在远程服务器上执行的命令。在这里,使用了 mkdir 命令创建备份目录,然后将当前服务的 JAR 包移动到备份目录下,并加上时间戳作为文件名,以实现备份。

这段代码的作用是遍历 serviceNameList 列表中的服务名称,然后通过 SSH 连接到远程服务器执行备份操作,将每个服务的 JAR 包移动到指定的备份目录,并根据时间戳进行命名。Kgk28资讯网——每日最新资讯28at.com

七、更新 JAR 包

更新最新的 JAR 包就是将最新的 JAR 包放到对应的容器映射的目录,后面重启容器的时候,就能用最新的 JAR 包启动了。原理图如下所示:Kgk28资讯网——每日最新资讯28at.com

更新 JAR 包更新 JAR 包Kgk28资讯网——每日最新资讯28at.com

serviceNameList.eachWithIndex { service, index ->     echo "开始更新第 ${index + 1} 个 JAR 包,/nfs-data/wukong/apps/temp/${service}.jar ..."        sshPublisher(            failOnError: true,            publishers: [                sshPublisherDesc(                    configName: "${SSH_URL}",                    verbose: true,                    transfers: [                        sshTransfer(                            execCommand: "cd /nfs-data/wukong/apps && mv -f ./temp/${service}.jar ${service}.jar",                            execTimeout: 120000                        )                    ]                )            ]        )    echo "----- 完成更新 JAR 包 -----"}
  1. serviceNameList.eachWithIndex { service, index -> ... }: 这是一个 Groovy 中的迭代循环,对列表 serviceNameList 中的每个服务名称执行更新操作。service 是当前迭代的服务名称,index 是该服务在列表中的索引。
  2. echo "开始更新第 ${index + 1} 个 JAR 包,/nfs-data/wukong/apps/temp/${service}.jar ...": 这是一个打印语句,用于输出日志,显示当前正在更新的 JAR 包的名称及路径。
  3. sshPublisher { ... }: 这是一个 SSH 发布器,用于通过 SSH 连接到远程服务器并执行相应的操作。
  4. failOnError: true: 如果 SSH 连接或执行过程中出现错误,将会终止流水线执行。
  5. configName: "${SSH_URL}": 这是 SSH 配置的名称,${SSH_URL} 是一个变量,用于指定 SSH 连接的配置信息。
  6. transfers: [sshTransfer { ... }]: 这是 SSH 传输操作的列表,包含了将要执行的文件传输任务。
  7. execCommand: "cd /nfs-data/wukong/apps && mv -f ./temp/${service}.jar ${service}.jar": 这是要在远程服务器上执行的命令。在这里,使用 mv 命令将位于 /nfs-data/wukong/apps/temp/ 目录下的 ${service}.jar 移动到 /nfs-data/wukong/apps/ 目录,并覆盖同名的文件。
  8. execTimeout: 120000: 这是执行命令的超时时间,单位是毫秒。在这里,设置为 120000,即 120 秒。
  9. echo "----- 完成更新 JAR 包 -----": 这是另一个打印语句,用于输出日志,表示当前 JAR 包的更新操作已经完成。

这段代码的作用是遍历 serviceNameList 列表中的服务名称,然后通过 SSH 连接到远程服务器执行更新操作,将每个服务在 /nfs-data/wukong/apps/temp/ 目录下的 JAR 包移动到对应的位置,完成更新。Kgk28资讯网——每日最新资讯28at.com

八、启动多个服务

启动服务就是将 docker swarm 管理的服务重启下,原理图如下所示:Kgk28资讯网——每日最新资讯28at.com

图片图片Kgk28资讯网——每日最新资讯28at.com

后端项目使用 Docker Swarm 部署的,重启服务的命令如下:Kgk28资讯网——每日最新资讯28at.com

sudo docker service update --force <服务名>

我们可以编写远程执行这行命令的代码,pipeline 核心代码如下:Kgk28资讯网——每日最新资讯28at.com

serviceNameList.eachWithIndex { service, index ->     echo "开始重启第 ${index + 1} 个微服务,${service} ..."    sshPublisher(        failOnError: true,        publishers: [            sshPublisherDesc(                configName: "${SSH_URL}",                verbose: true,                transfers: [                    sshTransfer(                        execCommand: "sudo docker service update --force ${commands[service]}",                        execTimeout: 120000                    )                ]            )        ]    )    echo "----- 完成重启微服务 -----"}

这段代码的作用是遍历 serviceNameList 列表中的服务名称,然后通过 SSH 连接到远程服务器执行重启操作,完成微服务的重启。Kgk28资讯网——每日最新资讯28at.com

最后整个执行结果如下图所示:总共耗时 3min41s。Kgk28资讯网——每日最新资讯28at.com

图片图片Kgk28资讯网——每日最新资讯28at.com

九、总结

通过本篇的实战内容,我们学习到了通过编写 pipeline 代码来实现部署后端项目。推荐大家都用 pipeline 来部署项目,好处是更加灵活。Kgk28资讯网——每日最新资讯28at.com

另外本篇还没有对 Jenkins pipeline 的版本管理,我们其实可以将 pipeline 代码作为一个文件上传到 Gitlab,然后通过 Jenkins 拉取最新的 jenkins pipeline 文件来执行部署,这样更便于管理 pipeline 文件。Kgk28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-81249-0.html用代码实现流水线部署,像诗一般优雅

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 加速 Rust 编译时间,掌握这个技巧,速度全面提升 30 ~ 40 %

下一篇: 几个祖传代码不遵守就想骂的代码规范

标签:
  • 热门焦点
  • 轿车从天而降电动车主被撞身亡 超速抢道所致:现场视频让网友吵翻

    轿车从天而降电动车主被撞身亡 超速抢道所致:现场视频让网友吵翻

    近日,上海青浦区法院判决轿车从天而降电动车主被撞身亡案,轿车车主被判有期徒刑一年。案件显示当时男子驾驶轿车在上海某路段行驶,前车忽然转弯提速超车,
  • 8月总票房已突破10亿!《封神》第一:口碑已经成了

    8月总票房已突破10亿!《封神》第一:口碑已经成了

    8月5日消息,据灯塔专业版数据,截至8月5日9时35分,8月总票房(含预售)已突破10亿。其中,《封神》以大比分的优势领先。根据官方消息,目前该片总票房已经超过14.
  • K8S | Service服务发现

    K8S | Service服务发现

    一、背景在微服务架构中,这里以开发环境「Dev」为基础来描述,在K8S集群中通常会开放:路由网关、注册中心、配置中心等相关服务,可以被集群外部访问;图片对于测试「Tes」环境或者
  • 从 Pulsar Client 的原理到它的监控面板

    从 Pulsar Client 的原理到它的监控面板

    背景前段时间业务团队偶尔会碰到一些 Pulsar 使用的问题,比如消息阻塞不消费了、生产者消息发送缓慢等各种问题。虽然我们有个监控页面可以根据 topic 维度查看他的发送状态,
  • 虚拟键盘 API 的妙用

    虚拟键盘 API 的妙用

    你是否在遇到过这样的问题:移动设备上有一个固定元素,当激活虚拟键盘时,该元素被隐藏在了键盘下方?多年来,这一直是 Web 上的默认行为,在本文中,我们将探讨这个问题、为什么会发生
  • 一个注解实现接口幂等,这样才优雅!

    一个注解实现接口幂等,这样才优雅!

    场景码猿慢病云管理系统中其实高并发的场景不是很多,没有必要每个接口都去考虑并发高的场景,比如添加住院患者的这个接口,具体的业务代码就不贴了,业务伪代码如下:图片上述代码有
  • 共享单车的故事讲到哪了?

    共享单车的故事讲到哪了?

    来源丨海克财经与共享充电宝相差不多,共享单车已很久没有被国内热点新闻关照到了。除了一再涨价和用户直呼用不起了。近日多家媒体再发报道称,成都、天津、郑州等地多个共享单
  • 联想YOGA 16s 2022笔记本将要推出,屏幕支持触控功能

    联想YOGA 16s 2022笔记本将要推出,屏幕支持触控功能

    联想此前宣布,将于11月2日19:30召开联想秋季轻薄新品发布会,推出联想 YOGA 16s 2022 笔记本等新品。官方称,YOGA 16s 2022 笔记本将搭载 16 英寸屏幕,并且是一
  • DRAM存储器10月价格下跌,NAND闪存本月价格与上月持平

    DRAM存储器10月价格下跌,NAND闪存本月价格与上月持平

    10月30日,据韩国媒体消息,自今年年初以来一直在上涨的 DRAM 存储器的交易价格仅在本月就下跌了近 10%,此次是全年首次降价,而NAND 闪存本月价格与上月持平。市
Top