AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當前位置:首頁 > 科技  > 軟件

用代碼實現流水線部署,像詩一般優雅

來源: 責編: 時間:2024-04-03 17:44:17 233觀看
導讀你好,我是悟空。本文目錄如下:圖片這次我們要接著上面的話題聊下如何通過通過編寫代碼的方式實現自動化部署 Java 項目。而用代碼方式其實就是使用 Jenkins 強大的 pipeline 功能來實現的。通過本篇你可以學習到如下內

你好,我是悟空。m2o28資訊網——每日最新資訊28at.com

本文目錄如下:m2o28資訊網——每日最新資訊28at.com

圖片圖片m2o28資訊網——每日最新資訊28at.com

這次我們要接著上面的話題聊下如何通過通過編寫代碼的方式實現自動化部署 Java 項目。m2o28資訊網——每日最新資訊28at.com

而用代碼方式其實就是使用  Jenkins 強大的 pipeline 功能來實現的。m2o28資訊網——每日最新資訊28at.com

通過本篇你可以學習到如下內容:m2o28資訊網——每日最新資訊28at.com

  • Pipeline 的概念、優點、缺點。
  • 實戰:通過編寫 pipeline 來部署一個完整的后端項目。
  • pipeline 傳參的合理利用。
  • 多選插件、遠程傳輸文件、遠程執行命令的使用。

一、Pipeline

1.1 流水線

要了解什么是Pipeline,就必須知道什么是流水線。類似于食品工廠包裝食品,食品被放到傳送帶上,經過一系列操作后,包裝完成,這種工程就是流水線工程。m2o28資訊網——每日最新資訊28at.com

1.2 Pipeline 是什么

在自動化部署中,開發完成的代碼經過一系列順序操作后被部署完成,這個就是部署過程中的流水線,我們通常稱作 pipeline。m2o28資訊網——每日最新資訊28at.com

之前我們的部署步驟都是通過在 Jenkins 的 UI 界面上配置出來的,但其實 Jenkisn 2.x 版本已經可以支持編寫代碼的方式來啟動自動化部署了,通過“代碼”來描述部署流水線。m2o28資訊網——每日最新資訊28at.com

Jenkins pipeline其實就是基于一種聲明式語言,用于描述整條流水線是如何進行的。流水線的內容包括執行編譯、打包、測試、輸出測試報告等步驟。m2o28資訊網——每日最新資訊28at.com

1.3 為什么要用 Pipeline

Pipeline 通過代碼來實現,其實就具有很多代碼的優勢了,比如:m2o28資訊網——每日最新資訊28at.com

  • 支持傳參:可以在 Pipeline 代碼里面配置用戶要輸入或選擇的參數,這個功能真的太棒了。比如可以傳 Gitlab 分支名、部署哪個服務等。
  • 更好地版本化:將 pipeline 代碼提交到軟件版本庫中進行版本控制。
  • 更好地協作:pipeline 的每次修改對所有人都是可見的。除此之外,還可以對pipeline進行代碼審查
  • 更好的重用性:手動操作沒法重用,但是代碼可以重用。

當然 pipeline 的缺點也是有的:m2o28資訊網——每日最新資訊28at.com

  • 學習成本高:需要熟悉 pipeline 的語法規則。
  • 復雜:代碼不夠直觀,編寫的邏輯可能很復雜,容易出錯。

1.4 如何使用 Pipeline

在之前的文章中,我是通過創建一個自由風格的項目來實現自動化部署,其實還可以通過創建一個Pipeline 來實現,如下圖所示:m2o28資訊網——每日最新資訊28at.com

創建 Pipeline 任務創建 Pipeline 任務m2o28資訊網——每日最新資訊28at.com

然后就可以在配置流水線的地方編寫代碼了。如下圖所示:m2o28資訊網——每日最新資訊28at.com

編寫流水線代碼編寫流水線代碼m2o28資訊網——每日最新資訊28at.com

1.5 Pipeline 基礎結構

Pipeline 基礎結構如下所示:m2o28資訊網——每日最新資訊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 會報錯。m2o28資訊網——每日最新資訊28at.com

二、部署思路

2.1 Jenkins 承擔的角色

