您的位置:首页 > 理论基础 > 计算机网络

关于网络编程中的序

2012-06-30 17:04 176 查看
关于网络编程中的序

 

 

         有过网络编程的人一般都知道无状态有状态的区别,大多数人都知道web是无状态的,但很多人不知道有序和无序的区别,甚至有的从业很多年的同事也想当然的以为都是有序的。

所谓序其实说起来很容易理解,就是abc三个包发到后端,依次返回ABC,说起来就这么简单,但是这个小小的序其实决定着后端如何实现的策略,我们常见的cs服务,如mysqlclient和mysql通信,对同一个连接都是有序的,我们访问memcached和redis等服务的时候,都是有序的,我们的http请求也是有序的,只有等上一个返回了才返回下一个请求,哪怕下一个早就可以提前执行,于是在浏览器如果要同时请求多个web资源只有开多个连接,利用多个连接的并发性实现资源的并发请求,早期的浏览器只开1-3个连接,如今的浏览器可能会同时打开多到8个并发连接,有的服务器也会限制同一个客户端同时打开的连接数,其实这些问题都是因为序引起的,如今SPDY等号称http2.0的协议都在试图解决让http无序的问题,解决方法也非常容易理解,就是给每个请求分配一个不同的reqid,server在返回的时候带上每个reqid,这样打乱顺序返回到客户端的时候也能实现一一对应,如此就顺利的实现了无序,这样每个浏览器不需要开多个连接,1个连接对一个server即可,服务器也能承载更大的负荷,socket资源大大节省,每个客户端理论上只需要一个连接即可,另外server处理上也比之前简单,再也不需要考虑顺序问题,分配执行的时候简单地并发到一组线程就可以,无需考虑序的问题,哪怕某个执行阻塞也无所谓,不会出现任何问题。当然SPDY等http2.0协议要解决问题中,序只是其中之一的问题,还有其他几个,本文就不深入讨论了。

         具体网络编程中,我曾经有一段时间也没深入理解序的问题,早期我在tcp编程中很长一段时间使用了这种包头:

struct PKHEAD

{

         unsignedint length;

         unsignedshort st;

         unsignedshort mt;

         ...

};

就一个长度和一个类型(细分为主类型、子类型),由这个头可见这种包发出去都是要求有序的,否则我同时发了两个相同类型的请求如果不按照序返回那就对应出错了,这种有序要求对后台是一个很严格的约束,后台实现中必须严格的按照顺序处理包,否则就让前台对应出错了,大多数人倾向于将某个连接的包都在一个线程处理,规避调度到多个线程之后复杂的序问题。对很多应用而言,如果无序则可以让约束更少,实现更自由,在无序的条件下,需要定义包的特征,于是我将包头修改成了如下的样子:

struct PKXHEAD

{

         unsignedint length;

         unsignedshort st;

         unsignedshort mt;

         unsignedint seqno;

         ...

};

其中seqno就是每个包的一个序列号,server返回的时候也一并返回这个seqno就可实现一一对应,如此就为包的无序处理提供了基础,对一个无序的调用后台可以很简单的处理,哪怕是将同一个连接的N个包并发到多个线程同时处理也没任何问题,不需再为序的问题烦恼。

         对一个无状态服务,如果要采用有序方式处理,就如现在的http1.1一样,其实是设计上的缺陷,但毕竟不是所有服务都是可以无序的,还是有很多服务是有序的,一般地一个server可能提供的一些服务可以是无序的,但有些服务是有序的,有序的只是其中的一部分,对这一部分请求可通过两个简单的方法实现有序,方法一、可在客户端严格时序,发一个a收一个A,然后再发收下一个依赖于A的,这样的处理方法对后台最宽容,但也很低效,有的时候不得不需要同时多开几个连接的方法提高效率。方法二、服务器将有序服务调度到一个线程处理,或返回时排序,其他无序服务则乱序处理,如此即可。

         可惜的是目前大多数服务采用的都是不支持序标识的应用协议,很多web编程人员可能从来都没有意识到序问题,其他网络编程人员可能有人意识到了序问题,但大多数人没足够重视,可能就如我之前的处理一样,直接一些方法规避了,没有深入考虑序标识带来的便捷性和高效性,总之,序问题值得重视,就如不理解多线程的人不能写好程序一样,不理解序的编程人员不是一个合格的网络编程人员。

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息