p2sp设计需要考虑的几点问题整理

p2p是peer-to-peer的简称,以前对它的了解主要来自BT下载工具,通过p2p技术我们能够更加方便地分享与下载文件资源。这些天看了一些资料,才知道在分布式计算,即时通信领域p2p技术也应用广泛,skype,QQ,pplive等常用的软件也是用了p2p技术。p2sp核心大体也是p2p的内容,只是多了一个中心用来调度或者提供服务的服务器,我们来看看简单设计一个P2SP的文件分享系统需要考虑的问题。

当然要再实现一个P2P私有协议复杂度很高,涉及算法、加密、安全性、可用性等很多问题,估计我是弄不出来的,这里只是从业务上来看看设计实现一个类似Napster的软件需要考虑的几点问题(当然Napster也不是P2P,它仍需要一个中心协调机制,属于典型的P2SP吧)。

一个文件分享的业务包含下面几点
1,客户端登录时,与服务器通信,更新其网络信息(IP与端口)与本地数据资源列表给服务器,并开启服务功能。
2,上传时,客户端B通过软件 上传文件file1成功后,服务器S记录下B的IP地址以及开放的端口信息
a,如果服务器S上已经存在此文件(检测方法比如通过计算文件md5值去服务器S查询比较),则只需添加一条标识文件file1的位置信息即可(同时可以不再上传此文件)
		file1 => file_info (table)
			Server: 	192.168.0.1
			Client A:	192.168.0.10:10000	(Uploaded by Client A)
			Client B:	192.168.0.11:10001	(Insert)
b,如果服务器S上不存在此文件,则在服务器端创建一条新记录
		file1 => file_info (table)
			Server:		192.168.0.1			(Create)
			Client B:	192.168.0.11:10001	(Create)
3,下载时,客户端E需要下载文件file2,首先与服务器S交互,获取到file2的存放地址Server,Client C,Client D(如上所示)
然后E客户端可以并发多个连接分别从3个位置获取文件(这里当然需要考虑各分片安排,速度调整等策略,此处不做分析)
如果Server,Client D都可以下载,而Client C下载失败,则更新Client C下载失败的次数( 次数多到一个阈值则认为file2不在Client C上了,通知服务器删除file_info中对应信息
当然 下载成功后继续添加Client E到file_info表内
		file2 => file_info (table)
			Server: 	192.168.0.1
			Client C:	192.168.0.12:10002	(Shall delete or not)
			Client D:	192.168.0.13:10001	(Already exised)
			Client E:	192.168.0.14:10002	(Insert)

(客户端需要搜集各个位置的传输分片大小,失败次数等反馈给服务器S,以便做速度可用性的优先级调整,并发下载当然需要保证最终文件是完整正确的,可以通过计算下载副本md5值与服务器比对得知)

4,为了防止客户端出现异常或者客户端网络环境断掉,客户端应定期发送心跳包给服务器,未获取到心跳一定次数后认为客户端断开。

5,客户端登出时,通知服务器关闭它的服务功能。


一些扩展的问题

A,上面我假定IP地址以及端口信息不变,如果是在广域网或者DHCP开启情况下,我们的file_info表中存放的应该是用户信息(简单标识哪些用户拥有此文件副本),然后再关联一个user_info表去更新各个用户的IP地址以及端口号(比如客户端在登录时通知服务器更新自己的IP和端口)。

B,如果是在跨局域网,存放的应该是用户的外网IP地址以及端口信息,此时需要利用到UDP穿透技术(或者TCP穿透技术,不过后者实现起来麻烦很多,毕竟多了三次握手的过程)UDP传输则需要在应用程序中控制数据的完整性。

C,P2P传输需要一个可靠的网络拓扑结构,尽量找距离下载客户端邻近的网络节点提供服务,比如针对A客户端按照距离它网络远近顺序分别为B,C,D提供下载服务。

D,其他问题:客户端升级后要保证能和以前版本客户端兼容。这个需要考虑很多方面的设计,这是题外话了。


更复杂的P2P技术问题

1,由于失去服务器端的控制, p2p传输如果存在漏洞,很容易被病毒利用传输。而且UDP打洞技术能绕过“防火墙”,病毒利用到P2P通信很容易攻击到别的客户机。
2,Nat(网络地址转换)的种类有很多,需要根据不同的情况选择数据传输的方案,比如判断是否可以进行UDP穿透等。(如果客户端的环境封掉了p2p应用,那要保证至少能从服务器上下载)所以 需要获取更多的用户环境信息

3,上面的p2sp设计并没有充分利用到p2p技术的优点,因为比如客户端B,C同时下载一个文件,它们只会在下载完毕后才能在服务器上记录它们的信息,原本按照p2p的设计,应该是B和C分别下载一部分分片,然后彼此分享。不过这种设计就要麻烦太多了,还没有头绪。

4,p2sp相比p2p有个明显的缺点,就是如果中心服务器S被攻击,整个系统都不能正常运转,所以要特别注意。


关于UDP穿透

我原本想着为每个客户端都安装一个Web服务,互相之间仅仅通过Http协议传输数据,后来想想还是不可行,为了保证P2P传输的可靠性,安全性,客户端之间通信的不仅仅有数据,还应该包含分片的MD5值,加密信息等。尤其采用UDP打洞后,传输的是UDP包,需要在应用层保证数据的顺序和完整(毕竟UDP通信是一种不可靠的连接)。

而且在UDP打洞过程需要服务器端与客户端频繁的通信交互,而这种Web架构不适合完成这样的功能。简单的UDP打洞过程如下:

Client A——Nat A——Server S——Nat B——Client B

1,客户端A连接服务器S,服务器S返回客户端B,C,D...的信息给A(它们的外网IP以及端口);

2,客户端A想和服务器端B通信,发送一个UDP包到B的外网地址(Nat B),并通知服务器S说想和客户端B通信

此时Nat A已被穿透,任意来自Nat B对应端口的数据都能传给Client A

3,服务器S联系客户端B,并告之A想和它通信,同时告之客户端A的信息(外网IP与端口)。

4,客户端B在得到服务器S的通知后,发送UDP包给A的外网地址(Nat A)。

此时Nat B也被穿透,任意来自Nat A对应端口的数据都能传给Client B

5,然后Client A与Client B之间就能任意收发UDP数据包了。

(第2步与第4步之间会有个时间差,不知道Nat 设备在没有收到回复数据多久后会关闭穿透的通道,所以还需要考虑维持这个通道,保证两个客户端之间传输的同步)

倘若A,B都是在一个局域网内,通过上面的方式可能会有问题,它们彼此之间其实能直接连通,反而通过UDP穿透后不能通信(百度上的人说的),所以应该在第一步先比较A分别与B,C,D是否在一个网段(比较方法比如掩码和内网IP),如果是则尝试直接通信,如果不是则再进行UDP穿透。

你可能感兴趣的:(p2sp设计需要考虑的几点问题整理)