使用ClickHouse和Terraform进行CI/CD

图片

本文字数:11047;估计阅读时间:28 分钟

审校:庄晓东(魏庄)

本文在公众号【ClickHouseInc】首发

简介

在 ClickHouse,我们致力于以 API 为先的开发方式来构建 ClickHouse Cloud。用户通过用户界面执行的每个操作都应该可以通过脚本语言执行,从而可以供其他系统利用。这意味着我们最近发布的 Cloud API 也是一个产品,具有通过 swagger 定义其行为的合同,用户可以依赖该合同。尽管我们现有的用户非常期待该 API 的发布,以满足自动化配置和取消配置、定期扩展以及灵活的配置管理等需求,但它也使我们能够开始与工具集成:首先是 Terraform。

在这篇博客文章中,我们将探讨我们的新 Terraform 提供程序以及如何使用它来解决一个常见需求:对需要针对 ClickHouse 实例进行测试的系统进行 CI/CD。作为示例,我们将介绍如何将我们的 Go 客户端测试从单体 ClickHouse Cloud 服务迁移到使用 Terraform,并仅在测试期间提供临时服务。这不仅可以帮助我们降低成本,还可以在客户端和调用之间隔离我们的测试。我们希望其他人也能从这种模式中受益,并为他们的测试基础设施带来成本节约和简化!

Terraform

Terraform 是一个由 HashiCorp 创建的开源基础设施即代码软件工具,它允许用户使用一种称为 HashiCorp 配置语言(HCL)或可选的 JSON 的声明性配置语言来定义基础设施。

基础设施即代码是通过可机器读取的定义文件而不是物理硬件配置或交互式配置工具来管理和配置计算资源的过程。这种方法已经几乎被普遍接受为管理云计算资源的手段。Terraform 作为实现这一过程的工具,已经获得了广泛的用户群和广泛的采用。

为了与 Terraform 集成并允许用户配置 ClickHouse Cloud 服务,必须实现一个提供程序插件,并且最好通过 Hashicorp 注册表提供。

身份验证

由于 ClickHouse 提供程序依赖于 ClickHouse API,因此需要认证密钥才能配置和管理服务。用户可以通过 ClickHouse Cloud 界面创建一个令牌,以及一个密钥。下面展示了这个简单的过程:

图片

用户还应该记录他们的组织 ID,如下所示。

使用提供程序

一旦令牌和密钥被创建,用户可以创建一个 .tf 文件,并声明使用提供程序。为了避免将凭据放在主文件中,token_keytoken_secret 和 organization_id 被替换为 Terraform 变量。这些变量又可以在 secret.tfvars 文件中指定,该文件不应提交到源代码控制中。

main.tf


terraform {required_providers {clickhouse = {source = "ClickHouse/clickhouse"version = "0.0.2"}}
}variable "organization_id" {type = string
}variable "token_key" {type = string
}variable "token_secret" {type = string
}provider clickhouse {environment   = "production"organization_id = var.organization_idtoken_key     = var.token_keytoken_secret  = var.token_secret
}

secret.tfvars


token_key = "<token_key>"
token_secret = "<token_secret>"
organization_id = "<organization_id>"

假设用户已安装了 Terraform,可以使用 terraform init 命令安装提供程序。


terraform initInitializing the backend...Initializing provider plugins...
- Finding clickhouse/clickhouse versions matching "0.0.2"...
- Installing clickhouse/clickhouse v0.0.2...
- Installed clickhouse/clickhouse v0.0.2 (self-signed, key ID D7089EE5C6A92ED1)Partner and community providers are signed by their developers.
If you'd like to know more about provider signing, you can read about it here:
https://www.terraform.io/docs/cli/plugins/signing.htmlTerraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.Terraform has been successfully initialized!

配置好我们的提供程序后,可以通过在上面的文件中添加几行 HCL 代码来部署 ClickHouse Cloud 服务。


