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

[经验分享] 《How Tomcat Works》读书笔记(二):Connector

[复制链接]

尚未签到

发表于 2017-1-28 08:34:51 | 显示全部楼层 |阅读模式
Chapter Three:Connector
  tomcat的Connector名字叫做Coyote,我之前也写了几篇关于coyote的博客,不过在看了第三章后,才对tomcat的Connector有了更加深入的认识。需要说明的是,这一章的Connector只是一个简化版,而第四章介绍的也只是“默认”(旧版本)的Tomcat的Connector,正因为“默认”的Connector性能不佳,才产生了后来的coyote,这是后话。
StringManager
  在讲述连接器前,首先介绍一个tomcat内部使用频率非常高的工具类——StringManager,简称sm(O(∩_∩)O有点歧义~)。我们知道tomcat是一个大项目,里面的package很多,而每个package内的类都需要输出很多信息,包括错误信息、调试信息,等等。为了降低耦合性,tomcat开发人员专门设计了这个sm类,用来存取相关的输出信息。每个package都有一个“LocalStrings.properties”文件,就像ini文件那样保存了这些信息。我们只需要像下面这样:
  StringManager sm = StringManager.getManager("ex03.pyrmont.connector.http");
  就可以获得一个特定于某个package输出信息的sm,然后直接getString即可。为了便于支持多语言,一般还包括了LocalStrings_es.properties和LocalStrings_ja.properties,sm会自动根据本地语言设置来选择相应的语种,这和Struts非常像(兴许Struts就是模仿tomcat的)。可惜,没有LocalStrings_cn.properties
Bootstrap
  像我们看到的tomcat6一样,在这一章的小例子中,也专门将Bootstrap类提取出来,用于启动tomcat,当然这里还是非常简单的new了一个Connector,以后的章节会陆续添加功能。在这里,Connector实现了Runnable接口
  public final class Bootstrap {
   public static void main(String[] args) {
     HttpConnector connector = new HttpConnector();
     connector.start();
   }
}
Connector
  终于可以一睹Connector的“芳容”了!很遗憾,这一章的Connector还非常简陋,只是把前一章中监听Socket的部分代码copy了过来,略微有点不同的是:
  // Hand this socket off to an HttpProcessor
       HttpProcessor processor = new HttpProcessor(this);
       processor.process(socket);
  很明显,这里多了一个HttpProcessor ,其实就相当于“容器”的角色。tomcat发展到现在,其架构也还是:Connector+Container
HttpProcessor
  可以说,HttpProcessor 是这一章的重头戏,大部分功能都是通过这个类,直接或间接地实现的。
  照旧,在HttpProcessor 的process方法中,首先获取Socket的输入输出流、new 一个Request和Response,然后调用:
  parseRequest(input, output);
     parseHeaders(input);
  这两个方法是本类的核心,parseRequest是处理http请求行(就是类似“GEThttp://xxx.xxx/xxx?name=xxx”,位于http请求的第一行),parseHeaders则处理请求行之后的一堆header,比如content-length、cookie等。别看只有两个方法,深入进去其实调用了很多其他类的方法,看来解析一个http请求也不是那么容易的。
SocketInputStream
  这个类转自tomcat源代码,它对Socket的原始inputstream进行了封装,负责将以下字段分离出来:

  • http schema:请求行中的GET,POST等等
  • URI:例如,http://xxx.xxx/xxx,这里还要区分是绝对路径还是相对路径
  • 查询字符串:就是“?”后面的那些键值对
  • header:http 请求的headers
  当然,分离出来的字段都是以char数组的形式保存的,因为生成String的开销很大,通常都是“lazy load”,不到不得已不会随便new string
Populate Request
  所谓populate,即是“赋值”的意思,就是调用Request的那些set方法,把之前解析出来的那些字段一个个放进Request对象中,供后续使用。考虑到解析、分割字符串的开销很大,tomcat的原则是把查询字符串(query string)和cookie的解析工作放到Servlet中,因为这些字段未必一定会用到,要的时候在生成也不迟,从而节省了系统资源。
  具体的解析过程很啰嗦,基本上都是字符串处理,在一堆字节中摸爬滚打,这里就不赘述了。
Create Response
  相比Request,Response的工作量就小了一些。但也有不少改进之处。首先,之前的Response.getWriter方法,单纯的返回一个包装了Socket的OutputStream的PrintWriter,但这是JAVA自带的PrintWriter,功能上不能完全满足tomcat的需要,例如它的print方法不能自动flush(具体可以参考JavaDoc)。所以,在这里通过两个类:ResponseStream和ResponseWriter,分别拓展了原始的ServletOutputStream和PrintWriter。下面摘取其中一部分代码:
  public void write(String s, int off, int len) {
    super.write(s, off, len);
    super.flush();
  }
  这是ResponseWriter的write方法,可见就是在PrintWriter的方法上多了一个flush而已
其他
  搞定Request后,还是像上一章那样,把Request交给ServletProcessor或者StaticResourceProcessor,基本没有大的变动
总结
  首先,这一章的服务器架构如下:(图片源自原书)
   DSC0000.png
处理流程为:

  • Bootstrap启动HttpConnector
  • HttpConnector监听Socket端口,将得到的Socket对象交给HttpProcessor
  • HttpProcessor通过调用parseRequest和parseHeaders方法,解析底层Socket流中的字节,生成Request对象和Response对象
  • 把Request对象和Response对象交给“容器”处理,即ServletProcessor或者StaticResourceProcessor
  • 载入Servlet对象,利用Facade模式,将Request对象和Response对象传入Servlet的service方法,处理,然后通过Response对象的writer,把响应内容返回给客户端

运维网声明 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-334318-1-1.html 上篇帖子: 关于ECLIPSE下的TOMCAT使用问题 下篇帖子: tomcat 中配置和使用连接池
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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