通过Docker搭建4节点的Tendermint集群

news2024/9/22 5:31:26

Tendermint:0.34.24
Docker:20.10.21
Docker-Compose:2.20.2
OS:Ubuntu 20.04
Go:1.19.2 Linux/amd64

1 修改Tendermint源码

1.1 修改监听IP

为什么要将127.0.1修改成0.0.0.0呢?因为容器内的服务如果是以127.0.0.1暴露的话,外部是无法通过端口映射访问docker容器内对应服务的。
127.0.0.1是一个特殊的IP地址,称为本地回环地址,只能用于在同一台计算机上的进程之间进行通信。当您将服务绑定到127.0.0.1地址时,它将只能在本机进行访问,无法通过外部网络访问该应用程序。
在这里插入图片描述

1.2 不产生空区块

在这里插入图片描述

1.3 统一ChainID

在这里插入图片描述

1.4 修改AddBookStrict为false,用来支持局域网通信

在这里插入图片描述

2 编译生成二进制可执行文件

make install
make install_abci

3 编写dockerfile定制镜像

FROM ubuntu
ENV MYPATH /usr/local
WORKDIR $MYPATH
ADD ./tendermint $MYPATH
ADD ./abci-cli $MYPATH
RUN apt update
RUN apt install curl

注意要将abci-cli和tendermint可执行文件与dockerfile文件放在同一目录下:
在这里插入图片描述
查看定制的docker镜像:
在这里插入图片描述

4 编写docker-compose编排容器

网络采用桥接模式,并对每个节点的RPC服务端口26657进行外部映射。

version: "3"
services:
        node0:
                image: tm
                container_name: node0
                ports:
                        - "26657:26657"
                volumes:
                        - /usr/local/node0:$HOME/.tendermint
                networks:
                        mynet:
                                ipv4_address: 172.20.20.0
                command: 
                        - /bin/bash
                        - -c
                        - |
                                ./tendermint init
                                ./tendermint show-node-id > $HOME/.tendermint/nodeid.txt
                                ./abci-cli kvstore

        node1:
                image: tm
                container_name: node1
                ports:
                        - "36657:26657"
                volumes:
                        - /usr/local/node1:$HOME/.tendermint
                networks:
                        mynet:
                                ipv4_address: 172.20.20.1
                command:
                        - /bin/bash
                        - -c
                        - |
                                ./tendermint init
                                ./tendermint show-node-id > $HOME/.tendermint/nodeid.txt
                                ./abci-cli kvstore


        node2:
                image: tm
                container_name: node2
                ports:
                        - "46657:26657"
                networks:
                        mynet:
                                ipv4_address: 172.20.20.2
                volumes:
                        - /usr/local/node2:$HOME/.tendermint
                command:
                        - /bin/bash
                        - -c
                        - |
                                ./tendermint init
                                ./tendermint show-node-id > $HOME/.tendermint/nodeid.txt
                                ./abci-cli kvstore


        node3:  
                image: tm
                container_name: node3
                ports:
                        - "56657:26657"
                networks:
                        mynet:
                                ipv4_address: 172.20.20.3
                volumes:  
                        - /usr/local/node3:$HOME/.tendermint
                command:
                        - /bin/bash
                        - -c
                        - |
                                ./tendermint init
                                ./tendermint show-node-id > $HOME/.tendermint/nodeid.txt
                                ./abci-cli kvstore
networks:
        mynet:
                ipam:
                        driver: default
                        config:
                                - subnet: 172.20.0.0/16

启动容器:
docker-compose up -d
在这里插入图片描述

5 统一的genesis.json

因为容器卷的缘故,宿主机本地可以直接查看每个节点的config和data目录。
集群要求每个节点的genesis.json文件完全相同,并且包含所有节点的validator信息。
这里通过一个简单的Python脚本快速构建统一的genesis.json文件:

linesArr = []

for i in range(0, 4):
    f = open("/usr/local/node%d/config/genesis.json" % i, 'r')
    linesArr.append(f.readlines())
    f.close()

f = open("./genesis.json", 'w')