variable "service_password" {type = string
}resource "clickhouse_service" "service" {name         = "example-service"cloud_provider = "aws"region       = "us-east-2"tier         = "development"idle_scaling   = truepassword  = var.service_passwordip_access = [{source    = "0.0.0.0/0"description = "Anywhere"}]
}output "CLICKHOUSE_HOST" {value = clickhouse_service.service.endpoints.0.host
}

在这里,我们指定了我们期望的云提供商、区域和层级。层级可以是开发版或生产版。开发版代表 ClickHouse Cloud 中的入门产品,适用于较小的工作负载和入门项目。对于上述示例,我们启用了 idling,这样我们的服务在未使用时不会产生费用。

启用 idling_scaling 是开发版实例的唯一有效值,即不能禁用它。提供程序的未来版本将验证此设置。

我们还必须指定一个服务名称和一个可访问此服务的 IP 地址列表(在我们的示例中是任何地方),以及服务的密码。我们再次将此抽象为我们的秘密文件中的一个变量。

我们的输出声明将我们服务的端点捕获为 CLICKHOUSE_HOST 输出变量,确保一旦服务准备就绪,获取连接详细信息就变得简单了。完整的示例 main.tf 文件可以在此处找到【https://pastila.nl/?025ef1fd/d369943908f299267b8b8d488c230380】。

通过单个命令 terraform apply 加上 -var-file 选项来传递我们的秘密文件,即可部署此服务。

terraform apply -var-file=secrets.tfvarsTerraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:+ createTerraform will perform the following actions:# clickhouse_service.service will be created+ resource "clickhouse_service" "service" {+ cloud_provider = "aws"+ endpoints    = (known after apply)+ id           = (known after apply)+ idle_scaling   = true+ ip_access    = [+ {+ description = "Anywhere"+ source    = "0.0.0.0/0"},]+ last_updated   = (known after apply)+ name         = "example-service"+ password     = (sensitive value)+ region       = "us-east-2"+ tier         = "development"}Plan: 1 to add, 0 to change, 0 to destroy.Do you want to perform these actions?Terraform will perform the actions described above.Only 'yes' will be accepted to approve.Enter a value: yesclickhouse_service.service: Creating...
clickhouse_service.service: Still creating... [10s elapsed]
clickhouse_service.service: Still creating... [20s elapsed]
clickhouse_service.service: Still creating... [30s elapsed]
clickhouse_service.service: Still creating... [40s elapsed]
clickhouse_service.service: Still creating... [50s elapsed]
clickhouse_service.service: Still creating... [1m0s elapsed]
clickhouse_service.service: Still creating... [1m10s elapsed]
clickhouse_service.service: Creation complete after 1m12s [id=fd72178b-931e-4571-a0d8-6fb1302cfd4f]Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

如上所示,Terraform根据定义构建了一个计划,然后才提供服务。由于之前配置了输出,因此也会打印分配给我们服务的主机名。可以使用 terraform destroy 命令删除上述服务。

为了使Terraform对一组资源应用更改,它需要一种获取当前状态的手段,包括已提供的资源及其配置。这在一个“状态”中描述,其中包含资源的完整描述。这允许随着时间的推移对资源进行更改,每个命令都能确定采取的适当操作。在我们的简单案例中,我们将这个状态保存在上述命令运行的文件夹中。然而,状态管理是一个更加复杂的话题,有许多维护它的方法适用于真实环境,包括使用HashiCorp的云服务。当预计会有多个个体或系统在任何给定时间操作状态并且需要并发控制时,这一点尤为重要。

 一个实际的CI/CD例子

将Terraform添加到Github操作中

