Fabric多机部署启动节点与合约部署
这是我搭建的fabric的网络拓扑
3 个 orderer 节点;组织 org1 , org1 下有两个 peer 节点, peer0 和 peer1; 组织 org2 , org2 下有两个 peer 节点, peer0 和 peer1;
以上是我的多机环境的网络拓扑,使用的是docker搭建的。我的网络已经搭建成功,这里主要记录一下多机环境下合约部署与交互的操作,因为是用虚拟机搭建,有时候关机后需要重启dcoek节点,然后创建通道部署链码。关于config和docker-compose的yaml文件不知道怎么部署的可以私信我哦,多机生产网络的搭建有太多的坑了。
1. 启动网络
在两台机器上启动网络
docker-compose -f docker-compose-up.yaml up -d
可以看到我的所有节点都已经起来了,三个orderer,两个组织每个组织包含两个peer节点。
2. 创建通道并加入
2.1 虚拟机1创建通道并加入
进⼊ cli1容器,也就是以 peer0.org1 的⾓⾊与⽹络交互
docker exec -it cli1 bash
创建通道
peer channel create -o orderer0.example.com:7050 -c mychannel -f ./channel-artifacts/channel.tx --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
组织1 的 peer0 节点加⼊通道 mychannel
peer channel join -b mychannel.block
更新 组织1 的锚节点
peer channel update -o orderer0.example.com:7050 -c mychannel -f ./channel-artifacts/Org1MSPanchors.tx --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
退出 cli1 容器,从 cli1 容器中拷⻉出 mychannel.block ⽂件到 multiple-deployment ⽂件夹下,并复制到 虚拟机2 中
exit docker cp cli1:/opt/gopath/src/github.com/hyperledger/fabric/peer/mychannel.block ./
scp -r mychannel.block org2@192.168.5.112:/home/org2/go/src/github.com/hyperledger/fabric-samples/multiple-deployment
查看虚拟机2是否收到:
2.2 虚拟机2加入通道
将 mychannel.block 拷⻉到 虚拟机2 的 cli1 ( 组织2 的 peer0 ⾓⾊)容器中
docker cp mychannel.block cli1:/opt/gopath/src/github.com/hyperledger/fabric/peer/
进⼊ cli1 容器
docker exec -it cli1 bash
ls
加入通道:
peer channel join -b mychannel.block
更新组织 2 的锚节点(主节点)
peer channel update -o orderer0.example.com:7050 -c mychannel -f ./channel-artifacts/Org2MSPanchors.tx --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
3. 安装调用智能合约
安装的同样是basic链码,在前面对这个链码介绍过,当时在测试网络中进行了部署调用,有兴趣的可以去看看对于合约的讲解。博文
3.1 安装链码
首先是虚拟机1的操作:
# 进入容器
docker exec -it cli1 bash
# 打包链码
peer lifecycle chaincode package mycc.tar.gz --path ../../multiple-deployment/chaincode/go/basic --lang golang --label mycc_1
# 安装链码 安装需要在两个组织都安装,现在只是在虚拟机1
peer lifecycle chaincode install mycc.tar.gz
#控制台信息:
root@b63202ddd2b5:/opt/gopath/src/github.com/hyperledger/fabric/peer# peer lifecycle chaincode install mycc.tar.gz
2023-11-15 02:11:26.585 UTC 0001 INFO [cli.lifecycle.chaincode] submitInstallProposal -> Installed remotely: response:<status:200 payload:"\nGmycc_1:c6ad224cdefc5e53bc261bb6b1fbed12b789225105f59373869b533067c9b009\022\006mycc_1" >
2023-11-15 02:11:26.587 UTC 0002 INFO [cli.lifecycle.chaincode] submitInstallProposal -> Chaincode code package identifier: mycc_1:c6ad224cdefc5e53bc261bb6b1fbed12b789225105f59373869b533067c9b009
注意合约的这个id后面要用
mycc_1:c6ad224cdefc5e53bc261bb6b1fbed12b789225105f59373869b533067c9b009
退出 cli1 容器,将打包的链码 mycc.tar.gz 从 cli1 容器中提取出来,并拷⻉到 虚拟机2的 multiple-deployment ⽬录下
exit
docker cp cli1:/opt/gopath/src/github.com/hyperledger/fabric/peer/mycc.tar.gz ./
scp -r mycc.tar.gz org2@192.168.5.112:/home/org2/go/src/github.com/hyperledger/fabric-samples/multiple-deployment
在虚拟机2查看我们已经收到了发送的打包后的链码
接下来是虚拟机2的操作
退出 cli1 容器,将 multiple-deployment ⽬录下的链码压缩包 mycc.tar.gz 复制到 cli1 ( 组织2 的 peer0 )容器中
exit
docker cp mycc.tar.gz cli1:/opt/gopath/src/github.com/hyperledger/fabric/peer/
# 进入容器查看
docker exec -it cli1 bash
ls
安装链码
peer lifecycle chaincode install mycc.tar.gz
两个组织都已经安装了链码,链码的id应该是一样的:mycc_1:c6ad224cdefc5e53bc261bb6b1fbed12b789225105f59373869b533067c9b009
3.2 授权与提交链码
虚拟机1,再次进⼊ cli1 容器,同意提交链码
docker exec -it cli1 bash
peer lifecycle chaincode approveformyorg --channelID mychannel --name mycc --version 1.0 --init-required --package-id mycc_1:c6ad224cdefc5e53bc261bb6b1fbed12b789225105f59373869b533067c9b009 --sequence 1 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
虚拟机2,进⼊ cli1 容器,同意提交链码
peer lifecycle chaincode approveformyorg --channelID mychannel --name mycc --version 1.0 --init-required --package-id mycc_1:c6ad224cdefc5e53bc261bb6b1fbed12b789225105f59373869b533067c9b009 --sequence 1 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
虚拟机1:
查看链码状态是否就绪
peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name mycc --version 1.0 --init-required --sequence 1 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --output json
提交链码
peer lifecycle chaincode commit -o orderer0.example.com:7050 --channelID mychannel --name mycc --version 1.0 --sequence 1 --init-required --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
3.3 与网络进行交互(合约的调用)
3.3.1 初始链码 – 虚拟机1
peer chaincode invoke -o orderer0.example.com:7050 --isInit --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n mycc --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"Args":["InitLedger"]}' --waitForEvent
对应的就是完成了下面的代码的功能
我们对账本进行了初始化,并且是在虚拟机1上的操作,现在想要验证一下虚拟机1的操作有没有在网络中进行同步,可以在虚拟机2上查看现在账本上的所有资产,是否是刚才初始化的那些资产。
3.3.2 在虚拟机2上查看一下当前的所有资产
进入容器后
peer chaincode invoke -o orderer0.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n mycc --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"Args":["GetAllAssets"]}' --waitForEvent# 控制台输出的资产
{\"AppraisedValue\":300,\"Color\":\"blue\",\"ID\":\"asset1\",\"Owner\":\"Tomoko\",\"Size\":5},{\"AppraisedValue\":400,\"Color\":\"red\",\"ID\":\"asset2\",\"Owner\":\"Brad\",\"Size\":5},{\"AppraisedValue\":500,\"Color\":\"green\",\"ID\":\"asset3\",\"Owner\":\"Jin Soo\",\"Size\":10},{\"AppraisedValue\":600,\"Color\":\"yellow\",\"ID\":\"asset4\",\"Owner\":\"Max\",\"Size\":10},{\"AppraisedValue\":700,\"Color\":\"black\",\"ID\":\"asset5\",\"Owner\":\"Adriana\",\"Size\":15},{\"AppraisedValue\":800,\"Color\":\"white\",\"ID\":\"asset6\",\"Owner\":\"Michel\",\"Size\":15}
通过结果得知,现在我们的操作已经在网络中同步了。
3.3.3 创建一个资产
创建资产CreateAsset(id string, color string, size int, owner string, appraisedValue int)
peer chaincode invoke -o orderer0.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n mycc --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"Args":["CreateAsset","asset7","red","15","Guandw","1000"]}' --waitForEvent
3.3.4 查看资产
peer chaincode invoke -o orderer0.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n mycc --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"Args":["GetAllAssets"]}' --waitForEvent
{“AppraisedValue”:300,“Color”:“blue”,“ID”:“asset1”,“Owner”:“Tomoko”,“Size”:5},{“AppraisedValue”:400,“Color”:“red”,“ID”:“asset2”,“Owner”:“Brad”,“Size”:5},
{“AppraisedValue”:500,“Color”:“green”,“ID”:“asset3”,“Owner”:“Jin Soo”,“Size”:10},{“AppraisedValue”:600,“Color”:“yellow”,“ID”:“asset4”,“Owner”:“Max”,“Size”:10},{“AppraisedValue”:700,“Color”:“black”,“ID”:“asset5”,“Owner”:“Adriana”,“Size”:15},{“AppraisedValue”:800,“Color”:“white”,“ID”:“asset6”,“Owner”:“Michel”,“Size”:15},
{\"AppraisedValue\":1000,\"Color\":\"red\",\"ID\":\"asset7\",\"Owner\":\"Guandw\",\"Size\":15}
通过结果我们在虚拟机2创建资产,然后再虚拟机1查看所有资产一样可以看到虚拟机2的操作在网络中同步了。我们的网络搭建也是没有问题的。
4. 关闭网络
如果要结束⽹络,可以在退出 cli1容器 后使⽤以下指令退出
docker-compose -f docker-compose-up.yaml down
如果需要清空容器的volume的话执行,慎重因为清空后无法重启,一般是用来格式化,重新启动容器创建通道
docker system df
docker volume rm $(docker volume ls -qf dangling=true)
相关文章:

Fabric多机部署启动节点与合约部署
这是我搭建的fabric的网络拓扑 3 个 orderer 节点;组织 org1 , org1 下有两个 peer 节点, peer0 和 peer1; 组织 org2 , org2 下有两个 peer 节点, peer0 和 peer1; 以上是我的多机环境的网络拓扑,使用的是docker搭建的。我的网络…...

WordPress主题WoodMart v7.3.2 WooCommerce主题和谐汉化版下载
WordPress主题WoodMart v7.3.2 WooCommerce主题和谐汉化版下载 WoodMart是一款出色的WooCommerce商店主题,它不仅提供强大的电子商务功能,还与流行的Elementor页面编辑器插件完美兼容。 主题文件在WoodMart Theme/woodmart.7.3.2.zip,核心在P…...

Java 高等院校分析与推荐系统
1)项目简介 随着我国高等教育的大众化,高校毕业生就业碰到了前所未有的压力,高校学生就业问题开始进入相关研究者们的视野。在高校学生供给忽然急剧增加的同时,我国高校大学生的就业机制也在发生着深刻的变化,作为就业…...

