热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

ZooKeeper源码分析系列一开篇基础知识剖析

一、ZooKeeper总体介绍1.1、什么是zookeeperZooKeeper是一个分布式的,开放源码的分布式应用程序协同服务存储系统,同时是一款世界级的优秀开源

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5rW3wrfmmK_lgJLov4fmnaXnmoTlpKk=,size_18,color_FFFFFF,t_70,g_se,x_16

 


一、ZooKeeper总体介绍


1.1、什么是zookeeper


ZooKeeper 是一个分布式的,开放源码的分布式应用程序协同服务+存储系统,同时是一款世界级的优秀开源产品,在大数据生态系统中 Hadoop、Storm、HBase、Spark、Flink、Kafka 随处都是 ZooKeeper的应用场景。特别是在粗粒度分布式锁、分布式选主、主备高可用切换等不需要高 TPS 的场景下有不可替代的作用。



1.2、ZooKeeper 应用场景


很多分布式协调服务都可以用 ZooKeeper 来做,其中典型应用场景如下:
1、配置管理:比如微服务系统,各个独立服务都要使用集中化的配置管理,这个时候就需要 ZooKeeper。
2、组成员管理:比如上面讲到的 HBase 其实就是用来做集群的组成员管理。
3、各种分布式锁:ZooKeeper 适用于存储和协同相关的关键数据,不适合用于大数据量存储。如果要存 KV 或者大量的业务数据,还是要用数据库或者其他 NoSql 来做。
4、注册中心:大多数中小型公司都用zk来做注册中心



至于为什么 ZooKeeper 不适合大数据量存储呢?主要有以下两个原因:
1、设计方面:ZooKeeper 需要把所有的数据(它的 data tree)加载到内存中。这就决定了ZooKeeper 存储的数据量受内存的限制。一般的数据库系统例如 MySQL可以存储大于内存的数据,这是因为 InnoDB 是基于 B-Tree 的存储引擎(基于内存+磁盘一致性)。
2、工程方面:ZooKeeper 的设计目标是为协同服务提供数据存储,数据的高可用性和性能是最重要的系统指标,处理大数量不是 ZooKeeper 的首要目标。因此,ZooKeeper 不会对大数量存储做太多工程上的优化。



二.ZooKeeper源码环境


2.1、ZooKeeper版本选择


在了解任何技术源码的时候,最重要的两件事要搞清楚:
1、版本如何选择
2、源码环境准备
zookeeper的大版本:
1、zookeeper-3.4.x 企业最常用,大数据技术组件最常用
2、zookeeper-3.5.x
3、zookeeper-3.6.x
最总结论:zookeeper-3.4.14.tar.gz,安装包就是源码包, ZooKeeper-3.5 以上,源码 和 安装包就分开了。



2.2、 ZooKeeper源码环境准备


1、准备一个IDE:IDEA
2、从官网下载源码包,IDEA去导入这个源码项目即可
3、稍微等待一下,maven去下载一些依赖jar
4、从官网下载 zookeeper-3.4.14.tar.gz 安装包,该安装包直接包含源码或者从 github 去拉取源码项目



三.ZooKeeper基础之序列化机制


3.1、序列化使用场景


1、当在网络中需要进行消息,数据传输,那么这些数据就需要进行序列化和反序列化
2、当数据需要被持久化到磁盘的时候



3.2、什么是序列化, 为什么要进行序列化操作


1、序列化是指将我们定义好的 go/php/java 类型转化成数据流的形式。之所以这么做是因为在网络传输过程中,TCP 协议采用“流通信”的方式,提供了可以读写的字节流
2、任何一个分布式系统的底层,都必然会有网络通信,这就必然要提供一个分布式通信框架和序列化机制。所以我们在看 ZooKeeper 源码之前,先搞定 ZooKeeper 网络通信和序列化。



3.3、序列化实现方式

3.3.1、java序列化实现

Java 中进行序列化和反序列化的过程中,主要使用 ObjectInputStream 和 ObjectOutputStream 来进行具体的序列化和反序列化。

ad868f0eb91afc53433ccfa743749c3c.png

3.3.2、hadoop的序列化实现