针对ClickHouse Cloud进行测试对于向用户提供高质量的客户端至关重要。在Terraform提供程序可用之前,我们的ClickHouse客户端是针对ClickHouse Cloud中的单个服务进行测试的,测试由Github操作进行编排。这个实例被共享给我们的客户端,每个客户端在针对存储库进行PR或提交时都会创建自己的数据库和表。虽然这是足够的,但它也存在一些局限性:

  • 单点故障。任何与此服务相关的问题,例如由于区域可用性引起的问题,都会导致所有测试失败。

  • 资源冲突。通过确保所有资源(例如表)都遵循使用客户端名称和时间戳的命名约定来避免,但这会产生后果(见下文)。

  • 资源增长和测试复杂性。确保测试可以并行运行意味着确保特定测试使用的表、数据库和用户是唯一的,以避免冲突 - 这需要在所有客户端中保持一致的样板代码。当与需要大量测试以确保在ClickHouse中覆盖功能的客户端结合使用时,这意味着可能会创建数百个表。需要进一步的测试编排以确保每个客户端在完成时删除这些表,以避免表爆炸 - 或许并不令人意外,ClickHouse并不适用于10k个表!

  • 成本效率低。尽管上述测试的查询负载并不重大,但我们的服务实际上一直处于活动状态,并且由于大量并发的DDL操作可能导致潜在的高zookeeper负载。这意味着我们使用了生产服务。此外,我们的测试需要对服务处于空闲状态进行健壮处理,以防止服务关闭。

  • 可观察性的复杂性。随着许多客户端和多个测试的运行,使用服务器日志调试测试失败变得更加复杂。

Terraform提供程序承诺提供这些问题的简单解决方案,每个客户端只需在测试开始时创建一个服务,运行其测试套件,并在完成后销毁服务。因此,我们的测试服务变得短暂。

图片

这种方法具有许多优势:

  • 测试隔离性 - 尽管测试仍然容易受到某个区域ClickHouse Cloud不可用的影响,但已经能够抵御服务问题,例如,客户端触发ClickHouse错误导致整个服务出现问题,或者客户端测试导致整个服务的配置更改。我们的客户端测试立即得到了隔离。

  • 没有资源增长和简化的测试 - 我们的服务仅存在于测试运行的生命周期内。客户端开发人员现在只需考虑由于自己的测试并发引起的资源冲突的可能性。他们还可以对整个服务进行配置更改,从而可能简化测试。

  • 成本效率低 - 较小的(dev)服务可以创建并仅存在几分钟(在大多数情况下<10分钟),从而最大程度地减少成本。

  • 简单的可观察性 - 虽然我们在测试完成时销毁服务,但服务ID会被记录下来。如果需要,可以在我们的可观察性系统中使用它来检索服务器日志。

现有工作流程

对于我们的第一个客户端,我们选择了Clickhouse Go,使用简单的Github操作,并且在代码的测试套件中封装了大量的测试复杂性。

Github操作提供了一个基于工作流的简单CI/CD平台。与Github紧密集成,用户只需在.github/workflow目录下以yml文件的形式声明性地创建工作流,每个工作流包含要运行的作业。这些作业由步骤组成,可以配置为按计划运行或针对特定事件运行,例如PR。

现有的Cloud测试包括一个配置为针对上述单体服务运行的作业。测试套件已经支持通过环境变量CLICKHOUSE_HOSTCLICKHOUSE_PASSWORD指定要执行测试的ClickHouse实例。这些变量通过Github Secrets进行填充。这还需要将环境变量CLICKHOUSE_USE_DOCKER设置为false,以禁用现有的基于docker的测试。

除了这些特定的更改之外,云测试与基于docker的单节点测试类似 - 使用矩阵来测试客户端针对不同的go版本,并使用步骤来检出代码并在运行测试之前安装go。


integration-tests-cloud:runs-on: ubuntu-lateststrategy:max-parallel: 1fail-fast: truematrix:go:- "1.19"- "1.20"steps:- uses: actions/checkout@main- name: Install Go ${{ matrix.go }}uses: actions/setup-go@v2.1.5with:stable: falsego-version: ${{ matrix.go }}- name: Run testsenv:CLICKHOUSE_HOST: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_HOST }}CLICKHOUSE_PASSWORD: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_PASSWORD }}CLICKHOUSE_USE_DOCKER: falseCLICKHOUSE_USE_SSL: truerun: |CLICKHOUSE_DIAL_TIMEOUT=20 CLICKHOUSE_TEST_TIMEOUT=600s CLICKHOUSE_QUORUM_INSERT=3 make test

