写网络程序躲不过协议,协议其实就是定义了消息的格式,以及消息是如何交换的。协议可简单可复杂,复杂精密如TCP协议,简单奔放如HTTP的协议。这里将我所接触到的协议稍微总结一下,最后抛出一个我的设计的简单通用的文本协议。mysql
设计一个协议不是一件很容易的事情,尤为是当对设计的要求包含很好的描述性和可扩展性的时候。若是再将效率考虑在内,则更是件耗脑力的活。在继续讨论下去以前,先看看现有的一些协议吧。这里主要讨论的是应用层的协议,应用层的协议大可能是请求响应模式(除了zeromq这个变态的家伙,后面再说),因此这里侧重讨论消息格式。git
HTTP协议github
这多是你们接触得最多的协议了,HTTP协议是一个比较简单的基于文本的协议。消息格式基于文本,换行分隔键值串,键和值用冒号分隔,同时定义了一些标准的键和值。这个协议描述性教强——人类可读。扩展性强——加自定义的头很容易,也几乎不会有反作用(除了消息体积增长一点点)。可是,缺点就是标准定义的东西太多了,细节太多。解析较复杂。redis
memcached协议sql
memcached有两种协议,文本协议和二进制协议,文本协议以换行表示一个请求结束。请求内部参数以空格分隔。为了二进制安全,在二进制数据前要加上长度这个参数,如set x 3 abc\r\n。安全
文本协议当然简单,但是当请求很小的时候,过多的协议自己的数据则显得浪费(好比每一个HTTP请求只发送一个字母,可HTTP头可能有上百的字符,太浪费了),并且,server在接收到请求以后还要作文本解析,也耗cpu,因而memcached又推出了二进制协议,为了锦上添花,是的memcached更加高效。二进制协议的优势就是高效,由于全部信息都以最少的数据量来表达,且server解析请求时作的是数学比较而不是字符串比较,效率高不少。网络
memcached的协议比起HTTP来就轻得多了(固然,二者所面向的场景不同,故这个比较没太大意义)。可是,也有缺点,就是扩展性较差,协议定得比较死,哪一个位置上有哪些东西,是什么意义是定死的。因此,直接哪来用在不一样的场景下不大现实。memcached
redis协议google
redis的协议也是文本协议,可是设计得比较当心和通用(我后面本身定义的协议深受其影响),在保证描述性的同时尽可能减小协议自己的数据量,好比,在memcached的文本协议中,错误用“ERROR\r\n”来表示,而redis使用“-”来表示,用“:”开头的行表示整数等等。这样的设计结合了文本协议的简单和一部分二进制协议的高效。用在redis这个场合,非常适合。交换方式一样是请求响应。redis协议有一个缺点,就是,一个消息有多少参数是须要在开头指定的。不像HTTP协议用空行来表示结束。这就带来一个缺点,很差流水操做,也就是说消息必须在发送第一个字节以前被彻底肯定,由于第一个东西就是参数个数:-(。spa
上面讨论的基本都是文本协议,固然还有不少采用二进制协议的服务,如gearman、mysql等,二进制协议就至关于压缩版的文本协议,提升了传输效率,可是下降了描述性和灵活性(万一那个位置预留的位数不够就囧了)。
总的来讲,这就是一个平衡的过程。若是消息体不是很小(好比每次只传一个字节的消息就很小了),那么采用文本协议仍是值得的。毕竟文本协议简单,好扩展,利于调试(telnet就能够当客户端用),虽然说消息是让计算机读的,但有时候也要人去看。因此,能用文本仍是用文本吧。
简单文本协议
最后我定义了一个简单的基于文本的协议,叫作simpletp(Simple Text based Protocol),详细定义在这里http://simpletp.org,这个协议是为了简单的RPC而设计,结合了HTTP协议的灵活(以空行结束),redis协议的轻量(size+data)。但为了简单通用,没有采用redis的单字符表示类型的设计,由于这样就会引入额外的复杂性,如表示整数用“:”,那么浮点数、复数等等怎么办,干脆什么类型都没有,就简单的传输size+data串(有点相似zeromq,可是比zeromq作的事情少),而具体的类型则交由其余机制去处理,如protocol buffer。