《区块链底层设计Java实战》之第四章P2P 网络构建
第4 章 P2P 网络构建
叫嚣乎东西 隳突乎南北
第4 章 P2P 网络构建 ......................................................................................... 64
4.1 P2P 简介 ................................................................................................... 65
4.2 区块链P2P 网络实现技术总结 .............................................................. 66
4.3 基于WebSocket 构建P2P 网络 .............................................................. 68
4.3.1 WebSocket 介绍 ........................................................................... 68
4.3.2 基于WebSocket 构建P2P 网络 .................................................. 69
4.4 基于t-io 构建P2P 网络 ........................................................................... 78
4.4.1 t-io 介绍 ........................................................................................ 78
4.4.2 t-io 的主要用法 ............................................................................ 80
4.4.3 基于t-io 构建P2P 网络 ............................................................... 83
4.5 小结 ........................................................................................................... 96
第3 章讲述了区块链系统中的基石之一密码学在区块链系统中的应用,本章将
介绍区块链系统的另一个基石——P2P 网络的构建。
在常见的分布式服务中,实现不同节点间的高效通信是一项基础技术。同理,
区块链系统作为分布式服务的一种,不同区块链节点间的高效通信同样非常重要。
P2P 通信网络是区块链系统中数据传输、共识达成一致的基础。本章将从P2P 的概
念和历史发展讲起,逐步介绍比特币和以太坊中P2P 网络的构建,最后重点介绍类
似比特币的P2P 网络构建方法。
4.1 P2P 简介
P2P 即Peer-to-Peer,最早起源于1997 年。这一年,Hotline Communications 公司
研制了能让用户从别人电脑中下载内容的软件,这便是最早的P2P。当时P2P 网络
一词的定义也与此相关,即P2P 网络是一类允许一组用户互相连接并直接从用户硬
盘上获取文件的网络。Hotline 也曾一度成为P2P 网络的代名词,曾有文章以“Hotline
– The Glory Days Of P2P”为题介绍当时的盛况。
随着互联网技术的发展,P2P 演化成了一种分布式网络。在分布式网络中,网络
的各个节点,无论是机构还是个人,可以共享他们所拥有的一部分软、硬件资源,
如数据处理能力、信息存储能力、互联网连接能力、打印机等。在P2P 分布式网络
中,这些共享资源能被其他对等节点(peer)直接访问,无须经过中间的服务器。
此网络中的每个节点都是双重身份,既是服务和内容等共享资源的提供者
(server),又是服务和内容等资源的获取者(client)。
从上面的描述可以总结出P2P 分布式网络的特点如下:
(1)无中央服务器,打破了C/S 模式。
(2)用户之间互联并可以分享文件。
随着技术的发展,P2P 技术和P2P 网络的好处(即资源能得到充分利用和最大
化的共享)在不断涌现的大量应用中得以体现。对此,Microsoft 在“Introduction to
Windows Peer-to-Peer Networking”一文中总结了部分应用情景,如即时通信应用,
包括生活中我们熟悉的QQ、微信等场景。
此外,P2P 的应用还包括文件共享类的P2P 网络服务,如Napster、Gnutella、
eDonkey、emule、BitTorrent 等;提供挖掘P2P 对等计算能力和存储共享能力的应用,
如SETI@home、Avaki、Popular Power 等;基于P2P 方式的协同处理与服务共享平
台,如JXTA、Magi、Groove 等。
在P2P 分布式网络中,其核心在于数据存储在客户端本地,同时提供本地存储
信息的查询服务,让网络中各个节点之间能直接进行数据传递,数据传递可以通过
文件的名称、文件的地址等实现。
此外,P2P 分布式网络中,数据流量得到了分流,管理节点也不再有服务容量的
压力,只需存储数据相关的索引与链接等内容即可,如IPFS 文件系统就是基于P2P
分布式网络的一种实现,在这个系统中可以百度搜索相关网址。
4.2 区块链P2P 网络实现技术总结
在区块链领域,不同的公链系统所使用的P2P 网络技术大不相同。国内迅雷发
布的区块链文件系统TCFS 是基于IPFS 实现的,比特币系统的 P2P 网络是无结构的,
而以太坊的 P2P 网络是有结构的。
在以太坊中,P2P 网络主要采用Kademlia 算法实现,Kademlia 是分布式散列表
(Distributed Hash Table,DHT)技术的一种。借助该技术,以太坊系统实现了在分布
式环境下快速准确地路由和定位数据。
分布式散列表是一个由广域网内大量节点共同维护的巨大散列表。这张散列表
被分割成不连续的块,每个节点被分配给一个属于自己的散列块,并成为这个散列
块的管理者。DHT 的节点是动态的,在节点中,通过加密散列函数,对象的名字或
关键词就可以被映射为128 位或160 位的散列值。目前,Tapestry、Chord、CAN 和
Pastry 都使用了分布式散列表技术。
当然,不同结构的P2P 网络,有不同的优点和缺点。比特币系统的网络结构是
最容易理解、最容易实现的一种形式,而以太坊网络引入了分布式散列表、异或距
离、二叉前缀树、K-桶等,结构上更复杂,实现起来也更困难,但在节点路由上要
远快于比特币,本质上属于空间换时间的做法。
在本书中,我们会实现类似比特币系统中所用的网络结构。
网络编程可能是不少研发人员的弱项,甚至不少研发人员会感觉到陌生。不过,
无须过多担心!在Java 领域中,可用于实现网络编程或者远程通信的技术种类繁多,
如传统技术中的Socket 编程、RMI(Remote Method Invocation,远程方法调用)、RPC
(Remote Procedure Call,远程过程调用)、Apache Mina(一个基于TCP/IP、UDP/IP
协议栈的通信框架)、Hessian(一个轻量级的remoting onhttp 工具)、JMS(Java Message
Service,Java 消息服务)、Netty(JBOSS 提供的一个Java 版网络服务器和客户端程
序开源框架)、WebService(如HTTP)等。
当然,除了这些基础技术,比较新的技术也是可以用于远程通信的。如
WebSocket、Vert.x、t-io、J-IM、http-kit、netty-socketio、async-http-client 等。其中,
WebSocket 是HTML5 中的新协议;Vert.x(网址:http://vertx.io/)是一个基于JVM、
轻量级、高性能的应用平台,基于全异步Java 服务器Netty;t-io 是基于Java Aio 的
网络编程框架,号称可以让天下没有难开发的网络编程;J-IM 是用Java 编写的,基
于t-io 开发的轻量级、高性能网络框架。
以上这些技术可以在公链、联盟链、私链中构建节点间的通信。但在联盟链或
私链的多个节点中,由于是部分去中心化的部署方式,因此技术选型的空间更多、
更大。我们可以基于MQ 或Kafka 等中间件实现消息的发布订阅,即联盟链中各个
节点可以共同订阅相同的topic,节点需要达成共识或同步数据时,向该topic 推送不
同类型的消息即可,包括该节点在内的所有节点均可以通过订阅topic 来实现消息的
接收并进行相应处理。
在上述这些技术中,Socket 编程是最基础的Java 技术,而WebService(如HTTP)、
RPC(Remote Procedure Call,远程过程调用)的方式可能对分布式服务开发的小伙
伴而言相对较为熟悉。一般,Web 服务器在普通阿里云或腾讯云服务器中可以支持
上万个HTTP 连接或WebSocket 连接。因此在联盟链中使用WebService 或RPC 完全
没有问题。
此时,在联盟链中,通过区块链底层管理后台,我们可以获取各个节点部署服
务器的公网IP。因此我们可以基于HTTP 或RPC(如ProtoBuffer、Thrift)构建节点
的通信网络。即客户端发消息时,遍历所有节点公网IP 列表,分别向这些服务器发
送HTTP 请求或RPC 请求;同时,由于各个节点都部署了对应的服务端程序,因此
可以对收到的HTTP 请求或RPC 请求进行处理。
当使用HTTP 协议构建节点的通信网络时,还可以使用HTTP 2.0 协议。2017 年,
Java 9 和Spring Boot 2.0 开始支持HTTP 2.0 协议,Tomcat 9 于2018 年8 月17 日也
支持了HTTP 2.0。HTTP 2.0 中的反向推送(Server Push)功能极大地简化了基于HTTP
1.1 版本的开发工作量。
虽然P2P 网络通信实现技术有所差异,但原理基本一致。本质上,P2P 网络中
各节点的通信就是字节将流从一台服务器传送到另外一台服务器的过程,基于传输
协议(如HTTP、TCP、UDP 等协议)和网络I/O 来实现。而HTTP、TCP、UDP 其
实都是基于Socket 实现的。
由于WebService、RPC、MQ 和Kafka 等技术在分布式服务应用开发中很常见,
因此本书不再过多阐述其用法。而在大部分分布式服务应用场景中鲜见使用Socket、
Mina、Netty 等技术,因此本书不会从最原始的Socket 实现,也不会基于Netty 实现,
而是基于研发人员较为熟悉的、新的技术,如WebSocket 技术,和相对不熟悉但很
容易上手且应用场景较为广泛的t-io 组件来实现,借此机会帮助读者拓展实用技术
栈。
4.3 基于WebSocket 构建P2P 网络
4.3.1 WebSocket 介绍
WebSocket 是HTML5 提出的一个协议规范。
WebSocket 约定了通信的规范,通过握手机制,客户端(如浏览器和服务器)之
间建立一个类似TCP 的长连接,从而方便客户端和服务端之间的通信,特别是服务
端能主动向客户端推送消息。在WebSocket 协议出现之前,Web 交互一般是基于HTTP
的短连接或者长连接实现的,甚至是最原始的轮询或Comet 方式。正是因为
WebSocket 实现了浏览器与服务器的全双工通信,才真正实现了Web 的实时通信。
WebSocket 的工作流程大致如下:浏览器通过JS 代码(JavaScript 代码)向服务
端发出建立WebSocket 连接的请求。在WebSocket 连接建立成功后,客户端和服务
端就可以通过 TCP 连接传输数据了。
下面将介绍基于WebSocket 如何构建P2P 网络。
4.3.2 基于WebSocket 构建P2P 网络
代码详见书中
4.4 基于t-io 构建P2P 网络
4.4.1 t-io 介绍
t-io/tio 是一个网络编程框架,或称为TCP 长连接框架,其官方网站中宣称,
t-io/tio 不仅仅是百万级TCP 长连接框架。
基于t-io 可以开发IM、TCP 私有协议、RPC、游戏服务器端、推送服务、实时
监控、物联网、UDP、Socket 等将会变得空前的简单。
目前,t-io/tio 的代码已在码云的开源平台中开源。在2017 年码云首批最有价值
开源项目评选中,t-io 上榜,码云平台为其颁发了证书,如图4-3 所示。
那么t-io 是什么样的工具类呢?按官网的介绍,我们总结如下:
t-io 一般是指tio-core,它是基于Java AIO 的网络编程框架,和Netty 属于同类。
t-io 家族除tio-core 外,还有tio-websocket-server、tio-http-server、tio-webpack-core、
tio-flash-policy-server 等,后面所列都是基于tio-core 开发的应用层组件。下面分别介
绍t-io 家族的各个成员,其中:
tio-core:基于Java AIO 的网络编程框架。使用示例是tio-showcase。
tio-websocket-server:基于tio-core 开发的WebSocket 服务器。使用示例是
tio-websocket-showcase。
tio-http-server : 基于tio-core 开发的HTTP 服务器。使用示例是
tio-http-server-showcase
tio-webpack-core:基于tio-core 开发的JS/CSS/HTML 编译压缩工具。
tio-flash-policy-server:基于tio-core 开发的flash-policy-server。
4.4.2 t-io 的主要用法
下面介绍t-io 常用类。t-io 常用类主要有ChannelContext、GroupContext、
AioHandler、AioListener、Packet、AioServer 和AioClient。其中,ChannelContext 是
通道上下文相关的类,GroupContext 用于服务配置与维护,AioHandler 是消息处理接
口,AioListener 是通道监听者,Packet 是应用层的数据包,AioServer 是t-io 服务端
的入口类,AioClient 是t-io 客户端的入口类,具体介绍如下。
代码详见书中