【JVM】Java虚拟机
本文主要介绍了JVM的内存区域划分,类加载机制以及垃圾回收机制. 其实JVM的初心,就是让java程序员不需要去了解JVM的细节,它把很多工作内部封装好了.但是学习JVM的内部原理有利于我们深入理解学习Java. 1.JVM的内存区域划分 JVM其实是一个java进程 ; 每个java进程,就是一个jvm…...

业务架构、技术架构、项目管理的有机结合
新入职的创业公司一年不行了。 这一年来没有上班,也因为大龄的问题找不到合适的工作。然后考了几个项目管理证书,又思考了一个技术兑现的问题。 技术本身是架构的执行层面,如果上面的公司战略、业务架构变小,缩水,或者…...

拜耳阵列(Bayer Pattern)以及常见彩色滤波矩阵(CFA)
一、拜耳阵列的来源 图像传感器将光线转化成电流,光线越亮,电流的数值就越大;光线越暗,电流的数值就越小。图像传感器只能感受光的强弱,无法感受光的波长。由于光的颜色由波长决定,所以图像传播器无法记录…...

【信息安全】浅谈IDOR越权漏洞的原理、危害和防范:直接对象引用导致的越权行为
前言 ┌──────────────────────────────────┐ │ 正在播放《越权访问》 - Hanser │ ●━━━━━━─────── 00:00 / 03:05 │ ↻ ◁ ❚❚ ▷ ⇆ └───────────────────────────────…...