441ca115baccb972b3e60ef6ce170e26.png

3.3.3、ZooKeeper 中的序列化机制

84a62bcca1fa4462bd927c2ff4d0662e.gif

序列化的 API 主要在 zookeeper-jute 子项目中。

3.3.4、重点API:

b19c8094c241466eb968012308bcef85.gif


org.apache.jute.InputArchive:反序列化需要实现的接口,其中各种 read 开头的方法,都是反序列化方法
org.apache.jute.OutputArchive:所有进行序列化操作的都是实现这个接口,其中各种 write 开头的方法都是序列化方法。
org.apache.jute.Index:用于迭代数据进行反序列化的迭代器
org.apache.jute.Record:在 ZooKeeper 要进行网络通信的对象,都需要实现这个接口。里面有序列化和反序列化两个重要的方法



四、ZooKeeper基础之持久化机制

对于只要底层涉及到关于数据的存储,读写操作, 一般都会有一个持久化机制来保证.那么ZooKeeper的数据模型主要涉及两类知识:数据模型 和 持久化机制, 背后是两套API来支撑


1、数据模型 : ZKDataBase + DataTree + DataNode
2、持久化机制: TxnLog + SnapLog


ZooKeeper 本身是一个对等架构(内部选举,从所有 learner 中选举一个 leader, 剩下的成为follower)


1、每个节点上都保存了整个系统的所有数据(leader存储了数据,所有的follower节点都是leader的副本节点)
2、每个节点上的都把数据放在磁盘一份,放在内存一份, 保证磁盘跟内存一致性,来平衡读写性能


ZooKeeper的数据模型,抽象出了重要的三个API用来完成数据的管理:


1、ZKDataBase 负责管理 DataTree ,执行 DataTree 的相关 快照和恢复的操作
2、DataTree znode系统的完整抽象, 整个数据树结构
3、DataNode znode 系统中的一个节点的抽象


关于 ZooKeeper 中的数据在内存中的组织,其实就是一棵树:


1、这棵树就叫做:DataTree (抽象了一棵树)
2、这棵树上的节点:DataNode (抽象一个节点)
3、关于管理这个 DataTree 的组件就是 ZKDataBase (内存数据库:针对 DataTree 能做各种操作)


ZooKeeper 的持久化的一些操作接口,都在org.apache.zookeeper.server.persistence 包中。

 

d2abf82dbbb94d8495608cfd9acaf85f.png

 

c6f7580b0e28b5d535113c0c8c98421b.png

 

d347e40e120840e79fa5b5fab3f05e26.gif

主要的类的介绍:


第一组:主要是用来操作日志的(如果客户端往zk中写入一条数据,则记录一条日志)
TxnLog,接口,读取事务性日志的接口。
FileTxnLog,实现TxnLog接口,添加了访问该事务性日志的API。
第二组:拍摄快照(当内存数据持久化到磁盘)
Snapshot,接口类型,持久层快照接口。
FileSnap,实现Snapshot接口,负责存储、序列化、反序列化、访问快照。
第三组;两个成员变量:TxnLog和SnapShot
FileTxnSnapLog,封装了TxnLog和SnapShot。
第四组:工具类
Util,工具类,提供持久化所需的API。



五、ZooKeeper基础之网络通信机制

Java IO 有几个种类:


1、BIO JDK-1.1(编码简单,效率低) 阻塞模型
2、NIO JDK-1.4(效率有提升,编码复杂) 基于reactor实现的异步非阻塞网络通信模型 通常的IO的选择:
1)、原生NIO 2)、基于NIO实现的网络通信框架:netty
3、AIO JDK-1.7(效率最高,编码复杂度一般) 真正的异步非阻塞通信模型


NIO 的三大API:


1、Buffer
2、Channel
3、Selector


ZooKeeper 中的通信有两种方式:


1、NIO,默认使用NIO
2、Netty


两个最重要的API:


ServerCnxn 服务端的通信组件
ClientCnxn 客户端的通信组件


关于客户端和服务端的一个定义:谁发请求,谁就是客户端,谁接收和处理请求,谁就是服务端


1、真正的client给zookeeper发请求
2、zookeeper中的leader给follower发命令
3、zookeeper中的followe给leader发请求


