现在的位置: 首页 > 综合 > 正文

浅谈网络通信之IO模型

2018年05月13日 ⁄ 综合 ⁄ 共 1476字 ⁄ 字号 评论关闭

    有人曾经问过我一个问题,让我谈一谈对网络通信的理解。其实我对网络通信的理解是:通信的过程已经有一套标准的套接字编程,网络通信的难点在于通信的两端的逻辑代码应该怎么去设计,怎么去编码。

    我曾经为windows客户端提供过两套接口调用(后台是linux),最初的版本是windows客户端开发人员自己维护一个进程,作为异步的方式来等待服务器端的相应,自己设置超时时间。这种方案最大的问题在于客户端和服务端的协作,各自需要维护一套接口,而且接口传递的参数必须严格一一对应,这样就容易出错,出错了就容易扯犊子。

    第二个版本变成api被分装成同步的,提供给windows客户端的api把通信分装到内部,客户端开发人员调用请求接口变得简洁,那么新问题又来了,超时变得平凡,而且严重影响客户端的操作体验,经常出现界面假死的现象。

    略谈为什么卡?

    1.通信中断不可避免,人为就可以模拟这个环节

    2.大量的信息需要被同步到客户端(设计的时候为满足设计人员的要求,客户端需要同步缓存服务器的信息)

    3.服务器端的业务逻辑隔离得不好,为了达到把信息缓存到内存,使用单进程去维护一个庞大的信息网

    4.逻辑设计上为保证操作的一致性导致必须按消息队列去顺序处理逻辑,一个接口处理的太庞大导致堵塞

    如何改进?

    1.消息中间件

    2.业务拆分

    3.使用membercached

    4.除非逻辑的强一致性,否则尽量采用异步通信

    本文的重点不在于介绍失败的经验,也不是像架构师那样去解决问题,问题始终存在,牛人肯定有更好的解决办法,那么我想问题的出现主要是对网络通信的IO不了解,以及对业务负载预估错误(产品定义是支持2K在线访问,结果频频出问题的用户有的是8K,有的甚至达到了20K)

    IO模型简单的可以分成两类:一类是异步,一类是同步。

   一、 异步就不多说,简单的说就是客户端发送请求后无需阻塞在调用的地方,该干嘛干嘛,检测超时或者不检测,等待服务发送请求过来再处理逻辑,但是可能出现文章中提到的设计复杂度的问题。

    二、同步处理的模型就多了,具体来分可以如下分类:

    1.阻塞式的IO模型。也就是client发起请求后就等着,一直到server端返回消息再做相应。

    2.非阻塞式IO模型。也就是client发起请求后server立马回复没搞定,然后接下来client端不断重复的问server端搞定没。这样的方式会让client的端的性能压力徒增,有个专业的术语叫轮询

    3.信号驱动式IO模型。也就是当client发起请求建立信号处理程序后server立马返回,不做处理,当系统发送一个信号告诉client端一切数据已经准备好,这个时候client端再向server发送请求,等server处理完毕后再返回client消息提示。这种方式的优势在于阻塞的时间比较短

    4.IO复用模型

    使用select或者poll,这玩意也有点像轮询,但是轮询不是卡在IO上,而是在描述符上。比如调用select后告诉内核我对哪些描述符感兴趣,然后不断的循环遍历这些描述符,OK一个处理一个。但是这个监控打开的描述符有限,在一些系统里面最大只有1024个。poll比select处理的多,但是服务器的性能却是一个瓶颈。

 

    以上IO模型参考至《unix网络编程.卷一》

    5.基于事件的epoll。像libevent实现了跨平台的epoll模型,简单的讲是通过回调函数去监控描述符,当一个描述符准备好了之后通过回调函数去激活通信。(这一点研究不深,仅限于理论)

    

抱歉!评论已关闭.