当前位置: 首页 > news >正文

etcd

etcd

etcd 是一个分布式键值对存储,设计用来可靠而快速的保存关键数据并提供访问。通过分布式锁,leader选举和写屏障(write barriers)来实现可靠的分布式协作。etcd集群是为高可用,持久性数据存储和检索而准备。

Etcd 是 CoreOS 基于 Raft 协议开发的分布式 key-value 存储,可用于服务发现、共享配置以及一致性保障(如数据库选主、分布式锁等)。

单机安装

下载地址 https://github.com/etcd-io/etcd/releases,解压后查看版本

etcd --version
etcdctl version

创建配置文件:conf.yaml

name: "hezebin-etcd"
data-dir: /usr/local/etcd/data
listen-client-urls: "http://127.0.0.1:2379"
advertise-client-urls: "http://127.0.0.1:2379"
initial-cluster-token: "hezebin-etcd-token"
initial-cluster: "hezebin-etcd=http://127.0.0.1:2380"
initial-advertise-peer-urls: "http://127.0.0.1:2380"
initial-cluster-state: "new"

启动 etcd 服务:

etcd --config-file=/usr/local/etcd/conf.yaml

打开终端,执行以下命令来检查 etcd 服务的健康状态:

etcdctl endpoint health

如果一切正常,您将看到类似以下的输出:

127.0.0.1:2379 is healthy: successfully committed proposal: took = 11.667µs

如果 etcd 服务正在运行且健康,您会收到健康状态的确认。

您还可以通过执行以下命令来查看 etcd 集群的成员状态:

etcdctl member list

这将列出 etcd 集群中的成员信息,包括成员的 ID、名称和状态。

设置键值对

etcdctl put name "hezebin"
etcdctl get name# 查询Etcd所有的key
etcdctl get --prefix ""# 只读取键 name 的值的命令
etcdctl get name --print-value-only# 以 name 为前缀的所有键的命令,结果数量限制为2:
etcdctl get --prefix --limit=2 name# 访问修订版本为 4 时的键的版本
etcdctl get --prefix --rev=4 name# 假设 etcd 集群已经有下列键:
a = 123
b = 456
z = 789
# 读取大于等于键 b 的 byte 值的键的命令:
etcdctl get --from-key b
# 清空数据
etcdctl del name
# 删除所有 n 前缀的节点
etcdctl del n -- prefix
# 删除键 zoo 并返回被删除的键值对的命令:
etcdctl del --prev-kv zoo

watch操作

watch 监测一个键值的变化,一旦键值发生更新,就会输出最新的值并退出

etcdctl watch name#更新键值
etcdctl put name "korbin"# watch 阻塞处返回结果
PUT 
name
korbin

读取键过往版本的值

应用可能想读取键的被替代的值。例如,应用可能想通过访问键的过往版本来回滚到旧的配置。或者,应用可能想通过多个请求来得到一个覆盖多个键的统一视图,而这些请求可以通过访问键历史记录而来。因为 etcd 集群上键值存储的每个修改都会增加 etcd 集群的全局修订版本,应用可以通过提供旧有的 etcd 修改版本来读取被替代的键。

假设 etcd 集群已经有下列键:

foo = bar         # revision = 2
foo1 = bar1       # revision = 3
foo = bar_new     # revision = 4
foo1 = bar1_new   # revision = 5

这里是访问键的过往版本的例子:

$ etcdctl get --prefix foo # 访问键的最新版本
foo
bar_new
foo1
bar1_new
$ etcdctl get --prefix --rev=4 foo # 访问修订版本为 4 时的键的版本
foo
bar_new
foo1
bar1
$ etcdctl get --prefix --rev=3 foo # 访问修订版本为 3 时的键的版本
foo
bar
foo1
bar1
$ etcdctl get --prefix --rev=2 foo # 访问修订版本为 2 时的键的版本
foo
bar
$ etcdctl get --prefix --rev=1 foo # 访问修订版本为 1 时的键的版本

压缩修订版本

如我们提到的,etcd 保存修订版本以便应用可以读取键的过往版本。但是,为了避免积累无限数量的历史数据,压缩过往的修订版本就变得很重要。压缩之后,etcd 删除历史修订版本,释放资源来提供未来使用。所有修订版本在压缩修订版本之前的被替代的数据将不可访问。

这是压缩修订版本的命令:

$ etcdctl compact 5
compacted revision 5
# 在压缩修订版本之前的任何修订版本都不可访问
$ etcdctl get --rev=4 foo
Error:  rpc error: code = 11 desc = etcdserver: mvcc: required revision has been compacted

