结构化与非结构化P2P
依照节点信息存储与搜索方式的不同,诸多P2P协议可以分为2大类:结构化(Structured)的与非结构化(Unstructured)的系统。
非结构化P2P系统
在非结构化的系统中,每个节点存储自身的信息或信息的索引(如指针和IP地址)。当用户需要在P2P系统中获取信息时,他们预先并不知道这些信息(如某个文件)会在那个节点上存储。因此,在非结构化P2P系统中,信息搜索的算法难免带有一定的盲目性,例如最简单的泛洪式查找(类似于广播)和扩展环查找(从最近的n个节点开始,层层转发直到找到目标或超出了跳数的上限为止)。
一些典型的应用采用了一些优化的办法。如在Gnutella中,采用了等级制的组成结构:节点被分成超级节点(Super Node)和普通节点。普通节点必须依附于超级节点,每个超级节点作为一个独立的域管理者,负责处理域内的查询操作。在查找的过程中,查询首先在域内进行,失败后才会扩展到超级节点之间。
非结构化系统的优点在于实现结构简单:无须中央服务器,节点之间完全平等,网络的层次是单一的,而且节点之间无需维护拓扑信息。
结构化P2P系统
在结构化P2P系统中,每个节点只存储特定的信息或特定信息的索引。当用户需要在P2P系统中获取信息时,他们必须知道这些信息(或索引)可能存在于那些节点中。由于用户预先知道应该搜索哪些节点,避免了非结构化P2P系统中使用的泛洪式查找,因此提高了信息搜索的效率。
但是,结构化P2P也引入了新的问题:
首先,既然信息是分布存储的,那么如何将信息分布存储在重叠网中的节点上?
其次,由于节点动态的加入和离开重叠网,如何将拓扑的变更信息通知其它节点?
DHT的引入基本解决了上述问题,因此自从DHT协议出现以后,结构化P2P的应用得到了快速的发展。目前已经有很多较为成熟的DHT协议被提出并且得到了应用。其中比较有代表性的有:缓冲阵列路由协议(CARP);一致性哈希;Chord;内容寻址网络;Pastry。
DHT简介
DHT使用分布式哈希算法来解决结构化的分布式存储问题。分布式哈希算法的核心思想是通过将存储对象的特征(关键字)经过哈希运算,得到键值(Hash Key),对象的分布存储依据键值来进行。具体来讲,大致有以下步骤:
  • 对存储对象的关键字进行哈希运算,得到键值。这样就将所有的对象映射到了一个具体的数值范围中。
  • 重叠网中的每个节点负责数值范围中的特定段落。例如,节点A负责存储键值从8000到8999的对象;而节点B负责7000~7999的对象。这样就将对象集合分布地存储在所有的节点中。