for i in range(len(linesArr)):
    lines = linesArr[i]

    if i == 0:
        for j in range(23):
            f.write(lines[j])

    for j in range(23, 32):
        if i == len(linesArr) - 1:
            f.write(lines[j])
        else:
            if j < 31:
                f.write(lines[j])
            else:
                f.write(lines[j][:len(lines[j]) - 1])
                f.write(",\n")

for i in range(32, len(linesArr[0])):
    f.write(linesArr[0][i])

f.close()

生成的统一的genesis.json创世文件:

{
  "genesis_time": "2024-01-06T02:17:15.806171802Z",
  "chain_id": "test-chain",
  "initial_height": "0",
  "consensus_params": {
    "block": {
      "max_bytes": "22020096",
      "max_gas": "50",
      "time_iota_ms": "1000"
    },
    "evidence": {
      "max_age_num_blocks": "100000",
      "max_age_duration": "172800000000000",
      "max_bytes": "1048576"
    },
    "validator": {
      "pub_key_types": [
        "ed25519"
      ]
    },
    "version": {}
  },
  "validators": [
    {
      "address": "6DE6C6F2CD5AD081A1B6C7A87FC915E04B1E2219",
      "pub_key": {
        "type": "tendermint/PubKeyEd25519",
        "value": "iKt2epWBuZHFayrS4qb7AJAwbfSlrJxOsLSbwwsUn9A="
      },
      "power": "10",
      "name": ""
    },
    {
      "address": "5993A76300771C1EF633D6801FF53D5B6527127A",
      "pub_key": {
        "type": "tendermint/PubKeyEd25519",
        "value": "uGc87MkuEtnMTcIQGUD22mNdTAQ7400FDqtIOkctbDg="
      },
      "power": "10",
      "name": ""
    },
    {
      "address": "039D64F5C23FD4CA0E4563B282B0B6F96CE278CB",
      "pub_key": {
        "type": "tendermint/PubKeyEd25519",
        "value": "FWFS6CuHP+iOk8tktKfMm1A8WJIldFP+chjDj9AbD78="
      },
      "power": "10",
      "name": ""
    },
    {
      "address": "73BFE884FB6C97F170FED9A9699EDB1B3E5341C4",
      "pub_key": {
        "type": "tendermint/PubKeyEd25519",
        "value": "xpPW7WNXZYJnUCOLT/Uv1czyfLEhpiDo7jN/DS/Ad2s="
      },
      "power": "10",
      "name": ""
    }
  ],
  "app_hash": ""
}

覆盖掉原来的genesis.json文件:
在这里插入图片描述

6 启动集群

如果没在docker-compose手动指定各容器的IP,则通过docker inspect查询各容器的IP:
在这里插入图片描述
查看每个节点的nodeID,由于容器卷以及容器启动时会将nodeID重定向到nodeid.txt文件,我们在宿主机本地就能够访问。
在这里插入图片描述

最后构造出统一的启动命令:
./tendermint node --p2p.persistent_peers=“15352fccfb6a2a177fa18253bfb4bd6cd71c0894@172.20.20.0:26656,c61f1ed46fef14b5d518dbe5f9831134cba72518@172.20.20.1:26656,891df109a91fb4fc97c936594aa694206fdbb8de@172.20.20.2:26656,fba18b7bc2d04a6a5aac41a40ab5f230be51b031@172.20.20.3:26656”

7 验证集群是否启动成功

7.1 第一种验证方式:

在这里插入图片描述
可以看到,node2的peer数量为3

7.2 第二种验证方式:

向node0发送一条name=jackie的交易:
在这里插入图片描述

分别从node1、node2、node3查询交易,得到的结果是base64格式:
在这里插入图片描述

对返回的结果进行base64解码:
在这里插入图片描述
不过,通过命令行提交交易太繁琐了,我们干脆写个简单的测试程序,向node0提交500个交易:

func main() {
	cli, err := http.New("http://localhost:26657", "/websocket")
	if err != nil {
		panic(err)
	}
	for i := 0; i < 500; i++ {
		_, err = cli.BroadcastTxAsync(context.TODO(), types.Tx(strconv.Itoa(i)))
		if err != nil {
			panic(err)
		}
	}
}

会发现四个节点的区块全部同步到同一个高度:
在这里插入图片描述
如果我们让节点node0宕机,会发现其他三个节点会打印出node0宕机的信息:
在这里插入图片描述
最后优雅关闭所有容器:
在这里插入图片描述