ServerCnxn实现包:org.apache.zookeeper.server.ServerCnxn

 

372dd95a940af3fa1f2e6d6fbfd11a30.png

ServerCnxn实现包


详细说明:
Stats,表示ServerCnxn上的统计数据。
Watcher,表示事件处理,监听器
ServerCnxn,表示服务器连接,表示一个从客户端到服务器的连接。
ClientCnxn,存在于客户端用来执行通信的组件
NettyServerCnxn,基于Netty的连接的具体实现。
NIOServerCnxn,基于NIO的连接的具体实现。



六、Zookeeper基础之Watcher工作机制

客户端的 Watcher 注册:


1、org.apache.zookeeper.ZooKeeper:客户端基础类、存储了ClientCnxn和ZkWatcherManager
2、ZKWatchManager:ZooKeeper的内部类,实现了ClientWatchManager接口,主要用来存储各种类型的Watcher,主要有三种:dataWatches、existWatches、childWatches以及一个默认的defaultWatcher
3、org.apache.zookeeper.ClientCnxn:与服务端的交互类,主要包含以下对象:LinkedListoutgoingQueue、SendThread 和 EventThread,其中outgoingQueue未待发送给服务端的Packet列表,SendThread线程负责和服务端进行请求交互,而EventThread线程则负责客户端Watcher事件的回调执行
4、WatchRegistration:Zookeeper的内容类,包装了Watcher和clientPath,并且负责Watcher的注册
5、Packet:ClientCnxn的内部类,与Zookeeper服务端通信的交互类


e6dddbcff2053150d8e6640c29c449b3.png

两条主线


1、实现主线:Watcher + WatchedEvent
2、管理主线:WatchManager(负责响应watcher.process(watchedEvent)) + ZKWatchManager(负责注册等相关管理)


bb9f6db70f2cac0c386a63d97b60f5cf.png

组件说明:


Watcher,接口类型,其定义了process方法,需子类实现。
Event,接口类型,Watcher的内部类,无任何方法。
KeeperState,枚举类型,Event的内部类,表示Zookeeper所处的状态。
EventType,枚举类型,Event的内部类,表示Zookeeper中发生的事件类型。
WatchedEvent,表示对ZooKeeper上发生变化后的反馈,包含了KeeperState和EventType。
ClientWatchManager,接口类型,表示客户端的Watcher管理者,其定义了materialized方法,需子类实现。
ZKWatchManager,Zookeeper的内部类,继承ClientWatchManager。
MyWatcher,ZooKeeperMain的内部类,继承Watcher。
ServerCnxn,接口类型,继承Watcher,表示客户端与服务端的一个连接。
WatchManager,管理Watcher。


Watch


一、ZooKeeper总体介绍


1.1、什么是zookeeper


ZooKeeper 是一个分布式的,开放源码的分布式应用程序协同服务+存储系统,同时是一款世界级的优秀开源产品,在大数据生态系统中 Hadoop、Storm、HBase、Spark、Flink、Kafka 随处都是 ZooKeeper的应用场景。特别是在粗粒度分布式锁、分布式选主、主备高可用切换等不需要高 TPS 的场景下有不可替代的作用。



1.2、ZooKeeper 应用场景


很多分布式协调服务都可以用 ZooKeeper 来做,其中典型应用场景如下:
1、配置管理:比如微服务系统,各个独立服务都要使用集中化的配置管理,这个时候就需要 ZooKeeper。
2、组成员管理:比如上面讲到的 HBase 其实就是用来做集群的组成员管理。
3、各种分布式锁:ZooKeeper 适用于存储和协同相关的关键数据,不适合用于大数据量存储。如果要存 KV 或者大量的业务数据,还是要用数据库或者其他 NoSql 来做。
4、注册中心:大多数中小型公司都用zk来做注册中心