节点可以直接存储对象本身,如文件中的一个片段;也可以存储对象的索引,如该对象所在节点的IP地址。
结构化的分布式存储问题解决后,剩下的问题就是用户如何才能找到存储着目标信息的节点。在有着大量节点(如100万个)的P2P系统中,任何节点都不可能拥有全部的节点?键值?内容的对应关系;因此用户获得了键值之后,如何找到该键值对应的节点就被称为DHT的路由问题。DHT协议必须定义优化的查找(路由)算法来完成这一搜寻的工作。不同的DHT协议之间区别很大程度上就在于定义了不同的路由算法。
DHT的应用非常简洁----API简单到只有一项输入和一项输出:
应用层将数据对象(文件、数据块或索引)通过哈希算法获得键值,将该键值提交给DHT后,返回结果就是键值所在节点的IP地址
主流DHT协议
缓冲阵列路由协议(CARP,Cache Array Routing Protocol)
协议简介
CARP是由微软公司的Vinod Valloppillil和宾西法尼亚大学的Keith W. Ross在1997年提出的。该协议可以将URL空间映射到一个仅有松散关联关系的Web cache 服务器(在协议中称为“代理”,Proxy)阵列中。支持该协议的HTTP客户端可以根据要访问的URL智能选择目标代理。该协议解决了在代理阵列内分布存储内容的问题,避免了内容的重复存储,提高了客户端访问时Web Cache命中的概率。
哈希算法
哈希使用的关键字有2个,一个是代理的标识符(每个代理均有唯一的标识),另一个是URL本身。存储内容时,每个代理负责缓冲哈希键值最大的URL。这样,当缓冲代理阵列发生少量变化时(新的代理加入或旧的代理退出),原有的URL还有可能仍然被映射到原来的代理上,仍可以按照原有的方式访问。
路由算法
客户端(HTTP浏览器)首先加载一个代理配置文件,该文件中存储了代理的标识符和IP地址等用于哈希的关键参数。浏览器在访问网页时,可以根据URL和代理标识获得代理的位置信息(IP地址),从而可以直接访问缓冲代理中的页面。
讨论
CARP的哈希过程比较简单,路由查找更是简单到至多只有一跳(O(1))。但是CARP在P2P的应用环境中有一些致命的缺陷:
每个节点必须知道其它所有节点的信息。在大规模的重叠网环境中,由于可能存在大量的(数百万)节点,加之节点都是动态加入和退出网络,因此这一条件几乎不可能满足。
在缓冲阵列发生较大变化时(这在P2P网络中非常常见),原有的URL和代理之间的对应关系可能发生改变,从而使得原有的配置文件失效。
一致性哈希(Consistent Hash)
协议简介
一致性哈希算法在1997年由麻省理工学院提出(参见0),设计目标是为了解决因特网中的热点(Hot pot)问题,初衷和CARP十分类似。一致性哈希修正了CARP使用的简单哈希算法带来的问题,使得DHT可以在P2P环境中真正得到应用。
哈希算法
一致性哈希提出了在动态变化的Cache环境中,哈希算法应该满足的4个适应条件:
平衡性(Balance)
平衡性是指哈希的结果能够尽可能分布到所有的缓冲中去,这样可以使得所有的缓冲空间都得到利用。很多哈希算法都能够满足这一条件。
单调性(Monotonicity)
单调性是指如果已经有一些内容通过哈希分派到了相应的缓冲中,又有新的缓冲加入到系统中。哈希的结果应能够保证原有已分配的内容可以被映射到新的缓冲中去,而不会被映射到旧的缓冲集合中的其他缓冲区。
简单的哈希算法往往不能满足单调性的要求,如最简单的线性哈希:
x → ax + b mod (P)
在上式中,P表示全部缓冲的大小。不难看出,当缓冲大小发生变化时(从P1到P2),原来所有的哈希结果均会发生变化,从而不满足单调性的要求。
哈希结果的变化意味着当缓冲空间发生变化时,所有的映射关系需要在系统内全部更新。而在P2P系统内,缓冲的变化等价于Peer加入或退出系统,这一情况在P2P系统中会频繁发生,因此会带来极大计算和传输负荷。单调性就是要求哈希算法能够避免这一情况的发生。
分散性(Spread)
在分布式环境中,终端有可能看不到所有的缓冲,而是只能看到其中的一部分。当终端希望通过哈希过程将内容映射到缓冲上时,由于不同终端所见的缓冲范围有可能不同,从而导致哈希的结果不一致,最终的结果是相同的内容被不同的终端映射到不同的缓冲区中。这种情况显然是应该避免的,因为它导致相同内容被存储到不同缓冲中去,降低了系统存储的效率。分散性的定义就是上述情况发生的严重程度。好的哈希算法应能够尽量避免不一致的情况发生,也就是尽量降低分散性。
负载(Load)
负载问题实际上是从另一个角度看待分散性问题。既然不同的终端可能将相同的内容映射到不同的缓冲区中,那么对于一个特定的缓冲区而言,也可能被不同的用户映射为不同的内容。与分散性一样,这种情况也是应当避免的,因此好的哈希算法应能够尽量降低缓冲的负荷。
从表面上看,一致性哈希针对的是分布式缓冲的问题,但是如果将缓冲看作P2P系统中的Peer,将映射的内容看作各种共享的资源(数据,文件,媒体流等),就会发现两者实际上是在描述同一问题。
路由算法
在一致性哈希算法中,每个节点(对应P2P系统中的Peer)都有随机分配的ID。在将内容映射到节点时,使用内容的关键字和节点的ID进行一致性哈希运算并获得键值。一致性哈希要求键值和节点ID处于同一值域。最简单的键值和ID可以是一维的,比如从0000到9999的整数集合。
根据键值存储内容时,内容将被存储到具有与其键值最接近的ID的节点上。例如键值为1001的内容,系统中有ID为1000,1010,1100的节点,该内容将被映射到1000节点。
为了构建查询所需的路由,一致性哈希要求每个节点存储其上行节点(ID值大于自身的节点中最小的)和下行节点(ID值小于自身的节点中最大的)的位置信息(IP地址)。当节点需要查找内容时,就可以根据内容的键值决定向上行或下行节点发起查询请求。收到查询请求的节点如果发现自己拥有被请求的目标,可以直接向发起查询请求的节点返回确认;如果发现不属于自身的范围,可以转发请求到自己的上行/下行节点。
为了维护上述路由信息,在节点加入/退出系统时,相邻的节点必须及时更新路由信息。这就要求节点不仅存储直接相连的下行节点位置信息,还要知道一定深度(n跳)的间接下行节点信息,并且动态地维护节点列表。当节点退出系统时,它的上行节点将尝试直接连接到最近的下行节点,连接成功后,从新的下行节点获得下行节点列表并更新自身的节点列表。同样的,当新的节点加入到系统中时,首先根据自身的ID找到下行节点并获得下行节点列表,然后要求上行节点修改其下行节点列表,这样就恢复了路由关系。
讨论
一致性哈希基本解决了在P2P环境中最为关键的问题——如何在动态的网络拓扑中分布存储和路由。每个节点仅需维护少量相邻节点的信息,并且在节点加入/退出系统时,仅有相关的少量节点参与到拓扑的维护中。所有这一切使得一致性哈希成为第一个实用的DHT算法。
但是一致性哈希的路由算法尚有不足之处。在查询过程中,查询消息要经过O(N)步(O(N)表示与N成正比关系,N代表系统内的节点总数)才能到达被查询的节点。不难想象,当系统规模非常大时,节点数量可能超过百万,这样的查询效率显然难以满足使用的需要。换个角度来看,即使用户能够忍受漫长的时延,查询过程中产生的大量消息也会给网络带来不必要的负荷。
下文中讨论的几种DHT协议都对路由做出了优化,提出了各自的算法。
Chord协议
Chord在2001年由麻省理工学院提出(参见0),其核心思想就是要解决在P2P应用中遇到的基本问题:如何在P2P网络中找到存有特定数据的节点。与前两种协议不同,Chord专门为P2P应用设计,因此考虑了在P2P应用中可能遇到的特殊问题,这些内容将在路由的部分进行讨论。
哈希算法
Chord使用一致性哈希作为哈希算法。在一致性哈希协议中并没有定义具体的算法,在Chord协议中将其规定为SHA-1。
路由算法
Chord在一致性哈希的基础上提供了优化的路由算法:
在Chord中,每个节点同样需要存储m个其他节点的信息,这些信息的集合被称为查询表(Finger Table)。一致性哈希中的节点同样具有这样的表格,但在Chord中,表格中的节点不再是直接相邻的节点,它们的间距(ID间隔)将成2i 的关系排列(i 表示表中的数组下标)。这样形成的节点之间路由关系实际上就是折半查找算法需要的排列关系。
在查询的过程中,查询节点将请求发送到与键值最接近的节点上。收到查询请求的节点如果发现自身存储了被查询的信息,可以直接回应查询节点(这与一致性哈希完全相同);如果被查询的信息不在本地,就根据查询表将请求转发到与键值最接近的节点上。这样的过程一直持续到找到相应的节点为止。不难看出,查询过程实际上就是折半查找的过程。
经过Chord的优化后,查询需要的跳数由O ( N)减少到O(log(N))。这样即使在大规模的P2P网络中(例如N=100,000,000),查询的跳数也仅为O(8),每个节点仅需存储27个(log2100000000)其他节点的信息。
Chord还考虑到多个节点同时加入系统的情况并对节点加入/退出算法作了优化。
讨论
Chord算法本身具有如下优点:
负载平衡
这一优点来自于一致性哈希,也就是一致性哈希中提到的平衡性。所有的节点以同等的概率分担系统负荷,从而可以避免某些节点负载过大的情况。
分布性
Chord是纯分布式系统,节点之间完全平等并完成同样的工作。这使得Chord具有很高的鲁棒性,可以抵御DoS攻击。
可扩展性
Chord协议的开销随着系统规模(结点总数N)的增加而按照O(logN)的比例增加。因此Chord可以用于大规模的系统。
可用性
Chord协议要求节点根据网络的变化动态的更新查询表,因此能够及时恢复路由关系,使得查询可以可靠地进行。
命名的灵活性
Chord并未限制查询内容的结构,因此应用层可以灵活的将内容映射到键值空间而不受协议的限制。
Chord在CFS系统中得到了应用,具体的介绍可参见[8]
内容寻址网络(Content-Addressable Network,CAN)
CAN在2001年由加州大学伯克利分校提出(参见[3])。与Chord一样,CAN也是DHT的一个变种。
哈希算法
CAN的哈希算法与一致性哈希有所不同。Chord中,哈希得到的键值总是一维的,而在CAN中,哈希的结果由d维的笛卡尔空间来表示。d是一个由系统规模决定的常量。
路由算法
CAN的路由查询将在d维笛卡尔空间中进行。
在CAN中,每个节点自身的ID经由哈希后得到的d维向量。经过这样的映射后,整个P2P系统将被映射到一个d维笛卡尔空间中,每个节点的位置由其自身ID决定。CAN对邻居节点的定义并不要求成2i的关系排列,而是改为用在笛卡尔空间上相邻来表示:在d维笛卡尔空间中,2个节点的d维坐标中有d-1维是相等的,剩余的一维是相邻的节点称之为相邻节点。
CAN中的节点仅存储相邻节点表。由于在d维的空间中最多有2d个相邻的节点,因此节点的相邻节点表最多有2d个表项。
在查询的过程中,查询节点首先计算被查询内容的键值(d维向量),然后在节点列表中查找在笛卡尔空间中与该键值最为接近的相邻节点,找到后向该节点发送查询请求(这一策略被称为贪婪策略)。查询请求中将携带被查询内容的键值。收到查询请求的节点如果发现自身存储了被查询的信息,可以直接回应查询节点(这与一致性哈希完全相同);如果被查询的信息不在本地,就根据相邻节点表将请求转发到与键值最接近的节点上。这样的过程一直持续到找到相应的节点为止。在查询过程中,被查询节点到目标节点的笛卡尔空间距离单调地减少。
如果查询节点或转发节点发现邻居节点表中无法找到可用的下一跳节点,则采用非结构化P2P常用的扩展环搜索(Expanding Ring Search,使用无状态,受控的泛洪算法在重叠网中搜索)以找到合适的(符合贪婪策略)下一节点。
经过CAN的优化后,查询需要的跳数由O ( N)减少到均值为(d/4)(n1/d)的随机制,考虑到d为常数,这一值可以表示为O(n1/d)或O(dn1/d)。
讨论
CAN和Chord的主要区别在于路由算法不同。相比之下,在节点数量非常大时,CAN的平均查询跳数要比Chord增加得更快。而且CAN查询过程中需要的运算量也要高于Chord。但CAN使用的d为预先设置的常量,因此并不假设系统节点数量。在节点总数动态变化范围很大的系统中,CAN的相邻节点表结构保持稳定,这在P2P的应用中也是很重要的优点。
Pastry
Pastry在2001年由位于英国剑桥的微软研究院和莱斯(Rice)大学提出(参见[4])。Pastry也是DHT的一个变种。
哈希算法
Pastry使用一致性哈希作为哈希算法。哈希所得的键值为一维(实际上使用的是128bit的整数空间)。Pastry也没有规定具体应该采用何种哈希算法。
路由算法
在Pastry协议中,每个节点都拥有一个128bit的标识(Node Id)。为了保证Node ID的唯一性,一般由节点的网络标识(如IP地址)经过哈希得到。
Pastry中的每个节点拥有一个路由表R(Routing table),一个邻居节点集M(Neighborhood Set)和一个叶子节点集合L(Leaf set),它们一起构成了节点的状态表。
路由表R共有logBN(B = 2b为系统参数,典型值为16,N表示系统的节点总数)行,每行包括B-1个表项,每个表项记录了一个邻居节点的信息(节点标识、IP地址、 当前状态等)。这样就形成了拥有(B-1)logBN个条目的二维表格。路由表第n行的表项所记录的邻居节点的Node ID前n个数位和当前节点的前n个数位相同,而第n+1个数位则分别取从0到B-1的值(除了与当前节点第n+1数位的值)。这样形成的路由表很类似IP路由中最长掩码匹配的算法。参数b(或B)大小非常关键:B过大则节点需要维护很大的路由表,可能超出节点的负载能力,但路由表大些可以存储更多的邻居节点,在转发时更为精确。平均每次路由查找需要的跳数在Pastry中计算的结果是logBN,因此B的选择反映了路由表大小和路由效率之间的折衷。
叶子节点集合L中存放的是在键值空间中与当前节点距离最近的|L|个节点的信息,其中一半节点标识大于当前节点,另一半节点标识小于当前节点。|L|的典型值为2b或者2*2b。
邻居节点集合M中存放的是在真实网络中与当前节点“距离”最近的|M|个节点的信息。“距离”的定义在Pastry中非常类似IP路由协议中对距离的定义,也就是考虑到转发跳数、传输路径带宽、QoS等综合因素后所得的转发开销(可以参见OSPF等路由协议)。Pastry并未提供距离信息的获取方法,而是假设应用层可以通过某种手段(人工配制或自动协商)得到信息并配置邻居节点集合。|M|的典型值为2b或者2*2b。
图 3给出了一个Pastry节点状态表的例子,该图来源于[4]。
在节点状态表中,节点本身的ID为10233102。叶子集合中有8项,每一项都代表一个当前节点已知的其他节点的信息。路由表共有4*8项,可以看出由上至下节点ID重合的位数(前缀)不断增加。邻居集合中的节点ID由于来源于应用层,一般没有规律性可循。
Pastry的路由过程如下:
首先,路由查询消息中将携带被查询对象ID(Object Id),又称消息键值。当收到路由消息时,节点首先检查消息键值是否落在叶子节点集合的范围内。如果是,则直接把消息转发给叶子节点集合中节点标识和消息键值最接近的节点;否则就从路由表中根据最长前缀优先的原则选择一个节点作为路由目标,转发路由消息。如果不存在这样的节点,当前节点将会从其维护的所有邻居节点集合(包括路由表叶子集合及邻居集合中的节点)中选择一个距离消息键值最近的节点作为转发目标。
从上述过程中可以看出,每一步路由和上一步相比都更靠近目标节点,因此这个过程是收敛的。如果路由表不为空,每步路由至少能够增加一个前缀匹配数位,因此在路由表始终有效时,路由的步数至多为logBN。
讨论
Pastry的路由利用了成熟的最大掩码匹配算法,因此实现时可以利用很多现成的软件算法和硬件框架,可以获得很好的效率。
与Chord和CAN相比,Pastry引入了叶子节点和邻居节点集合的概念。在应用层能够及时准确地获得这两个集合的节点信息时,可以大大加快路由查找的速度,同时降低因路由引起的网络传输开销;不过在动态变化的P2P网络中如何理想地做到这一点的确有很大的难度。
Pastry的典型应用包括PAST(参见[5][6])和SCRIBE(参见[7])。
趋势分析
目前DHT算法的发展方向非常多,不断有新的改进算法被提出来。就笔者目前了解到的信息而言,至少有以下一些方向:
接近性(Proximity)
文中提到的DHT算法中,除了Pasrty以外,均未考虑重叠网络拓扑结构与真实的IP网络之间的重合关系。节点之间进行对等通信时,不会考虑优先选取距离自己最近的节点。这样就使得最终形成的重叠网结构混乱,效率低下。因此如何让节点获得并利用接近性信息就非常重要。
结构化
目前基于DHT的应用尚未大规模展开,很多工程上的细节问题尚待解决。例如:目前有很多种类的P2P应用,如文件存储和共享、电子邮件、流媒体等。这些应用在处理P2P路由算法、拓扑维护和信息检索上使用的方法均有很大差别,导致即使是同类的应用也无法实现互通。如何为各种P2P的应用抽象出一个通用的层次,也是目前研究的热点问题之一。
信息查询
基于分布式哈希表的查询是一种单关键字的精确匹配,尽管相对于非结构化系统它使得系统资源可被确定性地查询到,但它也极大地限制了查询的应用范围。目前有许多改进的结构化查询算法已经被提出来。