至此。

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

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

相关文章

springboot学习笔记(杂)

springboot学习笔记 1.注解框架学习 2.各个类之间的继承和实现关系3.理解面向对象的思想(其实这个想写在2中的)4.开发常用工具Lombok4.0说在前面(如何快速使用Lombok)4.1了解Lombok4.2Lombok的作用一:减少代码冗余4.3Lombok的作用二:方便打日志4.4Lombok使用方法(各个注解作用)…

Linux shell jq工具操作文档(jq --help使用示例)

文章目录 jq工具介绍jq --help解读英文中文 使用示例1. 使用最简单的过滤器。将输入复制到输出&#xff0c;不做任何修改&#xff08;除了格式化&#xff09;2. 使用 -c 选项进行紧凑输出而非美化输出3. 使用 -n 选项以 null 作为单一输入值&#xff08;用于创建新json&#xf…

JS逆向之无限debugger对抗

文章目录 JS中实现debugger的方法无限Debugger示例Demo1Demo2Demo3Demo4总结 无限Debugger实战 JS中实现debugger的方法 首先&#xff0c;我们要知道&#xff0c;在浏览器实现debugger的方法有哪些 debugger关键词 &#xff0c;相当于C内联汇编的int3&#xff0c;在代码中嵌入…

进阶学习——Linux网络

目录 一、网络配置命令 1.ifconfig——IP地址 1.1ifconfig的基础用法 1.1.1ifconfig命令详解 1.2常用格式 1.3修改网卡名称 1.3.1临时修改 1.3.2永久修改 1.4临时修改网卡 1.4.1设置虚拟网卡 1.4.2延伸——ethtool 1.5永久修改网卡 1.6实验 —— 双网卡配置 1.…

C++ Primer 第五版 中文版 阅读笔记 + 个人思考

C Primer 第五版 中文版 阅读笔记 个人思考 第 10 章 泛型算法10.1 概述练习10.1练习10.2 第 10 章 泛型算法 泛型的体现&#xff1a;容器类型&#xff08;包括内置数组&#xff09;&#xff0c;元素类型&#xff0c;元素操作方法。 顺序容器定义的操作&#xff1a;insert&a…

计算机丢失mfc140.dll怎么办?解决mfc140.dll缺失的3种方法分享

计算机丢失mfc140.dll怎么办&#xff1f;在使用微软办公软件的时候&#xff0c;可能会弹出一个错误提示框说“找不到mfc140.dll&#xff0c;无法继续执行代码”。为了不影响工作效率&#xff0c;我们可能需要亲自动手尝试修复这一问题。以下是一些mfc140.dll缺失的3种方法相关介…

鸿蒙开发DevEco Studio搭建

DevEco Studio 安装 DevEco Studio 编辑器 下载&#xff1a;https://developer.harmonyos.com/cn/develop/deveco-studio#download Windows(64-bit)Mac(X86)Mac(ARM) 安装&#xff1a;DevEco Studio → 一路 Next运行&#xff1a; 基础安装&#xff1a;Node.js > 16.9.1…

powerdesigner导出sql将name放到comment注释上