至于为什么 ZooKeeper 不适合大数据量存储呢?主要有以下两个原因:
1、设计方面:ZooKeeper 需要把所有的数据(它的 data tree)加载到内存中。这就决定了ZooKeeper 存储的数据量受内存的限制。一般的数据库系统例如 MySQL可以存储大于内存的数据,这是因为 InnoDB 是基于 B-Tree 的存储引擎(基于内存+磁盘一致性)。
2、工程方面:ZooKeeper 的设计目标是为协同服务提供数据存储,数据的高可用性和性能是最重要的系统指标,处理大数量不是 ZooKeeper 的首要目标。因此,ZooKeeper 不会对大数量存储做太多工程上的优化。



二.ZooKeeper源码环境


2.1、ZooKeeper版本选择


在了解任何技术源码的时候,最重要的两件事要搞清楚:
1、版本如何选择
2、源码环境准备
zookeeper的大版本:
1、zookeeper-3.4.x 企业最常用,大数据技术组件最常用
2、zookeeper-3.5.x
3、zookeeper-3.6.x
最总结论:zookeeper-3.4.14.tar.gz,安装包就是源码包, ZooKeeper-3.5 以上,源码 和 安装包就分开了。



2.2、 ZooKeeper源码环境准备


1、准备一个IDE:IDEA
2、从官网下载源码包,IDEA去导入这个源码项目即可
3、稍微等待一下,maven去下载一些依赖jar
4、从官网下载 zookeeper-3.4.14.tar.gz 安装包,该安装包直接包含源码或者从 github 去拉取源码项目



三.ZooKeeper基础之序列化机制


3.1、序列化使用场景


1、当在网络中需要进行消息,数据传输,那么这些数据就需要进行序列化和反序列化
2、当数据需要被持久化到磁盘的时候



3.2、什么是序列化, 为什么要进行序列化操作


1、序列化是指将我们定义好的 go/php/java 类型转化成数据流的形式。之所以这么做是因为在网络传输过程中,TCP 协议采用“流通信”的方式,提供了可以读写的字节流
2、任何一个分布式系统的底层,都必然会有网络通信,这就必然要提供一个分布式通信框架和序列化机制。所以我们在看 ZooKeeper 源码之前,先搞定 ZooKeeper 网络通信和序列化。



3.3、序列化实现方式

3.3.1、java序列化实现

Java 中进行序列化和反序列化的过程中,主要使用 ObjectInputStream 和 ObjectOutputStream 来进行具体的序列化和反序列化。

bbfa83efd9c9b4f9bf28afcc2643f3cb.png

3.3.2、hadoop的序列化实现

005807c710021c7e8126facefb00832e.png

3.3.3、ZooKeeper 中的序列化机制

f2649c92046e45bf857a5adb79869cd0.gif

序列化的 API 主要在 zookeeper-jute 子项目中。

3.3.4、重点API:

30183c3473fe43f1a82b31da7f578e70.gif


org.apache.jute.InputArchive:反序列化需要实现的接口,其中各种 read 开头的方法,都是反序列化方法
org.apache.jute.OutputArchive:所有进行序列化操作的都是实现这个接口,其中各种 write 开头的方法都是序列化方法。
org.apache.jute.Index:用于迭代数据进行反序列化的迭代器
org.apache.jute.Record:在 ZooKeeper 要进行网络通信的对象,都需要实现这个接口。里面有序列化和反序列化两个重要的方法



四、ZooKeeper基础之持久化机制

对于只要底层涉及到关于数据的存储,读写操作, 一般都会有一个持久化机制来保证.那么ZooKeeper的数据模型主要涉及两类知识:数据模型 和 持久化机制, 背后是两套API来支撑


1、数据模型 : ZKDataBase + DataTree + DataNode
2、持久化机制: TxnLog + SnapLog


ZooKeeper 本身是一个对等架构(内部选举,从所有 learner 中选举一个 leader, 剩下的成为follower)


1、每个节点上都保存了整个系统的所有数据(leader存储了数据,所有的follower节点都是leader的副本节点)
2、每个节点上的都把数据放在磁盘一份,放在内存一份, 保证磁盘跟内存一致性,来平衡读写性能


ZooKeeper的数据模型,抽象出了重要的三个API用来完成数据的管理:


1、ZKDataBase 负责管理 DataTree ,执行 DataTree 的相关 快照和恢复的操作
2、DataTree znode系统的完整抽象, 整个数据树结构
3、DataNode znode 系统中的一个节点的抽象