P2P网络中DHT算法分析相关推荐

  1. P2P网络中的DHT分布式哈希结构

    现有的P2P实现可以分为三种类型.它们分别是:基于目录服务器P2P,非结构化P2P和结构化P2P.基于目录服务器这一类系统中设置目录服务器,用于保存用户节点的地址信息和该节点上共享文件的描述信息,文件 ...

  2. Unity网络:在局域网P2P网络中利用UDP广播实现保活/心跳

    C/S与P2P 严格来讲客户端与服务器指的都是进程,N个Client客户端进程与一个或多个Server服务器进程可以组成一个C/S结构的网络,而同时既是客户端也是服务器的N个节点可以组成一个P2P网络 ...

  3. p2p网络中的NAT穿透技术----常见NAT穿越解决方案

    p2p网络中的NAT穿透技术----常见NAT穿越解决方案 常见NA丁穿越解决方案 NAT技术在缓解IPv4地址紧缺问题.构建防火墙.保证网络安全等方面都发挥了重要 作用.然而,NAT设备的广一泛存在 ...

  4. P2P网络中的节点发现

    在P2P网络中,要发现并连接其他节点,常见的是通过种子节点连接到网络,然后通过种子节点获取其他节点的地址.以太坊的种子节点在cmd/swarm/bootnodes.go中定义,hpb的种子节点在con ...

  5. P2P网络中内网穿透的方法总结(2019)

    P2P网络中内网穿越方法总结(2019) 内网穿越的需求 问题分析 方案一 方案二 方案三 内网穿越的需求 今天去图书馆搜资料查了一下,这个问题很老,但是解决办法很久都没有更新过了,还得翻翻书.网上的 ...

  6. 【P2P网络】DHT协议基础1:Kademlia翻译稿

    转载自:http://blog.csdn.net/hoping/article/details/5307320 Kademlia :一种基于 XOR 度量的 P2P 信息系统 Petar Maymou ...

  7. BT网络中DHT和UPnp的解释(转)

    DHT 类似Tracker的根据种子特征码返回种子信息的网络.DHT全称叫分布式哈希表(Distributed Hash Table),是一种分布式存储方法.在不需要服务器的情况下,每个客户端负责一个 ...

  8. 迅雷在P2P网络中的另类上传速度

    如上图,我们一般在下载BT时,一般P2P是边下载边上传. 但是迅雷在自己的软件中可以设置上传速度,反而在展示时却把P2P协议的速度不在上传那么显示,而是使用协议速度来进行展示:并且这个速度无法设置. ...

  9. P2P中DHT网络原理

    2019独角兽企业重金招聘Python工程师标准>>> DHT网络爬虫基于DHT网络构建了一个P2P资源搜索引擎.这个搜索引擎不但可以用于构建DHT网络中活跃的资源索引(活跃的资源意 ...

最新文章

  1. python程序保存_初识python 文件读取 保存
  2. 分布式缓存系统 Memcached CAS协议
  3. SQL语句对于NUll的筛选
  4. php分页预览函数,PHP分页函数的简单示例
  5. poj 3257(哈希+二维dp)
  6. 网易云信项望烽:开源最初都是被动的
  7. 《我的第一本c++书》读后感
  8. php的list函数的使用,php list函数如何使用
  9. 微服务乱码_本地正常服务器乱码
  10. pptv图标出现在计算机磁盘,PPTV出现界面乱码如何解决
  11. MySQL数据库InnoDB存储引擎底层原理详解
  12. c语言循环语句解鸡兔同笼,JavaScript的for循环语句练习之解决鸡兔同笼问题
  13. 遗传算法bp神经网络原理,bp神经网络 遗传算法
  14. ubuntu和kubuntu换源
  15. 解压zip,z01,z02
  16. WebAR+教育丨帮助老师课堂教学,教育展览
  17. javax.crypto.AEADBadTagException: Tag mismatch 的解决办法
  18. 燃气管道运行全局实时监控系统-海城支线总页面
  19. 创业过程中的63个技术问题
  20. [Java Performance] JIT编译器简介

热门文章

  1. phalcon: eventManager事件管理(结合dispatcher调度控制器)制作简单的acl
  2. lvm 2(逻辑卷管理)基础详解
  3. RQNOJ 83 魔兽世界
  4. 使用network管理DD恢复全库操作步骤
  5. vSphere ESXi命令行使用方法详解
  6. Securecrt连接linux时速度特别慢的解决办法
  7. Laravel 加载第三方类库的方法
  8. Android应用程序进程启动过程的源代码分析(2)
  9. nginx和fpm的进程数配置和502,504错误
  10. android异常(2)