博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Reactor模式
阅读量:6658 次
发布时间:2019-06-25

本文共 1196 字,大约阅读时间需要 3 分钟。

hot3.png

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

while(true){ 
socket = accept(); 
handle(socket) 
这种方法的最大问题是无法并发,效率太低,如果当前的请求没有处理完,那么后面的请求只能被阻塞,服务器的吞吐量太低。
之后,想到了使用多线程,也就是很经典的connection per thread,每一个连接用一个线程处理,类似:
while(true){ 
socket = accept(); 
new thread(socket); 
tomcat服务器的早期版本确实是这样实现的。多线程的方式确实一定程度上极大地提高了服务器的吞吐量,因为之前的请求在read阻塞以后,不会影响到后续的请求,因为他们在不同的线程中。这也是为什么通常会讲“一个线程只能对应一个socket”的原因。最开始对这句话很不理解,线程中创建多个socket不行吗?语法上确实可以,但是实际上没有用,每一个socket都是阻塞的,所以在一个线程里只能处理一个socket,就算accept了多个也没用,前一个socket被阻塞了,后面的是无法被执行到的。
缺点在于资源要求太高,系统中创建线程是需要比较高的系统资源的,如果连接数太高,系统无法承受,而且,线程的反复创建-销毁也需要代价。
线程池本身可以缓解线程创建-销毁的代价,这样优化确实会好很多,不过还是存在一些问题的,就是线程的粒度太大。每一个线程把一次交互的事情全部做了,包括读取和返回,甚至连接,表面上似乎连接不在线程里,但是如果线程不够,有了新的连接,也无法得到处理,所以,目前的方案线程里可以看成要做三件事,连接,读取和写入。
线程同步的粒度太大了,限制了吞吐量。应该把一次连接的操作分为更细的粒度或者过程,这些更细的粒度是更小的线程。整个线程池的数目会翻倍,但是线程更简单,任务更加单一。这其实就是Reactor出现的原因,在Reactor中,这些被拆分的小线程或者子过程对应的是handler,每一种handler会出处理一种event。这里会有一个全局的管理者selector,我们需要把channel注册感兴趣的事件,那么这个selector就会不断在channel上检测是否有该类型的事件发生,如果没有,那么主线程就会被阻塞,否则就会调用相应的事件处理函数即handler来处理。典型的事件有连接,读取和写入,当然我们就需要为这些事件分别提供处理器,每一个处理器可以采用线程的方式实现。一个连接来了,显示被读取线程或者handler处理了,然后再执行写入,那么之前的读取就可以被后面的请求复用,吞吐量就提高了。

转载于:https://my.oschina.net/craftsdream/blog/2239683

你可能感兴趣的文章
记录一个坑(js)
查看>>
Fragment的使用
查看>>
异常处理汇总-开发工具
查看>>
eclipse svn提交忽略文件及文件夹,ignore设置无效..
查看>>
我为公司做的总体架构,欢迎提建议
查看>>
如何成为一名优秀的web前端工程师(前端攻城师)?
查看>>
【8086汇编基础】04--中断
查看>>
laravel 5.5 数据库迁移报错
查看>>
小记:《技术进步引发的灵感革命》网易游戏学院第二届公开日
查看>>
【C#并发】00概述
查看>>
[转] Webpack的devtool和source maps
查看>>
查询表结构视图
查看>>
input type file onchange上传文件的过程中,同一个文件二次上传无效的问题。
查看>>
Java入门篇(一)——如何编写一个简单的Java程序
查看>>
Kotlin Coroutine(协程) 基本知识
查看>>
JavaScript系列-this详解
查看>>
浅谈 Objective-C Associated Objects
查看>>
陆瀚卿:非农做单十大技巧,掌握六条算你赢!
查看>>
9章 RxJava混合实战
查看>>
1002 A+B for Polynomials
查看>>