彻底搞懂 Zookeeper,吊打大厂面试官
nanshan 2024-10-22 12:54 20 浏览 0 评论
ZooKeeper 是什么?
ZooKeeper 是一个基于 Java 语言开发的,开源,高可用,服务于其他分布式服务产品的一款服务注册与发现的工具。属于 Apache 基金会的一款产品。logo 是一个矿工。
官网地址:https://zookeeper.apache.org/
注:本文篇幅较长,大家按章节阅读。
ZooKeeper 应用场景详解?
服务注册与发现
ZooKeeper 有很多优良的特性,如自动选举、观察者模式、有序无序节点等。这些特性为服务的注册与发现提供了优质可靠的服务。
服务注册
先说一说 ZooKeeper 作为服务的注册中心,ZooKeeper 的存储结构是类似于 Linux 文件系统的树形存储结构。每个节点都可以存储一些少量的数据信息,我们服务启动时,可以创建 ZooKeeper 临时有序节点用于存储服务所注册的信息,如服务 IP、服务端口、服务的全类名、方法签名等等,为后续服务发现提供便利。
服务发现
服务发现相对比较简单,我们只需要连上 ZooKeeper 注册中心就可以监听我们注册的服务信息,当注册的服务发生变更时,我们也能够及时感知。当需要服务调用时,只需要读取对应节点中的服务信息,然后使用 RPC 框架发起远程调用即可。
服务上下线
ZooKeeper 的数据节点分为持久节点和临时节点,临时节点是当客户端断开连接时,则会删除该节点。此特性正好可以用于我们服务的动态上下线,当服务上线时,创建一个临时有序节点,当我们下线时,ZooKeeper 会自动删除这个节点,并通知其他客户端观察者节点的变更信息。如此我们就实现了服务的动态上下线。是不是非常简单呢。
服务软负载
当一个服务压力较大时,我们第一时间的想法一般是横向拓展,多部署几台服务器对外提供服务,从而产生了一个服务集群。那么这个服务集群每个服务之间的情况是有差异的,会引发一些问题:每台服务器网络延迟不同,单位时间内处理的请求次数不同等等。使用 ZooKeeper 则可以完美的化解这个问题,开发者可自主定制多套软负载均衡策略,可以使用不同的策略让服务集群中的服务合理的处理请求。
实现案例:https://segmentfault.com/a/1190000012185401
分布式锁
在分布式微服务系统中,一个应用会切分为多个服务部署到多台服务器当中,那么业务中的锁就只能锁住当前服务器运行的实例,而不能管控到其他服务器上的实例。那么这种情况下,上锁显然是会有问题的,例如 A 和 B 是部署在不同服务器的相同服务,服务 A 需要更改数据库中的某条记录,加锁;此时服务 B 也需要更改同一条记录,也加锁,那么 A 和 B 都加锁解锁成功,但是记录已被修改了两次,导致数据不一致。
那么多个服务想要锁住某块业务逻辑,势必需要使用同一把锁,进行统一的加锁和解锁。
ZooKeeper 不依赖服务,属于独立的注册中心,集群可靠性和容错性高。当应用获取锁时,在 ZooKeeper 中创建一个临时带序号节点,判断该节点是否时序号最小的临时节点,如果是则成功获取锁,如果不是则监听前一个节点是否释放。直到自己创建的节点成为带序号的最小节点,则获取到锁。释放锁时,删除该临时节点即可。
ZooKeeper 锁框架——Curator
自己使用 ZooKeeper 编写分布式锁可能会有一些考虑不太全面的问题,Apache Curator 是以 ZooKeeper 为基础开发的分布式锁框架,拥有一套完整的分布式锁解决方案。Curator 使用极其简单,具体操作步骤请继续向下阅读。
Apache Curator
官网:http://curator.apache.org/
快速使用:前提是搭建好 ZooKeeper 环境。
1. 从 Maven 仓库中下载对应依赖。
2. 创建一个 ZooKeeper 连接:
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3)
CuratorFramework client = CuratorFrameworkFactory.newClient(zookeeperConnectionString, retryPolicy);
client.start();
3. 创建一个锁节点:
client.create().forPath("/my/path", myData)
4. 使用分布式锁:
// 获取锁
InterProcessMutex lock = new InterProcessMutex(client, lockPath);
// 上锁, 设置自动解锁时间, 避免死锁
if (lock.acquire(maxWait, waitUnit)) {
try {
// 被锁住的业务
}finally {
// 最终解锁
lock.release();
}
}
ZooKeeper 安装与启动
安装
环境
需要提前准备好 JDK 环境,不会的可以百度安装,本文不再赘述。
版本
提供的是压缩文件,各类系统均可使用。
下载
官方下载:https://zookeeper.apache.org/releases.html
找到想要下载的版本即可,官方默认是 Linux 版本,修改些配置 Win 也可以使用!
下载速度受网速影响,服务器架设在国外因此速度很慢,耐心等待即可。
解压
Linux:使用 FTP 工具,上传到 Linux 服务器,使用 tar -zxvf zookeeper-3.4.7.tar.gz 解压到当前文件夹。
Windows:使用解压工具,作者使用的时 7-zip,需要解压两次,第一次解压为 zookeeper-3.4.7.tar 文件夹,然后进入文件夹,第二次解压 zookeeper-3.4.7.tar 压缩包得到 zookeeper-3.4.7 文件夹。
解压后的目录如下:
启动
配置
刚下载下来的 ZooKeeper 直接启动是会报错的,因此我们下载下来第一步就是要先修改一下配置文件。进入上图的目录下,我们常用的就是 bin 和 conf,进入 conf 目录下:
1. 先复制一份 zoo_sample.cfg,命名为 zoo_bk.cfg,避免以后我们改乱了配置文件没有备份。
2. 将 zoo_samplle.cfg 重命名为 zoo.cfg。
3. 修改配置:
# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
dataDir=/tmp/zookeeper
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
一共有五个配置项。
tickTime
通信心跳时间,客户端与服务器的心跳时间,单位:毫秒。
initLimit
leader 和 follower 初始通信时限,即在 10*2000 毫秒内,没有连接上,则认为此次通信失败。
syncLimit
leader 和 follower 同步通信时限,即建立连接后,如果通信时间超过 5*2000 毫秒,则 leader 判定此 follower 挂了。
dataDir
数据存储路径,Windows 修改为你的自定义路径。Linux 切记切记一定要修改为你自己定义的路径,因为默认的路径是 /tmp/zookeeper,当服务器磁盘空间不够时会优先清理 tmp,导致数据丢失。
clientPort
客户端端口,默认 2181。
我们修改一下 dataDir 即可,其他的可以使用默认值,生产环境按照需求配置即可。以下是完整配置:
# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
dataDir=D:/tmp/zookeeper
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
启动
进入 bin 目录,我们可以看到一些脚本,cmd 为 Windows 系统使用,sh 为 Linux 系统使用。
双击启动 zkServer.cmd,发现无响应,使用 cmd 运行,发现报错了,原因是 JAVA_HOME 的路径有问题!
包含路径包含空格,修改一下 JAVA_HOME,使用 " 号将有空格的路径括起来(注意要用英文引号),改为如下图所示:
再次启动,如下图显示,成功!
验证
使用 ZK 客户端连接一下,双击 zkCli.cmd 输入命令:get /,查询根节点成功,验证成功!
ZooKeeper 集群搭建
集群安装多少节点合适?
服务器越多,难道每一台都安装上 ZooKeeper 吗?其实不是的,ZooKeeper 是半数投票表决机制,无论什么操作,只要 leader 发起提案,需要获取超过半数节点的选票才能通过。因此集群节点一般为基数个,如 3、5、7、9。假设有 5 台服务器,那么 3 台安装 ZooKeeper,或者 5 台全部安装 ZooKeeper 都可以。假设有 50 台服务器呢?注意,ZooKeeper 上限推荐为 11 台服务器,因为半数投票机制,需要对所有节点通信,服务器越多则通信代价越大,并不是越多越好。
我们假定我们需要搭建的集群为 3 个节点。
多节点安装
参照上一节,将压缩包上传至 Linux 服务器,解压压缩包,备份配置文件。详细配置放在后面,先别修改配置。
演示安装目录:/opt/module/zookeeper。
创建数据存储目录
我们创建一个数据存储目录 /opt/module/zookeeper/zkData,用于存储数据。和 bin 目录,conf 目录同级。
配置服务器编号
在 /opt/module/zookeeper/zkData 下创建一个 myid 文件(建议在 Linux 系统下创建)。vi myid 写入编号,节点 1 写 1,节点 2 写 2,节点 3 写 3。只需要写一个数字即可,其他什么都不要!此编号用于标识 ZooKeeper 节点,后续会有说明。
配置 zoo.cfg
dataDir=/opt/module/zookeeper/zkData
增加如下配置:
################################## Cluster ############################
server.1=1 号服务器 ip:2888:3888
server.2=2 号服务器 ip:2888:3888
server.3=3 号服务器 ip:2888:3888
配置参数解读:server.A=B:C:D
- A 表示第几号服务器
- B 表示服务器地址
- C leader 和 follower 通信端口号
- D 选举端口
启动集群
进入 ZooKeeper 的 bin 目录下,执行 ./zkServer.sh start 启动 ZooKeeper 服务器。3 台服务器依次启动,使用 ./zkServer.sh status 查看是否启动成功,看到 STARTED 则表示启动成功。
ZooKeeper 选举策略详解
ZooKeeper 第一次选举
ZooKeeper 的第一次选举比较特殊,涉及的东西有些复杂,我画了大量的图来说清楚,加深大家的理解。
第一台服务器启动
ZooKeeper 集群中,一共有 3 台服务器,此时我们启动编号为 1 的 ZK 服务器,服务器启动后先投自己一票,然后发现没有其他节点且选票不够半数,则进入等待阶段。
第二台服务器启动
编号为 2 的服务器启动,首先投自己一票。然后服务器 1 和服务器 2 交换选票,服务器 1 发现自己的 myid 小于服务器 2 的 myid,则把自己的选票给服务器 2,服务器 2 获得半数投票成为 leader。
第 3 台服务器启动
编号为 3 的服务器启动,发现已经存在 leader,自动变为 follower。
至此,第一次 leader 的选举完成。
ZXID、SID、EPOCH 说明:
- ZXID 每一次写操作的事务 ID
- SID 每一台服务器的 ID,不能重复,和 myid 一致
- EPOCH 每个 leader 的任期代号,每次一次选举就会增加
ZooKeeper 非第一次选举
选举时机
当发生以下两种情况会选举:
- 服务器集群第一次启动
- 当无法与 leader 连接时
当服务器进入 leader 选举流程时也会出现两种情况:
- 集群中有 leader 存在
- 集群中 leader 确实挂了
如果集群中存在 leader,机器尝试取选举 leader 时,会被告知当前集群中的 leader 信息。只需要同步信息即可 如果集群中不存在 leader, 则需要进行真正的选举。
开始选举
选举涉及 ZIXD,SID,EPOCH,我们假设 3 个节点的集群,编号为 1,2,3。我们假设 2 是 leader,且已经挂了,那么剩下的 1 和 3 则需要开始选举。
假设 leader 挂之前,1 号节点(EPOCH=1, ZXID=4, SID=1),2 号节点(EPOCH=1, ZXID=4, SID=2),3 号节点(EPOCH=1, ZXID=3, SID=3)。
现在 1 号和 3 号发起选举。
选举原则
- EPOCH 任期 ID 谁大谁胜出
- EPOCH 相同,ZXID 事务 ID 谁大谁胜出
- ZXID 相同,SID 谁大谁胜出
根据这个原则,我们看 1 号和 3 号,EPOCH 相同,1 号 ZXID 事务 ID 大于 3 号事务 ID,1 号成为 Leader。
ZooKeeper 选举原理剖析
说到原理,又要回到起点,也就是 ZooKeeper 的中心思想,这里涉及 Paxos 算法和 ZAB 协议,作者尽量说明白。
Paxos 算法
Paxos 算法是什么?
Paxos 算法是一种基于消息传递且具有高度容错性的一致性算法。也就是说,Paxos 算法是用于保证一致性的。
Paxos 算法解决什么问题?
就是如何快速正确的在一个分布式系统中对某个数据值达成一致,并保证不论发生任何异常,都不会破坏整个系统的一致性。
在一个 Paxos 系统中,首先会将节点划分为 Proposer(提议者)、Acceptor(接受者)、Learner(学习者)。每个节点都可以身兼数职。
Paxos 算法流程
Prepare 准备阶段
Proposer 向多个 Acceptor 发出 Propose 请求 Promise(承诺) Acceptor 针对收到的 Propose 请求进行 Promise(承诺)。
Accept 接受阶段
Proposer 收到多数 Acceptor 承诺的 Promise 后,向 Acceptor 发出 Propose 请求,Acceptor 针对收到的 Propose 请求进行 Accept 处理。
Learn 学习阶段
Propose 将形成的决议发给所有的 Learners。
Paxos 算法流程图
Paxos 算法改进
当一场决议中,如果存在多个 Propose(提议者)且争相抢夺 Accept,导致提议迟迟达不到一致。针对这种情况,一种改进的 Paxos 算法提出:从系统中选举出一个 leader,只有 leader 才能够发起提案。
ZAB 协议
ZAB 算法借鉴了 Paxos 算法,并对 Paxos 进行了改进,是特别为 ZooKeeper 设计的支持崩溃回复的原子广播协议。基于该协议,一个集群中只有一个 Leader,其余均是 Follower,只有 Leader 能够发起提案。
协议内容
- 消息广播
- 崩溃恢复
消息广播
崩溃恢复
重新选举
一旦 leader 崩溃,则需要重新选举 leader,ZAB 协议原则如下:
- 含有未提交的提案的节点,不能参与 leader 选举
- leader 节点必须包含最大的事务 ID,即 ZXID
- 新节点成为 leader 后,必须先确认事务日志中的提案已被半数的 follwer 提交
- leader 确保事务日志中的所有提案都和 follower 同步完成后,才会将 follwer 加入可用的 follwer 列表中
实战操作 ZooKeeper
ZooKeeper 常用命令
[zkshell: 0] help
ZooKeeper -server host:port cmd args
addauth scheme auth
close
config [-c] [-w] [-s]
connect host:port
create [-s] [-e] [-c] [-t ttl] path [data] [acl]
delete [-v version] path
deleteall path
delquota [-n|-b] path
get [-s] [-w] path
getAcl [-s] path
getAllChildrenNumber path
getEphemerals path
history
listquota path
ls [-s] [-w] [-R] path
ls2 path [watch]
printwatches on|off
quit
reconfig [-s] [-v version] [[-file path] | [-members serverID=host:port1:port2;port3[,...]*]] | [-add serverId=host:port1:port2;port3[,...]]* [-remove serverId[,...]*]
redo cmdno
removewatches path [-c|-d|-a] [-l]
rmr path
set [-s] [-v version] path data
setAcl [-s] [-v version] [-R] path acl
setquota -n|-b val path
stat [-w] path
sync path
帮助列表中命令较多,我们只需要掌握一些较为常用的 ZooKeeper 命令即可。
查看某个路径的节点
[zkshell: 8] ls /
[zookeeper]
创建节点
create 路径 数据
[zkshell: 9] create /zk_test my_data
Created /zk_test
创建永久节点:
create /zk_test my_data
创建永久有序节点:
create -s /zk_test my_data
查看节点详情
[zkshell: 12] get /zk_test
my_data
cZxid = 5
ctime = Fri Jun 05 13:57:06 PDT 2009
mZxid = 5
mtime = Fri Jun 05 13:57:06 PDT 2009
pZxid = 5
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0
dataLength = 7
numChildren = 0
修改节点值
[zkshell: 14] set /zk_test junk
cZxid = 5
ctime = Fri Jun 05 13:57:06 PDT 2009
mZxid = 6
mtime = Fri Jun 05 14:01:52 PDT 2009
pZxid = 5
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0
dataLength = 4
numChildren = 0
[zkshell: 15] get /zk_test
junk
cZxid = 5
ctime = Fri Jun 05 13:57:06 PDT 2009
mZxid = 6
mtime = Fri Jun 05 14:01:52 PDT 2009
pZxid = 5
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0
dataLength = 4
numChildren = 0
删除节点值
[zkshell: 16] delete /zk_test
[zkshell: 17] ls /
[zookeeper]
[zkshell: 18]
Java 操作 ZooKeeper
本节为拓展内容,因篇幅有限,不做详细介绍,同学们可看推荐链接。
加入依赖
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.5.5</version>
</dependency>
使用 Demo
推荐阅读:https://segmentfault.com/a/1190000021320564
ZooKeeper 常见面试题
1. ZooKeeper 是什么?
ZooKeeper 是一个基于 Java 语言开发的,开源的,可靠的,服务于其他分布式服务产品的一款服务注册与发现的工具。属于 Apache 基金会。
2. ZooKeeper 有那些应用场景?
服务注册与发现(注册中心)
3. 你的 ZooKeeper 分布式锁实现思路是什么?
当应用获取锁时,在 ZooKeeper 中创建一个临时带序号节点,判断该节点是否时序号最小的临时节点,如果是则成功获取锁。如果不是则监听前一个节点是否释放,直到自己创建的节点成为带序号的最小节点,则获取到锁。释放锁时,删除该临时节点即可。
4. 什么是 ZAB 协议?
ZAB 协议是特别为 ZooKeeper 设计的支持崩溃回复的原子广播协议。
协议内容包含两种模式:
- 消息广播
- 崩溃恢复
ZooKeeper 节点类型有那些?
- 持久节点
- 持久有序节点
- 临时节点
- 临时有序节点
5. ZooKeeper 下 Server 工作状态有哪些?
服务器具有四种状态,分别是 LOOKING、FOLLOWING、LEADING、OBSERVING。
- LOOKING:寻找 Leader 状态。当服务器处于该状态时,它会认为当前集群中没有 Leader,因此需要进入 Leader 选举状态。
- FOLLOWING:跟随者状态。表明当前服务器角色是 Follower。
- LEADING:领导者状态。表明当前服务器角色是 Leader。
- OBSERVING:观察者状态。表明当前服务器角色是 Observer。
相关推荐
- 0722-6.2.0-如何在RedHat7.2使用rpm安装CDH(无CM)
-
文档编写目的在前面的文档中,介绍了在有CM和无CM两种情况下使用rpm方式安装CDH5.10.0,本文档将介绍如何在无CM的情况下使用rpm方式安装CDH6.2.0,与之前安装C5进行对比。环境介绍:...
- ARM64 平台基于 openEuler + iSula 环境部署 Kubernetes
-
为什么要在arm64平台上部署Kubernetes,而且还是鲲鹏920的架构。说来话长。。。此处省略5000字。介绍下系统信息;o架构:鲲鹏920(Kunpeng920)oOS:ope...
- 生产环境starrocks 3.1存算一体集群部署
-
集群规划FE:节点主要负责元数据管理、客户端连接管理、查询计划和查询调度。>3节点。BE:节点负责数据存储和SQL执行。>3节点。CN:无存储功能能的BE。环境准备CPU检查JDK...
- 在CentOS上添加swap虚拟内存并设置优先级
-
现如今很多云服务器都会自己配置好虚拟内存,当然也有很多没有配置虚拟内存的,虚拟内存可以让我们的低配服务器使用更多的内存,可以减少很多硬件成本,比如我们运行很多服务的时候,内存常常会满,当配置了虚拟内存...
- 国产深度(deepin)操作系统优化指南
-
1.升级内核随着deepin版本的更新,会自动升级系统内核,但是我们依旧可以通过命令行手动升级内核,以获取更好的性能和更多的硬件支持。具体操作:-添加PPAs使用以下命令添加PPAs:```...
- postgresql-15.4 多节点主从(读写分离)
-
1、下载软件[root@TX-CN-PostgreSQL01-252software]#wgethttps://ftp.postgresql.org/pub/source/v15.4/postg...
- Docker 容器 Java 服务内存与 GC 优化实施方案
-
一、设置Docker容器内存限制(生产环境建议)1.查看宿主机可用内存bashfree-h#示例输出(假设宿主机剩余16GB可用内存)#Mem:64G...
- 虚拟内存设置、解决linux内存不够问题
-
虚拟内存设置(解决linux内存不够情况)背景介绍 Memory指机器物理内存,读写速度低于CPU一个量级,但是高于磁盘不止一个量级。所以,程序和数据如果在内存的话,会有非常快的读写速度。但是,内存...
- Elasticsearch性能调优(5):服务器配置选择
-
在选择elasticsearch服务器时,要尽可能地选择与当前业务量相匹配的服务器。如果服务器配置太低,则意味着需要更多的节点来满足需求,一个集群的节点太多时会增加集群管理的成本。如果服务器配置太高,...
- Es如何落地
-
一、配置准备节点类型CPU内存硬盘网络机器数操作系统data节点16C64G2000G本地SSD所有es同一可用区3(ecs)Centos7master节点2C8G200G云SSD所有es同一可用区...
- 针对Linux内存管理知识学习总结
-
现在的服务器大部分都是运行在Linux上面的,所以,作为一个程序员有必要简单地了解一下系统是如何运行的。对于内存部分需要知道:地址映射内存管理的方式缺页异常先来看一些基本的知识,在进程看来,内存分为内...
- MySQL进阶之性能优化
-
概述MySQL的性能优化,包括了服务器硬件优化、操作系统的优化、MySQL数据库配置优化、数据库表设计的优化、SQL语句优化等5个方面的优化。在进行优化之前,需要先掌握性能分析的思路和方法,找出问题,...
- Linux Cgroups(Control Groups)原理
-
LinuxCgroups(ControlGroups)是内核提供的资源分配、限制和监控机制,通过层级化进程分组实现资源的精细化控制。以下从核心原理、操作示例和版本演进三方面详细分析:一、核心原理与...
- linux 常用性能优化参数及理解
-
1.优化内核相关参数配置文件/etc/sysctl.conf配置方法直接将参数添加进文件每条一行.sysctl-a可以查看默认配置sysctl-p执行并检测是否有错误例如设置错了参数:[roo...
- 如何在 Linux 中使用 Sysctl 命令?
-
sysctl是一个用于配置和查询Linux内核参数的命令行工具。它通过与/proc/sys虚拟文件系统交互,允许用户在运行时动态修改内核参数。这些参数控制着系统的各种行为,包括网络设置、文件...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- linux 查询端口号 (58)
- docker映射容器目录到宿主机 (66)
- 杀端口 (60)
- yum更换阿里源 (62)
- internet explorer 增强的安全配置已启用 (65)
- linux自动挂载 (56)
- 禁用selinux (55)
- sysv-rc-conf (69)
- ubuntu防火墙状态查看 (64)
- windows server 2022激活密钥 (56)
- 无法与服务器建立安全连接是什么意思 (74)
- 443/80端口被占用怎么解决 (56)
- ping无法访问目标主机怎么解决 (58)
- fdatasync (59)
- 405 not allowed (56)
- 免备案虚拟主机zxhost (55)
- linux根据pid查看进程 (60)
- dhcp工具 (62)
- mysql 1045 (57)
- 宝塔远程工具 (56)
- ssh服务器拒绝了密码 请再试一次 (56)
- ubuntu卸载docker (56)
- linux查看nginx状态 (63)
- tomcat 乱码 (76)
- 2008r2激活序列号 (65)