关于 ZooKeeper 中的数据在内存中的组织,其实就是一棵树:


1、这棵树就叫做:DataTree (抽象了一棵树)
2、这棵树上的节点:DataNode (抽象一个节点)
3、关于管理这个 DataTree 的组件就是 ZKDataBase (内存数据库:针对 DataTree 能做各种操作)


ZooKeeper 的持久化的一些操作接口,都在org.apache.zookeeper.server.persistence 包中。

 

8d76720f9f22fa542fcdeec4fe5d2511.png

 

342344795fd1bf1760d30be8ec8a6b68.png

 

8900fe70dd26414d8d80d007a7bb3523.gif

主要的类的介绍:


第一组:主要是用来操作日志的(如果客户端往zk中写入一条数据,则记录一条日志)
TxnLog,接口,读取事务性日志的接口。
FileTxnLog,实现TxnLog接口,添加了访问该事务性日志的API。
第二组:拍摄快照(当内存数据持久化到磁盘)
Snapshot,接口类型,持久层快照接口。
FileSnap,实现Snapshot接口,负责存储、序列化、反序列化、访问快照。
第三组;两个成员变量:TxnLog和SnapShot
FileTxnSnapLog,封装了TxnLog和SnapShot。
第四组:工具类
Util,工具类,提供持久化所需的API。



五、ZooKeeper基础之网络通信机制

Java IO 有几个种类:


1、BIO JDK-1.1(编码简单,效率低) 阻塞模型
2、NIO JDK-1.4(效率有提升,编码复杂) 基于reactor实现的异步非阻塞网络通信模型 通常的IO的选择:
1)、原生NIO 2)、基于NIO实现的网络通信框架:netty
3、AIO JDK-1.7(效率最高,编码复杂度一般) 真正的异步非阻塞通信模型


NIO 的三大API:


1、Buffer
2、Channel
3、Selector


ZooKeeper 中的通信有两种方式:


1、NIO,默认使用NIO
2、Netty


两个最重要的API:


ServerCnxn 服务端的通信组件
ClientCnxn 客户端的通信组件


关于客户端和服务端的一个定义:谁发请求,谁就是客户端,谁接收和处理请求,谁就是服务端


1、真正的client给zookeeper发请求
2、zookeeper中的leader给follower发命令
3、zookeeper中的followe给leader发请求


ServerCnxn实现包:org.apache.zookeeper.server.ServerCnxn

 

266e43f7cdec81964f0a2b543869494d.png

ServerCnxn实现包


详细说明:
Stats,表示ServerCnxn上的统计数据。
Watcher,表示事件处理,监听器
ServerCnxn,表示服务器连接,表示一个从客户端到服务器的连接。
ClientCnxn,存在于客户端用来执行通信的组件
NettyServerCnxn,基于Netty的连接的具体实现。
NIOServerCnxn,基于NIO的连接的具体实现。



六、Zookeeper基础之Watcher工作机制

客户端的 Watcher 注册:


1、org.apache.zookeeper.ZooKeeper:客户端基础类、存储了ClientCnxn和ZkWatcherManager
2、ZKWatchManager:ZooKeeper的内部类,实现了ClientWatchManager接口,主要用来存储各种类型的Watcher,主要有三种:dataWatches、existWatches、childWatches以及一个默认的defaultWatcher
3、org.apache.zookeeper.ClientCnxn:与服务端的交互类,主要包含以下对象:LinkedListoutgoingQueue、SendThread 和 EventThread,其中outgoingQueue未待发送给服务端的Packet列表,SendThread线程负责和服务端进行请求交互,而EventThread线程则负责客户端Watcher事件的回调执行
4、WatchRegistration:Zookeeper的内容类,包装了Watcher和clientPath,并且负责Watcher的注册
5、Packet:ClientCnxn的内部类,与Zookeeper服务端通信的交互类


26a5f8df67918efb9ceed02bd21ac145.png

两条主线


1、实现主线:Watcher + WatchedEvent
2、管理主线:WatchManager(负责响应watcher.process(watchedEvent)) + ZKWatchManager(负责注册等相关管理)