新工作流程

在迁移工作流程之前,我们需要一个简单的Terraform资源定义,用于Clickhouse服务。以下是在之前相同示例的基础上构建的,创建了一个处于开发层的服务,但引入了organization_idtoken_keytoken_secretservice_nameservice_password的变量。我们还输出了服务ID,以帮助后续调试,并允许我们的服务从任何地方都可以访问 - 由于其临时性质,安全风险很低。以下main.tf文件存储在clickhouse-go客户端的根目录中。


terraform {required_providers {clickhouse = {source = "ClickHouse/clickhouse"version = "0.0.2"}}
}variable "organization_id" {type = string
}variable "token_key" {type = string
}variable "token_secret" {type = string
}variable "service_name" {type = string
}variable "service_password" {type = string
}provider clickhouse {environment   = "production"organization_id = var.organization_idtoken_key     = var.token_keytoken_secret  = var.token_secret
}resource "clickhouse_service" "service" {name         = var.service_namecloud_provider = "aws"region       = "us-east-2"tier         = "development"idle_scaling   = truepassword  = var.service_passwordip_access = [{source    = "0.0.0.0/0"description = "Anywhere"}]
}output "CLICKHOUSE_HOST" {value = clickhouse_service.service.endpoints.0.host
}output "SERVICE_ID" {value = clickhouse_service.service.id
}

Terraform支持通过以TF_VAR_为前缀的环境变量指定变量值。例如,要填充组织ID,我们只需设置TF_VAR_organization_id

与以前的工作流程类似,这些环境变量的值可以通过Github加密密钥填充。在我们的情况下,我们在组织级别创建这些密钥,以便它们可以跨客户端和服务共享,这样可以简化管理。

图片

注意:我们在这里没有为服务名称设置值。除了不敏感之外,我们还希望确保这些名称在测试运行中是唯一的,这样我们就可以识别服务的来源和创建时间。

为了使Terraform在runner上可用,我们使用了hashicorp/setup-terraform操作。这会在Github操作CLI runner上安装Terraform,并公开其CLI,以便我们可以像从终端中一样进行调用。

我们的最终工作流如下所示:


integration-tests-cloud:runs-on: ubuntu-latestdefaults:run:shell: bashstrategy:max-parallel: 1fail-fast: truematrix:go:- "1.19"- "1.20"steps:- name: Check Out Codeuses: actions/checkout@v3- name: Setup Terraformuses: hashicorp/setup-terraform@v2.0.3with:terraform_version: 1.3.4terraform_wrapper: false- name: Terraform Initid: initrun: terraform init- name: Terraform Validateid: validaterun: terraform validate -no-color- name: Set Service Namerun: echo "TF_VAR_service_name=go_client_tests_$(date +'%Y_%m_%d_%H_%M_%S')" >> $GITHUB_ENV- name: Terraform Applyid: applyrun: terraform apply -no-color -auto-approveenv:TF_VAR_organization_id: ${{ secrets.INTEGRATIONS_TEAM_TESTS_ORGANIZATION_ID }}TF_VAR_token_key:  ${{ secrets.INTEGRATIONS_TEAM_TESTS_TOKEN_KEY }}TF_VAR_token_secret:  ${{ secrets.INTEGRATIONS_TEAM_TESTS_TOKEN_SECRET }}TF_VAR_service_password: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_PASSWORD }}- name: Set Hostrun: echo "CLICKHOUSE_HOST=$(terraform output -raw CLICKHOUSE_HOST)" >> $GITHUB_ENV- name: Service Idrun: terraform output -raw SERVICE_ID- name: Install Go ${{ matrix.go }}uses: actions/setup-go@v2.1.5with:stable: falsego-version: ${{ matrix.go }}- name: Run testsenv:CLICKHOUSE_PASSWORD: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_PASSWORD }}CLICKHOUSE_USE_DOCKER: falseCLICKHOUSE_USE_SSL: truerun: |CLICKHOUSE_DIAL_TIMEOUT=20 CLICKHOUSE_TEST_TIMEOUT=600s CLICKHOUSE_QUORUM_INSERT=2 make test- name: Cleanupif: always()run: terraform destroy -no-color -auto-approveenv:TF_VAR_organization_id: ${{ secrets.INTEGRATIONS_TEAM_TESTS_ORGANIZATION_ID }}TF_VAR_token_key:  ${{ secrets.INTEGRATIONS_TEAM_TESTS_TOKEN_KEY }}TF_VAR_token_secret:  ${{ secrets.INTEGRATIONS_TEAM_TESTS_TOKEN_SECRET }}TF_VAR_service_password: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_PASSWORD }}