Jenkins 承擔的角色如下圖所示:m2o28資訊網——每日最新資訊28at.com

圖片圖片m2o28資訊網——每日最新資訊28at.com

Jenkins 打包部署原理圖m2o28資訊網——每日最新資訊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 項目,所以通過流水線來部署項目的步驟如下圖所示:m2o28資訊網——每日最新資訊28at.com

流水線部署步驟流水線部署步驟m2o28資訊網——每日最新資訊28at.com

三、獲取 Gitlab 分支代碼

Pipeline 的強大之處是可以支持傳參以及獲取參數,為了讓用戶可以選擇獲取不同的分支代碼,我在 pipeline 代碼中配置了一個參數:獲取指定的 Gitlab 分支代碼。m2o28資訊網——每日最新資訊28at.com

3.1 Gitlab 分支配置

在 流水線代碼中添加 parameters 節點,指定類型為 string,配置相關的屬性。m2o28資訊網——每日最新資訊28at.com

pipeline {      parameters {          string (            name: 'GIT_BRANCH', // 參數名,后面 steps 中會用到            defaultValue: 'dev-01.30', // 默認值,會顯示在界面上,用戶可以改。            description: '請選擇部署的分支' // 說明        )    }    // 其他代碼    ...}

通過參數部分,定義了一個名為GIT_BRANCH的參數,它允許用戶在構建過程中選擇要構建的分支。默認情況下,分支被設置為dev-01.30,用戶可以選擇不同的分支。m2o28資訊網——每日最新資訊28at.com

在腳本中,這個參數可以通過params.GIT_BRANCH 獲取到。m2o28資訊網——每日最新資訊28at.com

保存配置后,需要先運行一次這個項目才能看到參數配置。如下圖所示:右邊就是參數配置。m2o28資訊網——每日最新資訊28at.com

Build with Parametersm2o28資訊網——每日最新資訊28at.com

3.2 配置環境參數

接著我們還需要定義一些常用的環境變量信息,比如 Gitlab 的倉庫地址,代碼如下所示:m2o28資訊網——每日最新資訊28at.com

pipeline {    parameters {      // 配置信息      ...    }    // 環境變量:定義 GitLab 倉庫的 URL 和分支      environment {          GIT_URL = 'https://xxx/xxx.git'             }    // 其他代碼    ...}

environment 節點為環境變量信息,GIT_URL 變量代表 Gitlab 的倉庫地址。在腳本中,這個變量可以通過${GIT_URL}使用。m2o28資訊網——每日最新資訊28at.com

3.3 獲取 Gitlab 分支代碼

接下來我們來看下如何在 pipeline 中添加一個獲取 gitlab 倉庫代碼的步驟。m2o28資訊網——每日最新資訊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 訪問m2o28資訊網——每日最新資訊28at.com

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

圖片圖片m2o28資訊網——每日最新資訊28at.com

3.4  測試 pipeline 執行

我們可以運行一下這個項目來測試 pipeline 代碼。運行結果如下圖所示,可以看到右側的階段視圖,整體耗時和每個步驟的耗時,以及每個步驟的成功與否都顯示出來了,非常直觀。m2o28資訊網——每日最新資訊28at.com

圖片圖片m2o28資訊網——每日最新資訊28at.com

四、編譯代碼

本篇主要講解的是部署 Java 項目,所以編譯項目也是采用 Maven 打包的方式。在 pipeline 腳本中執行 mvn 打包命令即可。m2o28資訊網——每日最新資訊28at.com

stage('編譯代碼') {     steps {       script {         echo "--------------- 步驟:開始編譯 --------------- "       bat 'mvn clean package'       echo "--------------- 步驟:編譯完成 --------------- "     }  }  }

核心代碼:bat 'mvn clean package'm2o28資訊網——每日最新資訊28at.com

因為我的 Jenkins 是部署在 Windows 機器上,所以執行命令用的 windows 自帶的 bat 工具來執行的。m2o28資訊網——每日最新資訊28at.com

關于 maven 工具的配置可以看之前寫的第二篇內容:m2o28資訊網——每日最新資訊28at.com

喝杯咖啡,一鍵部署完成!(建議收藏)m2o28資訊網——每日最新資訊28at.com

五、上傳 JAR 包

編譯完成后,就可以將 Jenkins 工作空間的 JAR 包上傳到服務器的 temp 目錄下。m2o28資訊網——每日最新資訊28at.com

如果你想部署指定的某些微服務,可以通過傳參的方式來上傳和更新指定的微服務。原理圖如下所示:m2o28資訊網——每日最新資訊28at.com

圖片圖片m2o28資訊網——每日最新資訊28at.com

5.1 支持勾選多個服務

為了實現可以選擇部署哪些微服務,需要安裝一個多選插件:Extended Choice Parameter。m2o28資訊網——每日最新資訊28at.com

圖片圖片m2o28資訊網——每日最新資訊28at.com

Extended Choice Parameter  插件m2o28資訊網——每日最新資訊28at.com

接下來是編寫的參數配置代碼:m2o28資訊網——每日最新資訊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 中看到配置選項:m2o28資訊網——每日最新資訊28at.com

圖片圖片m2o28資訊網——每日最新資訊28at.com

實現的效果如下圖右下角所示,可以支持多選。m2o28資訊網——每日最新資訊28at.com

圖片圖片m2o28資訊網——每日最新資訊28at.com

5.2 上傳 JAR 包

上傳需要使用 sshPublisher 插件,在第二篇文章中已介紹了。m2o28資訊網——每日最新資訊28at.com

下面上傳代碼的作用是遍歷 filesToCopy 列表中的文件,然后通過 SSH 將這些文件上傳到遠程服務器的指定目錄中。m2o28資訊網——每日最新資訊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 包路徑。m2o28資訊網——每日最新資訊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 就是用戶勾選的服務名的集合。原理圖如下所示:m2o28資訊網——每日最新資訊28at.com

備份服務器 JAR 包備份服務器 JAR 包m2o28資訊網——每日最新資訊28at.com

核心代碼如下:m2o28資訊網——每日最新資訊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 包移動到指定的備份目錄,并根據時間戳進行命名。m2o28資訊網——每日最新資訊28at.com

七、更新 JAR 包

更新最新的 JAR 包就是將最新的 JAR 包放到對應的容器映射的目錄,后面重啟容器的時候,就能用最新的 JAR 包啟動了。原理圖如下所示:m2o28資訊網——每日最新資訊28at.com

更新 JAR 包更新 JAR 包m2o28資訊網——每日最新資訊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 包移動到對應的位置,完成更新。m2o28資訊網——每日最新資訊28at.com

八、啟動多個服務

啟動服務就是將 docker swarm 管理的服務重啟下,原理圖如下所示:m2o28資訊網——每日最新資訊28at.com

圖片圖片m2o28資訊網——每日最新資訊28at.com

后端項目使用 Docker Swarm 部署的,重啟服務的命令如下:m2o28資訊網——每日最新資訊28at.com

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

我們可以編寫遠程執行這行命令的代碼,pipeline 核心代碼如下:m2o28資訊網——每日最新資訊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 連接到遠程服務器執行重啟操作,完成微服務的重啟。m2o28資訊網——每日最新資訊28at.com

最后整個執行結果如下圖所示:總共耗時 3min41s。m2o28資訊網——每日最新資訊28at.com

圖片圖片m2o28資訊網——每日最新資訊28at.com

九、總結

通過本篇的實戰內容,我們學習到了通過編寫 pipeline 代碼來實現部署后端項目。推薦大家都用 pipeline 來部署項目,好處是更加靈活。m2o28資訊網——每日最新資訊28at.com

另外本篇還沒有對 Jenkins pipeline 的版本管理,我們其實可以將 pipeline 代碼作為一個文件上傳到 Gitlab,然后通過 Jenkins 拉取最新的 jenkins pipeline 文件來執行部署,這樣更便于管理 pipeline 文件。m2o28資訊網——每日最新資訊28at.com

本文鏈接:http://www.tebozhan.com/showinfo-26-81249-0.html用代碼實現流水線部署,像詩一般優雅

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 加速 Rust 編譯時間,掌握這個技巧,速度全面提升 30 ~ 40 %

下一篇: 幾個祖傳代碼不遵守就想罵的代碼規范

標簽:
  • 熱門焦點
Top