注意: etcd 服务器的当前修订版本可以在任何键(存在或者不存在)以json格式使用get命令来找到。下面展示的例子中 mykey 是在 etcd 服务器中不存在的:

$ etcdctl get mykey -w=json
{"header":{"cluster_id":14841639068965178418,"member_id":10276657743932975437,"revision":15,"raft_term":4}}

lease租约(过期机制)

应用可以为 etcd 集群里面的键授予租约。当键被附加到租约时,它的存活时间被绑定到租约的存活时间,而租约的存活时间相应的被 time-to-live (TTL)管理。在租约授予时每个租约的最小TTL值由应用指定。租约的实际 TTL 值是不低于最小 TTL,由 etcd 集群选择。一旦租约的 TTL 到期,租约就过期并且所有附带的键都将被删除。

授予租约

# 授予租约,TTL为10秒
$ etcdctl lease grant 10
lease 32695410dcc0ca06 granted with TTL(10s)
# 附加键 foo 到租约32695410dcc0ca06
$ etcdctl put --lease=32695410dcc0ca06 foo barOK

应用通过租约 id 可以撤销租约。撤销租约将删除所有它附带的 key。

撤销租约

$ etcdctl lease revoke 32695410dcc0ca06
lease 32695410dcc0ca06 revoked
$ etcdctl get foo
# 空应答,因为租约撤销导致foo被删除

keepAlive续约

应用可以通过刷新键的 TTL 来维持租约,以便租约不过期。维持同一个租约的命令:

$ etcdctl lease keep-alive 32695410dcc0ca06
lease 32695410dcc0ca06 keepalived with TTL(10)
lease 32695410dcc0ca06 keepalived with TTL(10)
lease 32695410dcc0ca06 keepalived with TTL(10)
...

获取租约信息

应用程序可能想知道租约信息,以便可以更新或检查租约是否仍然存在或已过期。应用程序也可能想知道有那些键附加到了特定租约。

获取租约信息的命令:

$ etcdctl lease timetolive 694d5765fc71500b
lease 694d5765fc71500b granted with TTL(500s), remaining(258s)

获取租约信息和租约附带的键的命令:

$ etcdctl lease timetolive --keys 694d5765fc71500b
lease 694d5765fc71500b granted with TTL(500s), remaining(132s), attached keys([zoo2 zoo1])
# 如果租约已经过期或者不存在,它将给出下面的应答:
Error:  etcdserver: requested lease not found

事务

etcd 的事务(Transaction)机制允许你在一个原子操作中执行一系列操作,这些操作要么全部成功,要么全部失败,确保数据的一致性和完整性。

etcdctl txn 并没有对事务提供过多的支持,执行事务最好通过 go 来实现:

go get go.etcd.io/etcd/client/v3
package mainimport ("context""fmt""log""time""go.etcd.io/etcd/clientv3"
)func main() {// 创建 etcd 客户端cli, err := clientv3.New(clientv3.Config{Endpoints:   []string{"http://localhost:2379"}, // 替换为你的 etcd 地址DialTimeout: 5 * time.Second,})if err != nil {log.Fatal(err)}defer cli.Close()// 创建一个 etcd 事务etcdTxn := clientv3.NewKV(cli).Txn(context.Background())// 定义事务的比较和操作etcdTxn.If(clientv3.Compare(clientv3.Value("my_key"), "=", "10"),).Then(clientv3.OpPut("my_key", "20"),).Else(clientv3.OpPut("my_key", "30"),)// 提交事务txnResp, err := etcdTxn.Commit()if err != nil {log.Fatal(err)}// 检查事务是否成功if !txnResp.Succeeded {fmt.Println("Transaction failed")} else {fmt.Println("Transaction succeeded")}
}

注意:etcdTxn.If 中指定的条件是 clientv3.Compare(clientv3.Value("my_key"), "=", "10"),也就是检查键 “my_key” 的值是否等于 “10”。如果这个条件不满足(例如,键 “my_key” 的值为空),那么事务的 Else 分支会执行,而且整个事务会被标记为失败。

基于etcd实现分布式锁

原生实现

要在 etcd 中实现分布式锁,你可以利用 etcd 的事务特性和租约(Lease)机制。以下是一个使用 etcd 实现分布式锁的示例:

# 伪代码,etcdctl 并不支持下述命令,需要以 go 方式实现,api 更丰富
etcdctl txn -- \put my_lock some_value  --lease=0d7689bc575d6611  \if_not_exists# if_not_exists: 这是一个条件,表示只有在键不存在时才执行上述的 put 操作。这个条件确保只有第一次创建节点的时候才会成功,从而实现锁的获取。

这个命令的目的是在一个 etcd 事务中,尝试创建一个指定键名的键值对,如果该键名在 etcd 中尚不存在(即尝试获取锁),则创建成功,否则操作失败。这个操作模式可以帮助实现分布式锁的基本机制。

Go 代码实现:

package mainimport ("context""fmt""log""time""go.etcd.io/etcd/clientv3"
)func main() {// 创建 etcd 客户端cli, err := clientv3.New(clientv3.Config{Endpoints:   []string{"http://localhost:2379"}, // 替换为你的 etcd 地址DialTimeout: 5 * time.Second,})if err != nil {log.Fatal(err)}defer cli.Close()// 创建租约leaseResp, err := cli.Grant(context.Background(), 10) // 10 秒的租约时间if err != nil {log.Fatal(err)}// 锁的键名lockKey := "my_lock"// 尝试获取锁txnResp, err := cli.Txn(context.Background()).If(clientv3.Compare(clientv3.CreateRevision(lockKey), "=", 0)).Then(clientv3.OpPut(lockKey, "lock_holder", clientv3.WithLease(leaseResp.ID))).Commit()if err != nil {log.Fatal(err)}// 检查是否成功获取锁if !txnResp.Succeeded {log.Println("Failed to acquire lock")return}log.Println("Lock acquired")// 续约循环(保持锁)keepAliveCh, err := cli.KeepAlive(context.Background(), leaseResp.ID)if err != nil {log.Fatal(err)}go func() {for range keepAliveCh {// 续约成功,执行你的逻辑,或者也可以不做任何处理}}()// 在这里执行需要保护的临界区代码// 释放锁(取消续约)_, err = cli.Revoke(context.Background(), leaseResp.ID)if err != nil {log.Fatal(err)}log.Println("Lock released")
}

官方 concurrency 包实现

cli, err := clientv3.New(clientv3.Config{Endpoints: endpoints})
if err != nil {log.Fatal(err)
}
defer cli.Close()// 创建两个单独的会话用来演示锁竞争
s1, err := concurrency.NewSession(cli)
if err != nil {log.Fatal(err)
}
defer s1.Close()
m1 := concurrency.NewMutex(s1, "/my-lock/")s2, err := concurrency.NewSession(cli)
if err != nil {log.Fatal(err)
}
defer s2.Close()
m2 := concurrency.NewMutex(s2, "/my-lock/")// 会话s1获取锁
if err := m1.Lock(context.TODO()); err != nil {log.Fatal(err)
}
fmt.Println("acquired lock for s1")m2Locked := make(chan struct{})
go func() {defer close(m2Locked)// 等待直到会话s1释放了/my-lock/的锁if err := m2.Lock(context.TODO()); err != nil {log.Fatal(err)}
}()if err := m1.Unlock(context.TODO()); err != nil {log.Fatal(err)
}
fmt.Println("released lock for s1")<-m2Locked
fmt.Println("acquired lock for s2")

通过源码可以发现concurrency包的实现原理为执行一个 key 的前缀,并在最终设置到 etcd key 的尾部拼接上 /lease_id,租约为 60 秒,且每隔 20 秒续租一次。

在 tryAcquire 函数中通过 put 上述的键值,判断版本号,若设置成功则拿到锁,否则阻塞等待锁:
在这里插入图片描述

阻塞期间先通过查询一次 key 是否存在判断是否阻塞,若不存在表示拿到锁,结束阻塞;存在则通过 watch 监听 key 的变更,仅允许DELETE类型,其他变更操作会报错,并做强制解锁。
在这里插入图片描述
在这里插入图片描述

服务注册与发现

当使用 etcd 实现服务注册与发现时,通常需要以下步骤:

  1. 引入 etcd 的 Go 客户端库
  2. 连接到 etcd 服务器
  3. 注册服务:将服务的信息写入 etcd 中
  4. 发现服务:从 etcd 中获取已注册的服务信息

以下是一个简单示例,演示如何使用 Go 语言操作 etcd 实现基本的服务注册与发现功能。请确保已经安装了 etcd 并启动了 etcd 服务器。

package mainimport ("context""fmt""log""time""go.etcd.io/etcd/clientv3"
)func main() {// 创建 etcd 客户端cli, err := clientv3.New(clientv3.Config{Endpoints:   []string{"localhost:2379"}, // etcd 服务器地址DialTimeout: 5 * time.Second,})if err != nil {log.Fatal(err)}defer cli.Close()// 注册服务serviceName := "my-service"serviceIP := "192.168.1.100"servicePort := "8080"serviceKey := fmt.Sprintf("/services/%s/%s:%s", serviceName, serviceIP, servicePort)serviceValue := "some-metadata-about-the-service"ctx := context.Background()_, err = cli.Put(ctx, serviceKey, serviceValue)if err != nil {log.Fatal(err)}fmt.Printf("Service registered: %s\n", serviceKey)// 发现服务discoveryKey := fmt.Sprintf("/services/%s", serviceName)resp, err := cli.Get(ctx, discoveryKey, clientv3.WithPrefix())if err != nil {log.Fatal(err)}fmt.Println("Discovered services:")for _, kv := range resp.Kvs {fmt.Printf("Key: %s, Value: %s\n", kv.Key, kv.Value)}
}

可以结合 watch 机制优化更新服务变更。

Go 操作 Etcd 参考

go get go.etcd.io/etcd/client/v3
  • 民间文档:http://www.topgoer.com/%E6%95%B0%E6%8D%AE%E5%BA%93%E6%93%8D%E4%BD%9C/go%E6%93%8D%E4%BD%9Cetcd/%E6%93%8D%E4%BD%9Cetcd.html

  • 官方文档:https://github.com/etcd-io/etcd/blob/main/client/v3/README.md

相关文章:

etcd

文章目录 etcd单机安装设置键值对watch操作读取键过往版本的值压缩修订版本lease租约&#xff08;过期机制&#xff09;授予租约撤销租约keepAlive续约获取租约信息 事务基于etcd实现分布式锁原生实现官方 concurrency 包实现 服务注册与发现Go 操作 Etcd 参考 etcd etcd 是一…...

W5500-EVB-PICO做DNS Client进行域名解析(四)

前言 在上一章节中我们用W5500-EVB-PICO通过dhcp获取ip地址&#xff08;网关&#xff0c;子网掩码&#xff0c;dns服务器&#xff09;等信息&#xff0c;给我们的开发板配置网络信息&#xff0c;成功的接入网络中&#xff0c;那么本章将教大家如何让我们的开发板进行DNS域名解析…...

单例模式(C++)

定义 保证一个类仅有一个实例&#xff0c;并提供一个该实例的全局访问点。 应用场景 在软件系统中&#xff0c;经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例&#xff0c;才能确保它们的逻辑正确性、以及良好的效率。如何绕过常规的构造器&#xff0c;提供一种…...

LeetCode 热题 100 JavaScript--234. 回文链表