14de241b612eb96acae3716de63fb541.png

组件说明:


Watcher,接口类型,其定义了process方法,需子类实现。
Event,接口类型,Watcher的内部类,无任何方法。
KeeperState,枚举类型,Event的内部类,表示Zookeeper所处的状态。
EventType,枚举类型,Event的内部类,表示Zookeeper中发生的事件类型。
WatchedEvent,表示对ZooKeeper上发生变化后的反馈,包含了KeeperState和EventType。
ClientWatchManager,接口类型,表示客户端的Watcher管理者,其定义了materialized方法,需子类实现。
ZKWatchManager,Zookeeper的内部类,继承ClientWatchManager。
MyWatcher,ZooKeeperMain的内部类,继承Watcher。
ServerCnxn,接口类型,继承Watcher,表示客户端与服务端的一个连接。
WatchManager,管理Watcher。


Watcher 主要工作流程:


1、用户调用 Zookeeper 的 getData 方法,并将自定义的 Watcher 以参数形式传入,该方法的作用主要是封装请求,然后调用 ClientCnxn 的 submitRequest 方法提交请求
2、 ClientCnxn 在调用 submitRequest 提交请求时,会将 WatchRegistration(封装了我们传入的Watcher 和clientPath )以参数的形式传入,submitRequest 方法主要作用是将信息封装成Packet(ClientCnxn的内部类),并将封装好的 Packet 加入到 ClientCnxn 的待发送列表中(LinkedList outgoingQueue)
3、 SendThread 线程不断地从 outgoingQueue 取出未发送的 Packet 发送给客户端并且将该 Packet加入pendingQueue (等待服务器响应的Packet列表)中,并通过自身的 readResponse 方法接收服务端的响应
4、SendThread 接收到客户端的响应以后,会调用 ClientCnxn 的finishPacket 方法进行 Watcher方法的注册
5、在 finishPacket 方法中,会取出 Packet 中的 WatchRegistration 对象,并调用其 register 方法,从ZKWatchManager 取出对应的 dataWatches、existWatches 或者 childWatches 其中的一个Watcher 集合,然后将自己的 Watcher 添加到该 Watcher 集合中。


er 主要工作流程:


1、用户调用 Zookeeper 的 getData 方法,并将自定义的 Watcher 以参数形式传入,该方法的作用主要是封装请求,然后调用 ClientCnxn 的 submitRequest 方法提交请求
2、 ClientCnxn 在调用 submitRequest 提交请求时,会将 WatchRegistration(封装了我们传入的Watcher 和clientPath )以参数的形式传入,submitRequest 方法主要作用是将信息封装成Packet(ClientCnxn的内部类),并将封装好的 Packet 加入到 ClientCnxn 的待发送列表中(LinkedList outgoingQueue)
3、 SendThread 线程不断地从 outgoingQueue 取出未发送的 Packet 发送给客户端并且将该 Packet加入pendingQueue (等待服务器响应的Packet列表)中,并通过自身的 readResponse 方法接收服务端的响应
4、SendThread 接收到客户端的响应以后,会调用 ClientCnxn 的finishPacket 方法进行 Watcher方法的注册
5、在 finishPacket 方法中,会取出 Packet 中的 WatchRegistration 对象,并调用其 register 方法,从ZKWatchManager 取出对应的 dataWatches、existWatches 或者 childWatches 其中的一个Watcher 集合,然后将自己的 Watcher 添加到该 Watcher 集合中。


 


