设为首页 收藏本站
查看: 845|回复: 0

[经验分享] Coyote for Http11: org.apache.coyote.http11

[复制链接]

尚未签到

发表于 2017-1-7 10:40:08 | 显示全部楼层 |阅读模式
概述
  这个包支持http1.1协议,内部分为三类:ARP、NIO、普通http,这里只对最基本的普通http(使用java的IO流,而非NIO流)作简单研究
  根据上一篇提到的coyote的接口,这个包主要有以下几个类:

  • Http11Protocol,实现了ProtocolHandler接口
  • Http11Processor,实现了ActionHook接口
  • InternalInputBuffer,实现了InputBuffer接口
  • InternalOutputBuffer,实现了OutputBuffer接口
  • InputFilter和OutputFilter接口,具体的实现类在 org.apache.coyote.http11.filters 中
  下面是这几个类之间的关系,随便画了一幅图,凑合着看看^_^
DSC0000.png

  大致过程如下:

  • JIOEndpoint起到一个连接池的作用,可以启动多个socket监听,一旦收到浏览器发来的请求后,把对应的socket对象通过process方法,传递给Http11ConnectionHandler,再交给Http11Processor
  • Http11Processor内部有个InternalInputBuffer(图上未画出),InternalInputBuffer是真正对socket中包含的字节流进行处理的,它将字节转换为Request
  • Request流经过滤器filters,最后到达实现了Adapter接口的容器,coyote的工作就到此为止,回头继续处理下一个socket
  下面是几个主要类的功能介绍
Http11Protocol
  http1.1协议的ProtocolHandler实现
  主要包含
Http11ConnectionHandler(内部类)
JIoEndpoint
ServerSocketFactory(J2SE)
大致过程如下:
  在init方法中,将ServerSocketFactory、Http11ConnectionHandler传递给JIoEndpoint进行初始化
  然后,在start、pause等方法中,同样也会调用JIoEndpoint的start、pause
  JIoEndpoint可以设置最大线程数、优先级、端口等属性,根据这些属性,JIoEndpoint生成对应数量的ServerSocketFactory,用于监听相应的端口,一旦收到http请求,JIoEndpoint则将对应的Socket实例传递给Http11ConnectionHandler.process方法进行处理;而Http11ConnectionHandler里头会有一个processor实例,这个实例真正处理socket并将其中的数据转换为Request对象
  因此,ProtocolHandler的作用就是把所有这些和连接有关的组件包装起来,统一设置它们的属性,并负责控制它们的生命周期
Http11Processor
  这个类的作用就是生成Request(当然本质上还是InternalInputBuffer完成的),交给实现了Adapter接口的容器
  这个类有adapter、request、response、inputbuffer、outputbuffer等几个关键字段,其余就是和http协议有关的字段了,还有很多方法是关于http协议的,水平有限实在看不懂,估计要先详细学习一遍http协议才能读懂,这里就略过,直接看最关键的process(Socket socket) 方法
  该方法依次做如下的工作:

  • 把socket的inputstream和outputstream分别与inputbuffer和outputbuffer关联起来
  • 通过inputBuffer.parseRequestLine() 和 inputBuffer.parseHeaders() 方法,解析socket字节流中的头字段,写到request中
  • 通过prepareRequest方法组装filter,用于处理http消息体
  • adapter.service(request, response) 把生成的request和response交给容器处理
  • 如果一切顺利,开始处理socket中的下一个请求(因为http1.1是支持持续连接的,所以一个socket中可能包含多个请求),循环回到第一步
  • 如果出错,则设置response的响应码,并终止循环
  prepareRequest方法,用于准备inputbuffer的filter,这里简单写一下。关于filter的机理,请看:

  • 根据之前对http头字段的解析,分别检查protocol、method、expect、user-agent和MIMEheaders,此外还检查URI的格式(是否符合:protocol://host:port/ 的格式)
  • 准备加载filter
  • 如果有transfer-encoding这个头字段(貌似是编码格式,可以有多个,逗号分割),则分别设置不同编码的filter
  • 校验content-length头字段
InternalInputBuffer
  研究这个类可以从Http11Processor的process方法入手
  这个类的主要功能是:从socket中获取字节流,将字节读入一个缓冲区buf,然后从缓冲区逐个解析http请求头以及内容
  主要的字段:

  • request:Request对象,从缓冲区中解析出的信息会写入request中
  • buf:缓冲区,从socket的inputstream读取的字节放入此缓冲区中
  • headers : MimeHeaders,保存以键值对出现的报头,也就是除去请求报文第一行之后的所有头部
  具体的http请求报头的规范,可以参考W3C,或者
http://www.yuanma.org/data/2008/0827/article_3143.htm
parseRequestLine()
  解析请求报头的第一行,形如:GEThttp://class/download.microtool.de:80/somedata.exe,包括请求方法(GET or POST)、协议(http)、URI。解析后,放入request中
parseHeader()
  解析刚才parseRequestLine()之后的报头,由于RequestLine之后的报头都是以“:”分隔的键值对,因此每执行一次本方法,则在headers 中加入一个键值对,如果格式错误则返回false
endRequest()
  结束一个request的处理,把多余的字节清空
nextRequest()
  准备下一个request的处理,这个方法主要用来对所有的标记位和指针进行复位
fill()
  从socket的inputstream中读出一定数量的字节,填充buf,在很多方法中都有用到。例如解析报头时,当发现buf已经读取完了,就调用fill重新填充buf,如果inputstream已经读完了,fill返回false
InternalOutputBuffer的一些疑问
  根据inputbuffer的理解,可以大致猜到,这个类是用来从response中读取信息,然后写入socket的outputstream中,返回给客户端的
  类里面的方法许多也和inputbuffer一样,但令人纳闷的是居然还有nextRequest()、endRequest()方法,而里面做的事情却是针对response的(OutputBuffer本来就只有response),看不出任何与request有关的东西。难道是作者拷代码过来的时候忘了改方法名称?
  最后,觉得这个类和InternalInputBuffer实在有太多相似之处,为什么不抽象出一个父类呢?

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-325016-1-1.html 上篇帖子: (转)apache common中好用的arrayutils 下篇帖子: proxyServer squid / varnish / apache traffic server / ATS
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表