面试题:在传送文件时卡住,还想发送聊天信息
2018-07-01 19:23
183 查看
写在前面的话:我写博客是为了训练自己的表达能力,更多是为了记录自己的一些工作思路,好记性不如烂笔头。所以博客写出来的内容不像写论文那样负责,写学术论文会反复修改几十遍,并且在投稿时还有专业理论技术审稿。写博客,就像是在创作同人作品,看着有趣就行了。
这种方法的最大问题是无法并发,效率太低,如果当前的请求没有处理完,那么后面的请求只能被阻塞,服务器的吞吐量太低。之后,想到了使用多线程,每一个连接用一个线程处理,类似:
这个实现方式比第一个好很多,因为在不同的线程中,前一个请求的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。
Reactor(反应器)模式
高性能Server---Reactor模型
高性能IO之Reactor模式
面试题目
设计一个聊天软件,如果你在传送文件时卡住,还想发送聊天信息,你怎么解决?问题建模
服务器接收文件卡住,是否继续空等待,可以看成非阻塞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模式
相关文章推荐
- HttpURLConnection 发送 文件和字符串信息
- java HttpURLConnection 发送文件和字符串信息
- HttpURLConnection 发送 文件和字符串信息
- 点对点聊天(发送+接收文件)基类
- Python爬虫-爬取集思录的金融信息,并写入文件和检测数据变化发送邮件通知
- 基于openfire+smack开发Android即时聊天应用[四]-单人聊天、群聊、发送接收文件等
- 利用Socket.Send发送信息、Socket.SendFile传输文件
- Android将程序崩溃信息保存本地文件发送至服务器
- httpclient 发送文件和字符串信息
- http协议8---响应信息头案例三(content-Type作用,实现发送一个文件(html,XML,image))
- 微信插件开发手记-聊天界面传送任意类型文件
- 聊天系统Demo,增加文件传送功能(附源码)-- ESFramework 4.0 快速上手(14)
- TCP c/s模式实现点对点,一对多聊天 识别不同的TCP通道.给相应的TCP客户发送信息
- 使用curl查看网页源码/自动跳转/显示头信息/显示通信过程/发送表单信息/文件上传/Referer字段/User Agent
- 免费局域网聊天传送文件软件—飞秋
- java在线聊天项目0.3版本 制作客户端窗体,实现发送按钮和回车发送信息功能,使用ActionListener监听事件中actionPerformed方法(用内部类和匿名内部类两种方法)
- XMPP协议发送聊天消息,图片,文件
- 基于Qt的P2P局域网聊天及文件传送软件设计
- TCP c/s模式实现点对点,一对多聊天 识别不同的TCP通道.给相应的TCP客户发送信息
- Dynemic Web Project中使用servlet的 doGet()方法接收来自浏览器客户端发送的add学生信息形成json字符串输出到浏览器并保存到本地磁盘文件