推荐阅读
  • flea,frame,db,使用,之 ... [详细]
  • 本文回顾了作者在求职阿里和腾讯实习生过程中,从最初的迷茫到最后成功获得Offer的心路历程。文中不仅分享了个人的面试经历,还提供了宝贵的面试准备建议和技巧。 ... [详细]
  • Hibernate全自动全映射ORM框架,旨在消除sql,是一个持久层的ORM框架1)、基础概念DAO(DataAccessorOb ... [详细]
  • Maven + Spring + MyBatis + MySQL 环境搭建与实例解析
    本文详细介绍如何使用MySQL数据库进行环境搭建,包括创建数据库表并插入示例数据。随后,逐步指导如何配置Maven项目,整合Spring框架与MyBatis,实现高效的数据访问。 ... [详细]
  • 我的读书清单(持续更新)201705311.《一千零一夜》2006(四五年级)2.《中华上下五千年》2008(初一)3.《鲁滨孙漂流记》2008(初二)4.《钢铁是怎样炼成的》20 ... [详细]
  • 分布式开源任务调度框架 TBSchedule 深度解析与应用实践
    本文深入解析了分布式开源任务调度框架 TBSchedule 的核心原理与应用场景,并通过实际案例详细介绍了其部署与使用方法。首先,从源码下载开始,详细阐述了 TBSchedule 的安装步骤和配置要点。接着,探讨了该框架在大规模分布式环境中的性能优化策略,以及如何通过灵活的任务调度机制提升系统效率。最后,结合具体实例,展示了 TBSchedule 在实际项目中的应用效果,为开发者提供了宝贵的实践经验。 ... [详细]
  • 解决ADODB连接Access时出现80004005错误的方法
    本文详细介绍了如何解决在使用ADODB连接Access数据库时遇到的80004005错误,包括错误原因分析和具体的解决步骤。 ... [详细]
  • [附源码]计算机毕业设计JAVAjsp医药管理信息系统
    [附源码]计算机毕业设计JAVAjsp医药管理信息系统项目运行环境配置:Jdk1.8Tomcat7.0MysqlHBuilderX(Webstor ... [详细]
  • 本文探讨了如何在 Spring MVC 框架下,通过自定义注解和拦截器机制来实现细粒度的权限管理功能。 ... [详细]
  • 本文详细介绍了Java代码分层的基本概念和常见分层模式,特别是MVC模式。同时探讨了不同项目需求下的分层策略,帮助读者更好地理解和应用Java分层思想。 ... [详细]
  • 阿里巴巴终面技术挑战:如何利用 UDP 实现 TCP 功能?
    在阿里巴巴的技术面试中,技术总监曾提出一道关于如何利用 UDP 实现 TCP 功能的问题。当时回答得不够理想,因此事后进行了详细总结。通过与总监的进一步交流,了解到这是一道常见的阿里面试题。面试官的主要目的是考察应聘者对 UDP 和 TCP 在原理上的差异的理解,以及如何通过 UDP 实现类似 TCP 的可靠传输机制。 ... [详细]
  • 服务器部署中的安全策略实践与优化
    服务器部署中的安全策略实践与优化 ... [详细]
  • 回顾过去十多年的开发经历,我在技术能力、培训机会、国际视野以及大型企业的工作经验方面都有了显著的提升。特别是从最初的月薪8k到如今的38k,这一过程中,我深刻体会到系统化学习对提升架构能力的重要性。最初踏入职场时,面对众多未知,我主要依赖团队领导的指导,专注于编写代码、管理数据库和进行测试。随着经验的积累和技术的不断进步,我逐渐意识到,只有通过系统化的学习和实践,才能在技术领域取得更大的突破。 ... [详细]
  • 优化后的标题:深入探讨网关安全:将微服务升级为OAuth2资源服务器的最佳实践
    本文深入探讨了如何将微服务升级为OAuth2资源服务器,以订单服务为例,详细介绍了在POM文件中添加 `spring-cloud-starter-oauth2` 依赖,并配置Spring Security以实现对微服务的保护。通过这一过程,不仅增强了系统的安全性,还提高了资源访问的可控性和灵活性。文章还讨论了最佳实践,包括如何配置OAuth2客户端和资源服务器,以及如何处理常见的安全问题和错误。 ... [详细]
  • 近年来,BPM(业务流程管理)系统在国内市场逐渐普及,多家厂商在这一领域崭露头角。本文将对当前主要的BPM厂商进行概述,并分析其各自的优势。目前,市场上较为成熟的BPM产品主要分为两类:一类是综合型厂商,如IBM和SAP,这些企业在整体解决方案方面具有明显优势;另一类则是专注于BPM领域的专业厂商,它们在特定行业或应用场景中表现出色。通过对比分析,本文旨在为企业选择合适的BPM系统提供参考。 ... [详细]
author-avatar
小王儿
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有