总结一下,这个工作流程包括以下步骤:

  1. 通过 uses: actions/checkout@v3 将现有代码检出到runner上。

  2. 通过 uses: hashicorp/setup-terraform@v2.0.3 在runner上安装terraform。

  3. 调用 terraform init 来安装ClickHouse provider.

  4. 通过 terraform validate 命令验证已检出代码根目录中的terraform资源定义文件。

  5. 将环境变量 TF_VAR_service_name 设置为日期字符串,前缀为 go_client_tests_。这样确保我们的服务在客户端和测试运行中具有唯一的名称,并有助于调试。

  6. 运行 terraform apply 创建一个具有指定密码的Cloud服务,组织ID、令牌和密钥通过环境变量传递。

  7. 将 CLICKHOUSE_HOST 环境变量设置为前面应用步骤的输出值。

  8. 捕获服务ID以供调试目的。

  9. 基于当前的矩阵版本安装go。

  10. 运行测试 - 注意上面已设置 CLICKHOUSE_HOST。敏锐的读者会注意到我们传递环境变量使测试类似于我们之前的工作流程,以增加超时时间。但是,我们将 CLICKHOUSE_QUORUM_INSERT 降低到2。这是必需的,因为一些测试需要在查询之前在所有节点上存在数据。虽然我们之前的单体服务有三个节点,但我们较小的开发服务只有两个。

  11. 通过 terraform destroy 命令销毁服务,不管工作流是否成功(if: always())。

这些更改现在已生效!每当对存储库发出PR或提交时,更改将针对一个临时的ClickHouse Cloud集群进行测试!

图片

目前,这些测试不适用于从分支提出的PR(这需要ClickHouse组织的成员)。这是pull_request事件的标准Github策略,因为它可能导致秘密泄漏。我们计划在未来的改进中解决这个问题

结论

在本博文中,我们使用了新的Terraform提供程序为ClickHouse Cloud构建了一个CI/CD工作流,在Github actions中为测试提供临时集群。我们使用这种方法来降低在ClickHouse Cloud中进行客户端测试的成本和复杂性。

征稿启示

面向社区长期正文,文章内容包括但不限于关于 ClickHouse 的技术研究、项目实践和创新做法等。建议行文风格干货输出&图文并茂。质量合格的文章将会发布在本公众号,优秀者也有机会推荐到 ClickHouse 官网。请将文章稿件的 WORD 版本发邮件至:Tracy.Wang@clickhouse.com

图片

​​联系我们

手机号:13910395701

邮箱:Tracy.Wang@clickhouse.com

满足您所有的在线分析列式数据库管理需求

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

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

相关文章

如何快速学习盲打键盘的指法

学习盲打键盘的指法需要一定的时间和练习&#xff0c;但是以下几个方法可以帮助你加快学习的速度&#xff1a; 掌握正确的手位&#xff1a;了解标准的键盘布局以及手指应该放置的位置是学习盲打的第一步。在QWERTY键盘上&#xff0c;你的左手应该放在ASDF键上&#xff0c;右手应…