function ListNode(val, next) {this.val val undefined ? 0 : val;this.next next undefined ? null : next; }var isPalindrome function (head) {if (!head || !head.next) {return true; }// 使用快慢指针法找到链表的中间节点let slow head;let fast head;while …...

Redis 6.5 服务端开启多线程源码

redis支持开启多线程&#xff0c;只有从socket到读取缓冲区和从输出缓冲区到socket这两段过程是多线程&#xff0c;而命令的执行还是单线程&#xff0c;并且是由主线程执行 借鉴&#xff1a;【Redis】事件驱动框架源码分析&#xff08;多线程&#xff09; 一、main启动时初始化…...

嵌入式面试笔试刷题(day6)

文章目录 前言一、进程和线程的区别二、共享内存的原理三、中断有传参和返回值吗四、串口数据帧格式五、进程通信有几种&#xff0c;哪几种需要借助内核1.方式2.需要借助内核的 六、flash有哪几种类型七、指针的本质是什么八、指针和数组的区别九、使用宏定义交换变量不能使用中…...

24考研数据结构-第五章:树与二叉树

目录 第五章&#xff1a;树5.1树的基本概念5.1.1树的定义5.1.2 基本术语5.1.3 树的性质 5.2二叉树的概念5.2.1 二叉树的定义与特性5.2.2 几种特殊的二叉树5.2.3 二叉树的性质5.2.4 完全二叉树的性质5.2.5 二叉树的存储结构1. 顺序存储重要的基本操作非完全二叉树2. 链式存储逆向…...

构建稳健的微服务架构:关键的微服务设计原则和最佳实践

在现代软件开发中&#xff0c;微服务架构正逐渐成为构建复杂应用程序的首选方法之一。微服务架构的核心理念是将应用程序划分为一系列小型、自治的服务&#xff0c;每个服务专注于一个特定的业务功能。然而&#xff0c;要实现一个稳健的微服务架构并不仅仅是将功能拆分成微服务…...

消息队列常见问题(1)-如何保障不丢消息

目录 1. 为什么消息队列会丢消息&#xff1f; 2. 怎么保障消息可靠传递&#xff1f; 2.1 生产者不丢消息 2.2 服务端不丢消息 2.3 消费者不丢消息 3. 消息丢失如何快速止损&#xff1f; 3.1 完善监控 3.2 完善止损工具 1. 为什么消息队列会丢消息&#xff1f; 现在主流…...

Circle of Mistery 2023牛客暑期多校训练营5 B

登录—专业IT笔试面试备考平台_牛客网 题目大意&#xff1a;给出一个n个数的数组a&#xff0c;求一个排列&#xff0c;使其形成的其中一个置换环上的数的和>k&#xff0c;并使产生的逆序对数量最少 1<n<1e3;-1e6<k<1e6;-1e6<ai<1e6 tips:关于置换环是什…...

VC9、VC10、VC11等等各对应什么版本的Visual Studio,以及含义

文章目录 1、_MSC_VER 定义编译器的版本2、示例 1、_MSC_VER 定义编译器的版本 MS VC 15.0 _MSC_VER 1910 (Visual Studio 2017) MS VC 14.0 _MSC_VER 1900 (Visual Studio 2015) MS VC 12.0 _MSC_VER 1800 (VisualStudio 2013) MS VC 11.0 _MSC_VER 1700 (VisualStudio…...

两数相加 LeetCode热题100

题目 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外&#xff0c;这两个数都不会…...

Python基础 P2数字类型与优先级进阶练习

文章目录 Python基础 P2数字类型与优先级进阶练习1.闰年判断器2.进制转换及求和3.单位转换 Python基础 P2数字类型与优先级进阶练习 1.闰年判断器 简介 对于闰年的判断就是判断输入的内容类型是否符合要求&#xff0c;然后通过逻辑判断和运算得出该年份是否为闰年 举个栗子 …...

CAPL通过继电器实现CAN容错性自动化测试

系列文章目录 文章目录 系列文章目录前言一、环境搭建1.硬件环境2.软件环境3.继电器线路连接图:二、容错性测试方法1.CAN_H与CAN_L短路2.CAN_H与GND短路3.CAN_L与GND短路4.CAN_H与电源短路5.CAN_L与电源短路6.CAN_H断路7.CAN_L断路三、CAPL自动化测试1.测试用例目录2.测试报告…...

elasticsearch 配置用户名和密码

无密码的其他配置项在&#xff1a;https://blog.csdn.net/Xeon_CC/article/details/132064295 elasticsearch.yml配置文件&#xff1a; xpack.security.enabled: true xpack.security.http.ssl.enabled: true xpack.security.http.ssl.keystore.path: /path/to/elastic-certi…...

侯捷 C++面向对象编程笔记——9 复合 委托

9 复合 委托 9.1 Composition 复合 类似于c中结构里有结构——class里有class deque 是一个已经存在的功能很多的类&#xff08;两头进出的队列&#xff09;&#xff1b;利用deque的功能来实现queue的多种操作 该例只是复合的一种情况——设计模式 Adapter 9.1.1 复合下的构造…...

状态模式——对象状态及其转换

1、简介 1.1、概述 在软件系统中&#xff0c;有些对象也像水一样具有多种状态&#xff0c;这些状态在某些情况下能够相互转换&#xff0c;而且对象在不同的状态下也将具有不同的行为。为了更好地对这些具有多种状态的对象进行设计&#xff0c;可以使用一种被称为状态模式的设…...

Linux一阶段复习

Linux之父是林纳斯本纳第克特托瓦兹 Apache发布目录&#xff1a;/var/www/html nginx发布目录&#xff1a;/usr/share/nginx/html/ 配置dns的文件 &#xff1a; /etc/resolv.conf nginx的配置文件&#xff1a;/etc/nginx/ yum源的配置文件&#xff1a;/etc/yum.repos.d/ …...

宝塔Linux面板怎么升级?升级命令及失败解决方法

宝塔Linux面板怎么升级到新版本&#xff1f;root账号ssh登录到云服务器后&#xff0c;执行宝塔Linux面板升级命令即可搞定&#xff0c;新手站长分享宝塔Linux面板升级命令&#xff1a; 宝塔面板升级到新版本 1、使用root账号ssh登录到云服务器上 ssh root你的云服务器ip地址…...

前端面试的性能优化部分(6)每天10个小知识点

目录 系列文章目录前端面试的性能优化部分&#xff08;1&#xff09;每天10个小知识点前端面试的性能优化部分&#xff08;2&#xff09;每天10个小知识点前端面试的性能优化部分&#xff08;3&#xff09;每天10个小知识点前端面试的性能优化部分&#xff08;4&#xff09;每天…...

2023年 Java 面试八股文(20w字)

目录 第一章-Java基础篇 1、你是怎样理解OOP面向对象 难度系数&#xff1a;⭐ 2、重载与重写区别 难度系数&#xff1a;⭐ 3、接口与抽象类的区别 难度系数&#xff1a;⭐ 4、深拷贝与浅拷贝的理解 难度系数&#xff1a;⭐ 5、sleep和wait区别 难度系数&a…...

银河麒麟服务器ky10-server在线一键安装docker

脚本代码 # ---------------在线安装docker------------------- yum install docker -y # 修改docker拉取源为国内 rm -rf /etc/docker mkdir -p /etc/docker touch /etc/docker/daemon.json cat >/etc/docker/daemon.json<<EOF{"registry-mirrors": [&q…...

spring boot中web容器配置

web容器配置 spring boot 默认的web容器是 tomcat&#xff0c;如果需要换成其他的 web 容器&#xff0c;可以如下配置。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><!-- 默…...

DNSlog注入(利用DNSlog平台将SQL盲注变成回显注入)

前言什么是UNC什么是DNSlog注入DNSlog注入的条件防止DNSlog注入的几个措施 sqli-labs试验 前言 前几天面试的时候&#xff0c;面试官问我知不知道OOB&#xff08;带外数据&#xff09;。 当时我蒙了&#xff0c;确实没听说过这个东西&#xff0c;然后面试官告诉我原来dnslog注入…...

vim学习笔记(致敬vim作者)

vim cheat sheet 30. vim 删除大法 vim 删除某个字符之后改行的其他的字符&#xff1f;删除某行之后的其他行&#xff1f;删除某个字符之后的其他字符&#xff1f;【1】删除单个字符&#xff1f; 跳到要删除的字符位置 按下d键然后按下shift 4键 【2】删除某行之后的其他行…...

力扣 -- 139. 单词拆分

一、题目 题目链接&#xff1a;139. 单词拆分 - 力扣&#xff08;LeetCode&#xff09; 二、解题步骤 下面是用动态规划的思想解决这道题的过程&#xff0c;相信各位小伙伴都能看懂并且掌握这道经典的动规题目滴。 三、参考代码 class Solution { public:bool wordBreak(str…...

百度秋招攻略,百度网申笔试面试详解

百度秋招简介 作为行业巨头&#xff0c;百度向社会提供的岗位一直都是非常吃香的&#xff0c;每年也都有很多考生密切关注&#xff0c;百度发布的招聘广告&#xff0c;以尽可能的让自己进入这家企业工作&#xff0c;实现自己的人生价值。那么百度每年的秋招时间是多久&#xf…...

nohup Java -jar 生成的nohup.out 文件一直增加,如何处理

目录 1 实现 1 实现 除了使用echo "" > filename清空文件内容之外&#xff0c;还有其他几种方法可以删除文件中的内容而不删除文件本身&#xff1a;使用truncate命令&#xff1a;truncate命令可以用来截断文件并清空内容。使用以下命令清空文件内容&#xff1a;t…...

静态页面与动态页面的区别及部署jpress应用

简述静态网页和动态网页的区别 静态网页&#xff1a; 1、首先是静态网页&#xff0c;静态网页每个网页中都有一个固定的URL&#xff0c;网页URL以htm、HTML、jpg、.gif、.mp4等常见形式为后缀&#xff0c;而且不含有问号&#xff1b; 2、静态网页内容一经发布到网页服务器上…...

华为数通HCIA-华为VRP系统基础

什么是VRP? VRP是华为公司数据通信产品的通用操作系统平台&#xff0c;作为华为公司从低端到核心的全系列路由器、以太网交换机、业务网关等产品的软件核心引擎。 VRP提供以下功能&#xff1a; 实现统一的用户界面和管理界面 实现控制平面功能&#xff0c;并定义转发平面接口…...