您的位置:首页 > 职场人生

面试题:在传送文件时卡住,还想发送聊天信息

2018-07-01 19:23 183 查看
写在前面的话:我写博客是为了训练自己的表达能力,更多是为了记录自己的一些工作思路,好记性不如烂笔头。所以博客写出来的内容不像写论文那样负责,写学术论文会反复修改几十遍,并且在投稿时还有专业理论技术审稿。写博客,就像是在创作同人作品,看着有趣就行了。

面试题目

设计一个聊天软件,如果你在传送文件时卡住,还想发送聊天信息,你怎么解决?

问题建模

服务器接收文件卡住,是否继续空等待,可以看成非阻塞IO(NIO)文件读写。

解决思路

Reactor是网络编程中的一种设计模式。最原始的网络编程思路就是服务器用一个while循环,不断监听端口是否有新的套接字连接,如果有,那么就调用一个处理函数处理,类似:

while(true){
socket = accept();
handle(socket)
}

这种方法的最大问题是无法并发,效率太低,如果当前的请求没有处理完,那么后面的请求只能被阻塞,服务器的吞吐量太低。之后,想到了使用多线程,每一个连接用一个线程处理,类似:

while(true){
socket = accept();
new thread(socket);
}

这个实现方式比第一个好很多,因为在不同的线程中,前一个请求的read阻塞并不会影响后续的请求,在一定程度上提高了服务器的吞吐量。但该做法缺点在于资源要求太高,线程的创建、销毁比较耗时。一个解决方法就是创建线程池,但如果连接数太多,系统仍然无法承受。以去饭店吃饭为例。

每一个客户来就餐就是一个事件,吃饭的人会先看一下菜单,然后点菜。处理这些就餐事件的就需要我们的服务人员了,每个服务员相当于一个线程。多线程处理的方式会是这样的:

一个人来就餐,一个服务员去服务,然后客人会看菜单,点菜,该服务员将菜单给后厨。

二个人来就餐,二个服务员去服务……

五个人来就餐,五个服务员去服务……

如果饭店一直这样同一时间最多来5个客人,这家饭店是可以很好的服务下去的,但如果饭店生意变好,同一时间会有10个客人关顾,原先那套做法就可能出现问题。可以想象一种情形,如果正在接受服务员服务的客人点菜很慢,其他的客人可能就要等好长时间了。有些火爆脾气的客人可能就等不了走人了。这里,究其原因就是因为线程的粒度太大

Reactor就可以很好的解决这个问题,因为点菜才通常是很耗时的,所以当有人来吃饭的时候,服务员可以先把菜单交给点菜的人自己浏览,然后先去招待其他人,等点菜的人想好了要点的菜的时候再招呼服务员,等服务员过来了之后就可以为顾客点菜并发送到后厨了。这个在某种意义上说就是用单线程在做多线程的事情。

这些被拆分的小线程或者任务更加单一的子过程,对应的是Handler,每一种Handler会出处理一种Event。这里会有一个全局的管理者Selector,我们需要把Channel注册感兴趣的事件,那么这个Selector就会不断在Channel上检测是否有该类型的事件发生,如果有就会调用相应的事件处理函数(Handler)来处理。

我们知道TCP/IP在发送消息的时候,数据会被拆成大小合适的包,使用超时重传、顺序编号、校验和等机制,这就导致接收端无法知道什么时候收到的数据是一个完整的数据。例如:发送端分别发送了ABC,DEF,GHI三条信息,发送时被拆成了AB,CDRFG,H,I这四个包进行发送。在BIO模型中,当读不到完整数据时会阻塞,而NIO中则不会。原题中文件、消息可以附上相应的事件标志,交给Selector去分发给相应的Handler。



Reference

【Java】Reactor模式

Reactor(反应器)模式

高性能Server---Reactor模型

高性能IO之Reactor模式
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Reactor ReactJS
相关文章推荐