人工智能入门(一):基于Pytorch的手写数字识别模型

前言&#xff1a; 因为还在上学&#xff0c;时间不太够用&#xff0c;很多内容写到后面心有余力不足&#xff0c;未来有时间我会慢慢补充。人工智能的知识涉猎范围广又杂乱无章&#xff0c;啃书或上课学到的知识往往很早就过时了或者离实际的项目无关。所以&#xff0c;我很希…

VS调试、debug和release、栈区底层简单介绍、const 修饰指针变量介绍

文章目录 前言一、调试二、debug和release三、调试需要多用&#xff0c;多熟悉四、栈区底层简单介绍五、优秀的代码&#xff1a;常见的coding技巧: 六、const 修饰指针变量1. const 出现在 * 左边2. const 出现在 * 右边 七、strcpy函数的仿写1.版本12. 版本23. 版本34. 版本4 …

Andorid进程间通信之 UNIX SOCKET

1&#xff0c;什么是UNIX SOCKET UNIX SOCKET&#xff0c;域套接字&#xff0c;UNIX SOCKET可用于同一台设备进程间通信&#xff0c;它不需要经过网络协议栈&#xff0c;不需要打包拆包、计算校验和、维护序列号应答等&#xff0c;只需要将数据从一个进程复制到另一个进程&…

高精度加法及乘法

目录 字符串的高精度加法 为什么需要高精度加法&#xff1f; 怎么进行高精度加法&#xff1f; 链表的高精度加法 翻转链表&#xff08;带虚拟头节点&#xff09; 字符串的高精度乘法 字符串的高精度加法 大数加法_牛客题霸_牛客网 (nowcoder.com)https://www.nowcoder.co…

linux下查看前10最耗内存的进程

lunux查找占用内存前10的进程 1、使用Top命令查询进程 输入 top 命令&#xff0c;然后按下大写M按照内存MEM排序&#xff0c;按下大写P按照CPU排序。 2、查询占用CPU最高的前10个进程 ps aux|head -1;ps aux|grep -v PID|sort -rn -k 3|head 3、查询占用内存最大的前10个进程…

2024年度西安市创新联合体备案申报条件时间要求须知

一、申报条件 组建市级创新联合体需具备牵头单位、成员单位、组建协议、首席科学家等四个条件。 (一)牵头单位 1.牵头单位应为在西安市注册登记的省市产业链龙头骨干企业&#xff0c;重点支持市级重点产业链“链主”企业; 2.牵头单位一般为1家。 (二)成员单位 1.成员单位…

excel 按照姓名日期年月分组求和

excel 需要按照 姓名 日期的年份进行金额求和统计&#xff0c;采用sumifs 进行统计 注意&#xff1a;sumifs 不支持 合并列拆分计算&#xff0c;合并列只会计算一个值 表格数据大概如下&#xff1a;(sheet) ABC姓名日期金额A2023/01/01500A2023/01/151500B2023/01/01200B202…

python 调试 c++源码

1. gdb常用调试命令概览和说明 2. 编译c库设置Debug模式 cmake设置debug 在CMake中设置debug模式通常意味着启用调试信息和优化。以下是一个简单的CMakeLists.txt文件示例&#xff0c;展示了如何设置项目以便在Debug模式下构建&#xff1a; cmake_minimum_required(VERSION 3…

cad中快速计算多个矩形面积的方法

1、输入命令reg&#xff0c;选中矩形创建面域 2、输入命令uni,选中刚刚创建的面域&#xff0c;组合成一个面域 3、输入命令&#xff1a;LI &#xff0c;选中面域&#xff0c;即可查看面积和周长 需注意的一点&#xff0c;开始创建的矩形或者多段线要在一个面内&#xff0c;就是…

[沉浸式翻译]最好的网页翻译工具

