Patterns in network system design 之一
Pattern是系统设计过程中,重复出现的结构或者原则。不同的设计层次或者领域,有不同的pattern,比如analysis pattern, architecture pattern, design pattern, debug pattern, bug pattern等,甚至还有很多anti-pattern。Pattern是对已有知识的总结和优化,它对现有系统的维护,以及未来系统的设计都有帮助。
在这里,我要总结的是在网络系统设计里面出现的pattern,这只是经验的总结,每一个pattern并没有经过深思熟虑,所以pattern的描述可能是不完整的。而且这些pattern还不能形成一个完整的pattern language,也就是说,它们还可以提炼和扩展。如果能够形成一个pattern language,它将是我写这些文字最大的收获。
Pattern描述需要一定的格式,这里使用的是我自己简化过的描述方式,只保留了最基本的东西。复杂,详细的描述要花费时间和精力,有时间再慢慢扩充。下面就按顺序来描述这些pattern,大概有十多个,将会分几个部分发出来。
1) control plane/data plane
Pattern Name and Classification: control plane/ data plane
Intent: 把转发和协议分离,隔离错误,提高性能
Also Known As: control plane/ forwarding plane
Motivation (Forces):
在网络设备里面,最重要的工作就是转发,大部分流量都是在数据平面处理的。控制平面处理协议。一般来说,数据平面需要处理的是需要转发的流量,而控制平面处理的是终结在本机的流量。可能还需要加一个管理平面(management plane),用于配置,管理设备。 很明显,数据平面需要高性能的处理器,而控制平面就稍差一点。但控制平面往往会成为被攻击的重点,所以控制平面更关心协议实现的正确性和安全性。
Known Uses: 网关设备
Related Patterns: service plane
References:
1: Requirements for Separation of IP Control and Forwarding
2) first path/ fast path
Pattern Name and Classification: first path/ fast path
Intent: 把慢速路径和快速路径分离,隔离错误,提高性能
Also Known As: slow path/ fast path; exception path/ fast path
Motivation (Forces):
在session-based的网络设备里面,创建session的过程比较复杂,而根据session进行转发的工作则比较简单。所以把创建session的path分离出来,可以只针对这个部分进行优化。一般来说,在connection rate测试,考验的是first path的能力,而throughput 测试考验的是fast path的能力。
Known Uses: session-based gateway
Related Patterns: service plane
References:
1: How to choose the best router switching path for your network
3) Queue based design
Pattern Name and Classification: queue based design
Intent: 简化包处理流程
Also Known As: pending and polling
Motivation (Forces):
包交换(存储转发)网络,最基本的操作就是enqueue/dequeue。这个和电路交换网络有本质的不同。电路交换,在包通过的路径上,有资源预留,所以不会有等待的情况;而包交换网络是按跳(hop)转发的,在包通过的路径上,没有资源预留,所以当一个包不能被立即转发时,需要放到队列里面。队列可以分为很多种,比如按包大小分类的队列,按协议分类的队列等等。由于入队和出队是两个独立的操作,所以有多种入队和出队的策略。网络设备的处理基本上就是:从队列里面取出packet;处理;把packet放入队列。不同的处理可以基于不同的队列,比如在tunnel的处理过程中,可以把封装后的包放入一个新的队列,后续的处理流程可以从队列里面把包取出来,然后发送出去。引入队列以后,针对不同队列,可以有不同的处理过程,这些过程相对独立,编程或者纠错都方便一些。
引入队列之后,可能会使得系统的处理时间变长,从而是系统的latency变大。入队,出队操作越多,latency就越大,这一点需要注意。
Known Uses: ip network gateway
Related Patterns: event-driven programming
References:
1: http://en.wikipedia.org/wiki/Queueing_theory
2: Elements of Queuing Systems
4) Per thread queue
Pattern Name and Classification: per thread queue
Intent: 每个thread有自己的队列,减小冲突,增加并行
Also Known As: M model;costco model
Motivation (Forces):
在多核编程里面,任务调度非常重要。如果每个核都是独立poll自己的队列,那么这些核之间就不需要锁。锁只存在于:其他核把包放入接收队列;处理完成之后,把包放入发送队列,由发送核把包发出去。
Receiving core —> Processing core —> Transmitting core
只需要两个锁,而且最多有两个core在竞争这些锁。
这里面的问题在于:Receiving core如何把packet有效分配给processing core,使得每个processing core的workload是均衡的;还有就是如果processing core需要把包放入入队列,它只能放入当前core所在的队列,这样就是的任务处理更加不均衡。
Known Uses: multicore gateway
Related Patterns: Global queue
References:
1: Queueing Theory In Action, plus, frogs
5) Global queue
Pattern Name and Classification: global queue
Intent: 多个thread共享队列,任务共享,均衡调度
Also Known As: W model; fry’s model
Motivation (Forces):
在多核编程里面,如果多个核共享一个队列,每个核都是从这个队列里面把包取出来,然后处理。这样就每个核的load就是均衡的,因为每个核都是平等的,处理相同的任务。
/—> Processing thread —\
Receiving core —> Queue —–> Processing thread —> Queue —> Transmitting thread
\—> Processing thread —/
这里面的问题在于:锁冲突的几率增大;queue管理比较复杂。
Known Uses: multicore gateway
Related Patterns: per thread queue
References:
1: Queueing Theory In Action, plus, frogs
6) Run to completion
Pattern Name and Classification: run to completion
Intent: 在任务处理过程中,禁止调度
Also Known As: No
Motivation (Forces):
在实时系统里面,一个任务开始运行后,它应该被执行完成之后,才能调度其他任务到当前的CPU上运行,也就是说,这个任务不应该不中断,否则的话,任务运行的时间就是无法估计的,而且需要保护的东西将会有很多。网络系统是一个典型的实时系统,所以在包处理过程中,它是run to completion的。
Known Uses: network system
Related Patterns: pipe line; preemptive
References:
1: Design Patterns for Packet Processing Applications on Multi-core Intel® Architecture Processors
2: More about multicores and multiprocessors
7) Pipe line
Pattern Name and Classification: pipe line
Intent: 复杂任务需要分解成多个任务,分阶段执行
Also Known As: pipeline and filter
Motivation (Forces):
在网络系统里面,如果一个任务很复杂,需要很多CPU时间,那么这个任务需要分解成多个小任务来执行,否则的话,这个任务占用CPU时间过长,导致其他任务无法执行。而且多个每个核都执行这样的任务,那么,整个系统就无法处理其他任务,这将会导致严重的丢包。所以,每个任务执行的时间不应该有很大的差别,否则,任务调度就有困难。
一个任务分解成多个小任务后,每个小任务之间由queue连接,上一次处理完成之后,放入下一个队列。这样可以任务调度更均衡。每个小任务都是run to completion的,这一点需要注意。
Known Uses: network system
Related Patterns: run to completion; parallel
References:
1: Design Patterns for Packet Processing Applications on Multi-core Intel® Architecture Processors
2: More about multicores and multiprocessors
8 unreliable message
Pattern Name and Classification: unreliable message
Intent: 快速传递消息,可以容忍少量消息丢失
Also Known As: No
Motivation (Forces):
通过网络,或者通过某种通道传递消息时,需要考虑消息传递是否是可靠的。可靠的消息可以这样定义:
a: 消息是完整,正确的。这个一般用校验和来保证消息在传递过程中没有改变。
b: 接收方一定能够收到消息。接收方收到消息后,先检查校验和,然后给发送方一个应答。发送方在收到应答后,可以确认消息已经送达。如果发送方没有收到应答,需要定时重传消息,直到收到应答为止。如果消息之间需要保证顺序,那么在前一个消息没有发送完成之前,后续的消息不能发送。
c: 发送方的消息不能丢失。当发送方的应用把消息传递给消息发送模块后,如果它假设这个消息是可靠的,那么在消息模块里面要保证这个消息不能丢失。也就是说,如果应用模块把消息传递给消息模块并且返回成功,那么这个消息一定能到达接收方,或者消息模块需要返回错误给应用模块。
可以看到,为保证消息的可靠性,需要大量的额外工作,这将会严重影响系统的性能,特别是在高速通道上 更是如此。所以,如果少量的消息丢失是可以容忍的,那么建议使用unreliable message。但是应用程序需要 考虑消息丢失的情况,并为此做相应的处理。
Known Uses: UDP
Related Patterns: reliable message
References:
1: http://en.wikipedia.org/wiki/User_Datagram_Protocol
9) reliable message
Pattern Name and Classification: reliable message
Intent: 提供可靠的消息通道,简化应用程序的流程
Also Known As: No
Motivation (Forces):
可靠的消息通道可以简化上层应用的处理流程,上层应用不需要为消息丢失或者重复做额外处理。可靠性一般通过两种手段来保证:
a: 确认。收到消息需要确认。
b: 重传。消息和确认都有可能重传,重传需要定时器,也需要队列。
可靠还意味着消息是按顺序送给上层应用的,并且已经去掉了重复的消息。
为了使消息传递得更快,需要使用滑动窗口;为了避免消息通道拥塞,需要采用拥塞控制手段;为保证消息不会使发送和接收双方的缓冲区溢出,需要控制发送和接收的消息数量。所以,可靠消息通道的实现非常复杂,面临的难题也很多。如果上层应用普遍要求使用reliable message,那么使用reliable message可以简化应用的设计,否则,可以使用unreliabe message,而由应用来处理丢包和重复的问题。
Known Uses: TCP
Related Patterns: unreliable message
References:
1: http://en.wikipedia.org/wiki/Transmission_Control_Protocol
2: http://en.wikipedia.org/wiki/Reliable_messaging
10) synchronous message
Pattern Name and Classification: synchronous message
Intent: 当后续操作依赖于当前消息的响应时,需要使用同步消息
Also Known As: No
Motivation (Forces):
同步消息的涵义是:在发送请求之后,当前的操作必须等待应答消息返回以后,才能继续后面的流程。这个等待可以忙等待,也可以是睡眠。使用这个模式的前提是:后续操作依赖于当前操作的执行结果,也就是说,这些操作是序列化的。
由于这些操作是序列化的,所以很难并行化,而且不管是忙等待还是睡眠都会耗费一定的资源。所以,除非必要,最好不要用同步消息。
Known Uses:
Related Patterns: asynchronous message
References:
1: http://en.wikipedia.org/wiki/Message_passing
11) asynchronous message
Pattern Name and Classification: asynchronous message
Intent: 发送消息后,不用等待应答,消息和应答可以由不同的线程处理
Also Known As: No
Motivation (Forces):
如果一系列操作之间并没有依赖关系,那么消息发送和应答处理可以由不同的线程处理。这样做的好处是:消息发送和应答处理可以并行执行。一般来说,异步消息并不需要序列化。但是如果有序列化的需求,就需要给消息分配序号,并且使用锁来保证每个消息和应答都是按顺序处理的。在实现时,需要权衡序列化带来的复杂性,可能用同步消息会有更好的结果。
有个同事把同步消息比做打电话,把异步消息比做电子邮件。打电话需要同步等待,而看邮件就不需要即时响应,也不需要按顺序看。这个类比很形象。
Known Uses:
Related Patterns: synchronous message
References:
1: http://en.wikipedia.org/wiki/Message_passing
2: http://en.wikipedia.org/wiki/Messaging_pattern
12) piggyback message
Pattern Name and Classification: piggyback message
Intent: 发送消息时,捎带其他消息
Also Known As: No
Motivation (Forces):
piggyback,意思是捎带,也就是搭顺风车的意思。捎带的好处是可以节省一个或多个消息,对性能有好处。捎带的这个消息可以与当前的消息相关,也可以无关。当然,前提是通信双方有多个消息需要交换,如果只有一个,就没有什么可以捎带的了。
Known Uses: TCP
Related Patterns: No
References:
1: http://en.wikipedia.org/wiki/Piggybacking_(data_transmission)
13) single message
Pattern Name and Classification: single message
Intent: 每次只发送或接收一个消息
Also Known As: No
Motivation (Forces):
每次只发送或接收一个消息。这样做的好处是简单,不需要花费很多时间在message parsing上面。由于只有一个消息,消息长度和结构的验证都很容易,编程也容易。但一个消息的坏处是:双方交换的消息数量可能会很多,也可能会有其他开销。以http 1.0为例,每个URL都是独立的,所以需要为每个URL创建一个connection,系统资源消耗较大。
Known Uses: http 1.0
Related Patterns: bundle message
References:
1: http://en.wikipedia.org/wiki/Http
14) bundle message
Pattern Name and Classification: bundle message
Intent: 一次发送多个消息
Also Known As: No
Motivation (Forces):
如果多个消息可以放在一起发送,显然可以减少消息的数目。以http 1.1 tunnel mode为例,一个connection上可以发送多个消息,减少了创建connection的时间,减少了资源消耗。但它会增加message parsing的难度,因为需要它需要确定消息的边界也类型。如果是同一类型消息的bundle还好处理一点,因为长度和类型都是一样的;如果是多种消息的bundle,就需要使用TLV来定义消息,这更增加了消息处理的难度。
Known Uses: http1.1 tunnel mode
Related Patterns: single message
References: