Jetty9源码剖析 - Connection组件 - HttpOutput

转载自ph0ly:http://www.ph0ly.com

一、概念

HttpOutput实现了ServletOutputStream,提供应用层写数据的各种操作

二、继承体系

继承体系

HttpOutput继承自ServletOutput,实现了Runnable,和HttpInput基本一致,没啥说的

三、源码剖析

1. 创建

创建

前面说过HttpOuput是在HttpChannel创建时创建,和HttpInput一样,它仍然是一条连接一个实例,上图是它的构造函数
比较简单,用了个WriteBlocker,其实是一把带超时的锁

2. 写数据

write

HttpOutput其实是支持异步写,里面也带了一个状态机,不过这篇文章我们仅看同步模式下的写
上图是write方法的一部分,也是它最核心的地方
对于应用层调用write操作,如果应用写入的数据量小于配置的提交大小,就会积攒buffer,等达到提交大小时,再调用write方法写,或者用户层写入的数据直接就很大,超过了提交大小,就直接写

接下来看下write方法的实现

write-2

可以看到利用Blocker这把阻塞锁,调用write后阻塞,而write其实调了拦截器,前面提到拦截器就是HttpChannel

write-3

上图是HttpChannel的write方法,也就是上面调用的拦截器方法,这里就会调HttpChannel.sendResponse,而在HttpChannel章节提到过,sendResponse方法会调用HttpTransport类的send方法,即HttpConnection.send,最后HttpConnection会调用EndPoint往SocketChannel写数据,这样就完成了数据响应

3. 关闭

close

前面提到了write操作会积攒buffer,而HttpOutput也没有什么超时机制来保证刷数据,那是哪里触发刷的呢?其实HttpOutput提供了两种方式,第一种是flush,应用层直接调OutputStream.flush,另一种是应用层完成数据写入,并完成业务处理,这时控制权就回到Jetty框架层,而Jetty发现这个请求已经完成处理,这时候会在HttpChannel里面触发HttpOutput.close方法(当然不一定是直接触发)
这里我们看default分支,就会调write刷数据

4. 回收

recycle

由于HttpOutput是同一连接共享,因此每一个请求完成后都需要回收,可以看到就是把一些状态或参数置为初始状态

四、总结

HttpOutput最核心的也就是刷数据了,而在刷的策略上,它选了将小的Buffer积攒成一个大Buffer,实现更高效的数据写入,如果面对较大Buffer,则直接刷出去,这种策略都是比较常见的。这篇文章就写这么多,对于异步写这篇文章没提过多,后续将会和Servlet3异步专题来更详细说明。接下来的文章我会继续分析下一个组件HttpGenerator,欢迎大家持续关注~

猜你喜欢

转载自blog.csdn.net/qq_41084324/article/details/83382847