沉浸式翻译 沉浸式翻译是一种翻译工具&#xff0c;它提供了多种平台的支持&#xff0c;包括桌面端的Edge、Chrome、Firefox、Safari以及移动端的iOS和Android。用户可以在这些平台上安装沉浸式翻译的插件&#xff0c;以便在浏览网页时获得翻译服务。 浏览器的安装教程 详细的…

WEB网站服务器安全漏洞扫描环境搭建及漏洞工具扫描

一、适用环境 1、企业自建有门户网站&#xff1b; 2、使用Struts框架的WEB网站&#xff1b; 3、网站服务器涉及有数据库之类的项目&#xff0c;如&#xff1a;微信登录、手机登录、充值、收费等。 4、使用安卓版、苹果版、电脑版结合的缴费类网站平台。 5、方便但需提高安全性…

排列对称串

Description:很多字串&#xff0c;有些是对称的&#xff0c;有些是不对称的&#xff0c;请将那些对称的字事按从小到大的顺序输出&#xff0c;字事先以长度论大小&#xff0c;如果长度相同&#xff0c;再以ASCI码值为大小标准 Input.输入数据中含有一些字串(1≤串长≤256)。 #…

气膜游泳馆有哪些应用优势呢?-轻空间

气膜游泳馆作为一种利用气膜技术建造的室内体育场馆&#xff0c;具有环保、节能、灵活、美观等特点&#xff0c;适合在各种气候和地形条件下使用。以下是气膜游泳馆具有的应用优势&#xff1a; 1. 全年四季恒温恒湿&#xff1a;气膜游泳馆内部设有智能化的恒温恒湿系统&#xf…

基础环境:wsl2安装Ubuntu22.04 + miniconda

服务器相关信息&#xff1a; Thinkpad p1 gen5 64G 2T 3080ti&#xff0c;自带的有nvidia-smi显卡驱动。使用wsl2安装Ubuntu22.04 miniconda目标&#xff1a;安装gpu版本的PyTorch2.1.2&#xff08;torch2.1.2/cu117 torchvision0.16.2/cu117&#xff09; 处理器 12th Gen I…

ubuntu扩展根目录磁盘空间

ubuntu扩展根目录磁盘空间 扩展虚拟机磁盘空间 查看现有磁盘状态 查询现有分区状态&#xff0c;/dev/sda是我们要扩展的磁盘 fdisk -l 开始进行磁盘空间的扩容 parted /dev/sda#扩展3号分区的空间 resizepart 3刷新分区空间 resize2fs /dev/sda3查询扩展结果&#xff0c;…

Linux安装Matlab运行时

一般而言&#xff0c;安装Matlab的linux系统是带桌面版的&#xff0c;如果没带&#xff0c;不在本教程范围内。 一、下载Matlab 下载地址&#xff1a;MATLAB Runtime - MATLAB Compiler - MATLAB 本教程使用R2020b(9.9) 二、linux系统中进行解压 将zip传入linux系统&#xf…

EigenLayer生态全解析:再质押与AVS崛起的序章

基于以太坊网络的再质押协议EigenLayer提出了利用为以太坊网络验证而质押的ETH来与其他协议共享安全性和资本效率&#xff0c;同时为协议参与者提供额外利息。在AVS、再质押、积分系统等概念的推动下&#xff0c;逐渐形成一个庞大的生态系统&#xff0c;从2024年初到现在EigenL…

使用JS代理 实现大对象的功能拆解

序言 在Android开发中&#xff0c;可以通过webView的addJavascriptInterface方法注入一个对象到网页中。但是随着开发的需求越来越多。这个对象身上的方法也越来越多。这个对象对应的java类&#xff0c;体积越来越大&#xff0c;不利于维护。为了在不影响之前代码的基础上。把…

【C++干货基地】深度理解C++中的高效内存管理方式 new delete

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 引入 哈喽各位铁汁们好啊&#xff0c;我是博主鸽芷咕《C干货基地》是由我的襄阳家乡零食基地有感而发&#xff0c;不知道各位的…