Reactor

Netty 线程模型与Reactor 模式

微笑、不失礼 提交于 2020-11-18 05:21:49
前言 Netty 的线程模型是基于NIO的Selector 构建的,使用了异步驱动的Reactor 模式来构建的线程模型,可以很好的支持成百上千的 SocketChannel 连接。由于 READ/WRITE 都是非阻塞的,可以充分提升I/O线程的运行效率 ,避免了IO阻塞导致线程挂起, 同时可以让一个线程支持对多个客户端的连接SocketChannel的 READ/WRITE 操作, 从根本上解决了传统阻塞IO的一线程处理一连接的弊端。 高效率的Reactor模式 Reactor 模式 是一种为处理服务请求并发,提交到一个或者多个服务处理程序的事件设计模式。当请求抵达后,服务处理程序使用解多路分配策略,然后同步地派发这些请求至相关的请求处理程序 (来自维基百科: https://zh.wikipedia.org/wiki/反应器模式 ) 常见的reactor模式有以下三种 单线程reactor 多线程reactor 主从reactor 1、单线程reactor ractor 单线程模式是指所有的I/O操作都在一个NIO线程完成,该线程的职责: 1.作为NIO服务端,接收客户端TCP连接 2.作为NIO客户端,向客户端发送TCP连接 3.READ/WRITE 客户端的请求 不过单线程的reactor 模式无法发挥多核的优势,因此对于高并发量的系统仍然存在瓶颈,主要原因如下: 1

「网络IO套路」当时就靠它追到女友

最后都变了- 提交于 2020-11-16 08:26:45
今天分享的基本上一面试就会被问的网络IO,文中涉及的代码部分不太重要,重要的是对这概念的理解。在看文章之前大家也可通过下面的思维导图看看自己是否能回答出来。 大纲 1 阻塞与非阻塞--开胃菜 阻塞 我们知道在调用某个函数的时候无非就是两种情况,要么 马上返回 ,然后根据返回值进行接下来的业务处理。当在使用 阻塞IO 的时候,应用程序会被无情的 挂起 ,等待内核完成操作,因为此时的内核可能将CPU时间切换到了其他需要的进程中,在我们的应用程序看来感觉被卡主(阻塞)了。 阻塞IO 传统阻塞IO模型 传统阻塞IO模型 特点: 通过阻塞式IO获取输入的数据 其中每个连接都采用独立的线程完成数据输入,业务处理以及数据返回的操作 这种方案有什么问题? 首先当并发较大的时候,需要创建大量的线程来处理连接,需要占用大量的系统资源。 连接建立完成以后,如果当前线程没有数据可读,将会阻塞在read操作上造成线程资源的浪费 鉴于上面的两个问题,通常是解决方案是啥呢? 第一种是 采用IO复用的模型 ,所谓IO复用模型即多个连接共享一个阻塞对象,应用程序只会在一个阻塞对象上等待。当某个连接有新的数据处理,操作系统直接 通知 应用程序,线程从阻塞状态返回并开始业务处理 第二种方案即采用 线程池复用的方式 。将连接完成后的业务处理任务分配给线程,一个线程处理多个连接的业务

深入浅出Rust异步编程之Tokio

让人想犯罪 __ 提交于 2020-11-05 04:10:44
深入浅出Rust异步编程之Tokio 本文以tokio为例简单介绍Rust异步编程相关的一些知识。 首先让我们看看为什么使用rust来进行异步编程。这里tokio官方给出了一个性能测试的对比,可以看到tokio是性能最好,实际上运行这个基准测试的时候,tokio性能更好的2.0版本尚未发布,否则估计性能还有很大提升。因此,我们可以认为需要非常极致性能的时候,我们可以选择rust+tokio来实现。 Rust网络编程 Rust实际上并不跟一定的网络编程模型强绑定,实际rust可以实现阻塞IO+多线程,非阻塞IO+回调,用户态线程等多种模型。这里着重介绍Rust实现的用户态线程。 首先,Rust的用户态线程是一种基于Future的用户态线程,关于Future本身,本文后续部分有详细论述。 其次,由于是Rust实现,因此可以做到零成本抽象,并且更容易做到安全。 最后,由于没有运行时大量内存分配,没有动态逻辑分派,也没有GC开销,所以该实现的效率非常高。 Rust异步编程是构建在操作系统相关API上,MIO库类似Java的Nio库,针对多种操作系统的不同API做了统一封装。Future库类似Java的Future库,提供了相关接口和常用的组合能力。Tokio构建于两者之上,在MIO和future的基础上实现了用户态线程。使用Tokio进行异步编程的技术栈如下,需要注意的是

「网络IO套路」当时就靠它追到女友

烈酒焚心 提交于 2020-11-01 09:59:52
一周至少一篇到今天已经持续 30 周了,希望每一篇多多少少能给大家带来点干货。同样的,今天分享的基本上一面试就会被问的网络IO。文中涉及的代码部分不太重要,重要的是对这概念的理解。在看文章之前大家也可通过下面的思维导图看看自己是否能回答出来。 大纲 1 阻塞与非阻塞--开胃菜 阻塞 我们知道在调用某个函数的时候无非就是两种情况,要么 马上返回 ,然后根据返回值进行接下来的业务处理。当在使用 阻塞IO 的时候,应用程序会被无情的 挂起 ,等待内核完成操作,因为此时的内核可能将CPU时间切换到了其他需要的进程中,在我们的应用程序看来感觉被卡主(阻塞)了。 阻塞IO 传统阻塞IO模型 传统阻塞IO模型 特点: 通过阻塞式IO获取输入的数据 其中每个连接都采用独立的线程完成数据输入,业务处理以及数据返回的操作 这种方案有什么问题? 首先当并发较大的时候,需要创建大量的线程来处理连接,需要占用大量的系统资源。 连接建立完成以后,如果当前线程没有数据可读,将会阻塞在read操作上造成线程资源的浪费 鉴于上面的两个问题,通常是解决方案是啥呢? 第一种是 采用IO复用的模型 ,所谓IO复用模型即多个连接共享一个阻塞对象,应用程序只会在一个阻塞对象上等待。当某个连接有新的数据处理,操作系统直接 通知 应用程序,线程从阻塞状态返回并开始业务处理 第二种方案即采用 线程池复用的方式

java.io.IOException: mark/reset not supported 异常

五迷三道 提交于 2020-10-29 00:30:41
在 Azure 上传文件的时候遇到了一个下面的异常: java.io.IOException: mark/reset not supported at java.base/java.io.InputStream.reset(InputStream.java:655) at com.azure.storage.common.Utility.lambda$convertStreamToByteBuffer$4(Utility.java:236) at reactor.core.publisher.FluxDefer.subscribe(FluxDefer.java:46) at reactor.core.publisher.Mono.subscribe(Mono.java:4213) 问题解决 当给定的流不支持 mark 和 reset 就会报这个错误。 我们用的代码是: blobClient .upload ( inputStream , inputStream .available ()); InputStream 是不支持 mark 和 reset 的。 BufferedInputStream继承于FilterInputStream,提供缓冲输入流功能。 缓冲输入流相对于普通输入流的优势是,它提供了一个缓冲数组,每次调用read方法的时候,它首先尝试从缓冲区里读取数据,若读取失败