uni-app 蓝牙打印, CPCL指令集使用
先上代码: GitHub - byc233518/uniapp-bluetooth-printer-demo: 使用uniApp 连接蓝牙打印机 Demo, CPCL 指令简单实用示例 (内含 芝珂,佳博,精臣 多个厂家指令集使用文档) 文件结构: ├── App.vue ├── CPCL 指令手册.pdf // 指令集参考手册 ├── LICENSE ├── R…...

vue-组件通信(二)
🌈个人主页:前端青山 🔥系列专栏:Vue篇 🔖人终将被年少不可得之物困其一生 依旧青山,本期给大家带来vue篇专栏内容:vue-组件通信(二) 目录 组件通信(二) (1) props / $emit 1. 父组件向子组…...

2023年【危险化学品经营单位安全管理人员】考试题及危险化学品经营单位安全管理人员模拟试题
题库来源:安全生产模拟考试一点通公众号小程序 危险化学品经营单位安全管理人员考试题是安全生产模拟考试一点通总题库中生成的一套危险化学品经营单位安全管理人员模拟试题,安全生产模拟考试一点通上危险化学品经营单位安全管理人员作业手机同步练习。…...

Uni-App常用事件
Uni-App是一个跨平台的前端开发框架,支持多个平台的应用开发,包括H5、小程序、App等。在Uni-App中,有许多常用的事件可以用来处理用户交互、页面生命周期等方面的逻辑。以下是一些Uni-App中常用的事件: 点击事件(click…...

【笔记 Pytorch】稀疏矩阵、scipy.sparse模块的使用
安装:pip install scipy 描述:就是专门为了解决稀疏矩阵而生。导入模块:from scipy import sparse 优缺点总结 七种矩阵类型描述coo_matrix ★【名称】coordinate format 【优点】 ① 不同稀疏格式间转换效率高(特别是CSR和CSC) …...

C#学习相关系列之Linq常用方法---排序(一)
一、构建数据 public class Student_1{public int ID { get; set; }public string Name { get; set; }public int Chinese { get; set; }public int Math { get; set; }public int English { get; set; }public override string ToString(){return string.Format("ID:{0},…...

Android Proguard混淆
关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 ,擅长java后端、移动开发、人工智能等,希望大家多多支持。 目录 一、导读二、概览三、语法规则3.1 输入/输出选项3.2 保留选项3.3 缩…...

MySQL 1、初识数据库
一、什么是数据库? 以特定的格式保存好的文件,我们就叫做数据库。 提供较为便捷的数据的存取服务的软件集合、解决方案,我们就叫它数据库。 存储数据用文件就可以了,为什么还要弄个数据库。 文件或数据库都可以存储数据&#…...

H5ke11--3介绍本地,会话存储
代码顺序: 1.设置input,捕获input如果有多个用属性选择符例如 input[typefile]点击事件.向我们的本地存储设置键值对 2.在点击事件外面设置本地存储表示初始化的值.点击上面的事件才能修改我们想修改的值 会话(session)浏览a数据可以写到本地硬盘,关闭页面数据就没了 本地(…...

技术分享 | 如何写好测试用例?
对于软件测试工程师来说,设计测试用例和提交缺陷报告是最基本的职业技能。是非常重要的部分。一个好的测试用例能够指示测试人员如何对软件进行测试。在这篇文章中,我们将介绍测试用例设计常用的几种方法,以及如何编写高效的测试用例。 ## 一…...

quarkus的一些注解1
path 用于指定一个类或者方法的URL路径前缀。 Inject 将一个依赖注入到一个类或方法中 Get 用于指定一个处理HTTP GET请求 Produce 注解用于指定一个方法返回的内容类型。例如,Produces(MediaType.TEXT_PLAIN) 表示该方法返回一个纯文本类型的内容 QuarkusIn…...

初学Redis(Redis的启动以及字符串String)
首先使用在Windows PowerShell中输入指令来启动Redis: redis-server.exe 然后通过指令连接Redis: redis-cli 上图的127.0.0.1是计算机的回送地址 ,6379是默认端口 上述代码中创建了两个键,注意Redis中严格区分大小写࿰…...

C++ opencv基本用法【学习笔记(九)】
这篇博客为修改过后的转载,因为没有转载链接,所以选了原创 文章目录 一、vs code 结合Cmake debug1.1 配置tasks.json1.2 配置launch.json 二、图片、视频、摄像头读取显示2.1 读取图片并显示2.2 读取视频文件并显示2.3 读取摄像头并写入文件 三、图片基…...

理财和银保区别
理财和银保在以下六个方面存在区别: 产品性质:银行理财是银行发行的理财产品,属于金融投资,主要投向债券、票据等固定收益类资产。银保产品是保险公司发行的保险产品,属于保障投资,除了固定收益类资产外&am…...

一文浅入Springboot+mybatis-plus+actuator+Prometheus+Grafana+Swagger2.9.2开发运维一体化
Swagger是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTFUL风格的Web服务,是非常流行的API表达工具。 Swagger能够自动生成完善的 RESTFUL AP文档,,同时并根据后台代码的修改同步更新,同时提供完整的测试页面来调试API。 Prometheus 是一个开源的服务监控系统和时…...

【日常】爬虫技巧进阶:textarea的value修改与提交问题(以智谱清言为例)
序言 记录一个近期困扰了一些时间的问题。 我很喜欢在爬虫中遇到问题,因为这意味着在这个看似简单的事情里还是有很多值得去探索的新东西。其实本身爬虫也是随着前后端技术的不断更新在进步的。 文章目录 序言Preliminary1 问题缘起1.1 Selenium长文本输入阻塞1.2…...

C++知识点总结(6):高精度乘法真题代码
一、高精度数 低精度数 #include <iostream> #include <cstring> using namespace std;int main() {// 存储并输入两个数字 char a_str[1005] {};long long b;cin >> a_str >> b;// 特例先行:结果是0的情况if (a 0 || b 0){cout <&…...

Polygon zkEVM的Dragon Fruit和Inca Berry升级
1. Polygon zkEVM的Dragon Fruit升级 2023年8月31日,Polygon zkEVM团队宣称启动了其Mainnet Beta的Dragon Fruit升级的10天timelock,预计将于2023年9月11日激活。 Dragon Fruit升级点有: 改进了网络支持了最新的以太坊opcode——PUSH0 1.…...

【计算机网络学习之路】网络基础1
文章目录 前言一. 计算机网络发展局域网和广域网 二. 网络协议三. OSI七层模型四. TCP/IP四层(五层)模型五. 计算机体系结构与网络协议栈六. 协议形式及局域网通信数据包封装与分用 七. 跨网络通信八. MAC地址与网络通信的理解结束语 前言 本系列文章是…...

HTTP/2.0协议详解
前言 HTTP/2.0:互联网通信的革新标准 随着互联网技术的飞速发展,HTTP协议作为互联网应用最广泛的通信协议,也在不断演进和优化。HTTP/2.0是HTTP协议的最新版本,它旨在提供更高效、更安全、更快速的互联网连接。 一、HTTP/2.0的优…...

Python中的Random模块详解:生成随机数与高级应用
在Python编程中,随机数生成是许多应用的基础之一。random模块为我们提供了生成伪随机数的丰富工具,从简单的随机数生成到复杂的应用场景,都有很多功能可以探索。本文将深入介绍random模块的各个方面,通过详实的示例代码࿰…...

(论文阅读32/100)Flowing convnets for human pose estimation in videos
32.文献阅读笔记 简介 题目 Flowing convnets for human pose estimation in videos 作者 Tomas Pfister, James Charles, and Andrew Zisserman, ICCV, 2015. 原文链接 https://arxiv.org/pdf/1506.02897.pdf 关键词 Human Pose Estimation in Videos 研究问题 视频…...

【设计一个缓存--针对各种类型的缓存】
设计一个缓存--针对各种类型的缓存 1. 设计顶层接口2. 设计抽象类 -- AbstractCacheManager3. 具体子类3.1 -- AlertRuleItemExpCacheManager3.2 -- AlertRuleItemSrcCacheManager 4. 类图关系 1. 设计顶层接口 // 定义为一个泛型接口,提供给抽象类使用 public interface Cach…...