1. 批量设置 2. 脚本 Option Explicit ValidationMode True InteractiveMode im_Batch Dim mdl the current modelget the current active model Set mdl ActiveModel If (mdl Is Nothing) ThenMsgBox"There is no current Model " ElseIf Not mdl.IsKindOf(PdPD…

数据结构-函数题

6-2.求二叉树的高度 本题要求给定二叉树的高度。 函数接口定义&#xff1a; int GetHeight( BinTree BT ); typedef struct TNode *Position; typedef Position BinTree; struct TNode{ElementType Data;BinTree Left;BinTree Right; }; 要求函数返回给定二叉树BT的高度值…

Tomcat源码解析(一): Tomcat整体架构

Tomcat源码系列文章 Tomcat源码解析(一)&#xff1a; Tomcat整体架构 目录 一、Tomcat整体架构1、Tomcat两个核心组件功能2、Tomcat支持的多种I/O模型和应用层协议 二、Connector连接器1、连接器功能汇总2、ProtocolHandler组件2.1、Endpoint2.2、Processor 3、Adapter组件 三…

Realm Management Extension领域管理扩展之安全状态

RME基于Arm TrustZone技术。TrustZone技术在Armv6中引入,提供以下两个安全状态: 安全状态(Secure state)非安全状态(Non-secure state)以下图表显示了在AArch64中的这两个安全状态以及通常在每个安全状态中找到的软件组件: 该架构将在安全状态运行的软件与在非安全状态运…

MySQL之导入、导出

文章目录 1.navicat导入导出2.mysqldump命令导入导出2.1导出2.2导入 3.load data infile命令导入导出4.远程备份5.思维导图 1.navicat导入导出 使用Navicat工具导入t_log 共耗时 55s 2.mysqldump命令导入导出 2.1导出 导出表数据和表结构 语法&#xff1a; mysqldump -u用…

sentinel入门,转载的,不记得在哪复制的了

sentinel 基本概念 开发的原因&#xff0c;需要对吞吐量&#xff08;TPS&#xff09;、QPS、并发数、响应时间&#xff08;RT&#xff09;几个概念做下了解&#xff0c;查自百度百科&#xff0c;记录如下&#xff1a; 响应时间(RT)   响应时间是指系统对请求作出响应的时间。…

网工内推 | 运维工程师,国企、上市公司,RHCE认证优先

01 广东机场白云信息科技股份有限公司 招聘岗位&#xff1a;基础架构运维工程师&#xff08;中级&#xff09; 职责描述&#xff1a; 1、参与公司业务系统的监控、巡检、维护、故障定位、原因分析&#xff1b; 2、负责业务系统的上线、升级割接工作&#xff1b; 3、负责服务器…

kubectlkubeletrancherhelmkubeadm这几个命令行工具是什么关系?

背景 在最近学习k8s的过程中&#xff0c;发现kubectl&kubelet&rancher&helm&kubeadm这几个命令怎么在交错使用&#xff0c;他们究竟是什么关系&#xff1f;他们分别应该在什么情况下使用呢&#xff1f;这里我进行了简单的总结&#xff0c;做个区分。 各工具说…

HarmonyOS 应用开发学习笔记 ets组件生命周期

HarmoryOS Ability页面的生命周期 Component自定义组件 ets组件生命周期官放文档 本文讲解 ets组件的生命周期&#xff0c;在此之前大家可以先去了解Ability的生命周期&#xff0c;这两个生命周期有有一定的关联性 在开始之前&#xff0c;我们先明确自定义组件和页面的关系&…

互斥、自旋、读写锁的应用场景

互斥、自旋、读写锁的应用场景 锁&#x1f512;1、互斥锁、自旋锁2、读写锁&#xff1a;读写的优先级3、乐观锁和悲观锁总结&#xff1a; 锁&#x1f512; ​ 多线程访问共享资源的生活&#xff0c;避免不了资源竞争而导致错乱的问题&#xff0c;所以我们通常为了解决这一问题…

YOLO物体检测-系列教程6:YOLOv5源码解析1

计算机视觉 全教程 目录 物体检测 系列教程 总目录 1、基本概述 YOLOv5没有一篇对应的论文&#xff0c;是一个对v4更好的实现v5版本是一个在github更新的基于工程项目的实现基本上和v4没有差异&#xff0c;只不过在整个项目上做出了更好的实现效果主要基于github的文档介绍来…

Selenium 学习(0.19)——软件测试之基本路径测试法——拓展案例

1、案例 请使用基本路径法为变量year设计测试用例&#xff0c;year的取值范围是1000<year<2001。代码如下&#xff1a; 2、步骤 先画控制流程图 再转化为控制流图&#xff08;标出节点&#xff09; V(G) 总区域数 4 V(G) E - N 2 (边数 - 节点数 2…

独占锁ReentrantLock的原理

类图结构 ReentrantLock是可重入的独占锁&#xff0c;同时只能有一个线程可以获取该锁&#xff0c;其他获取该锁的线程会被阻塞而被放入该锁的AQS阻塞队列里面。 首先看下ReentrantLock的类图以便对它的实现有个大致了解。 从类图可以看到&#xff0c;ReentrantLock最终还是使…