分享:
专栏如今已经更新完了五个模块,我们学习了Tomcat和Jetty的整体架构、连接器、容器和通用组件,这些内容可以说是Tomcat和Jetty的设计核心。在日常工作的使用中,我们使用到了Tomcat和Jetty提供的功能,我希望通过学习专栏,还能帮你了解这些功能是如何实现的,以及Tomcat和Jetty在设计时都考虑了哪些地方。
所以在学习专栏时,你不妨思考这样一个问题,假如让你来设计并实现一个Web容器,你会怎么做呢?如何合理设计顶层模块?如何考虑方方面面的需求,比如最基本的功能需求是加载和运行Web程序,最重要的非功能需求是高性能、高并发。你可以顺着这两条线先思考下你会怎么做,然后再回过头来看看Tomcat和Jetty是如何做到的。这样的学习方法其实就在有意识地训练自己独立设计一个系统的能力,不管是对于学习这个专栏还是其他技术,带着问题再去学习都会有所帮助。
说完关于专栏的学习方法,下面我必须要鼓励一下坚持学习到现在的你。专栏从第三模块开始,开始讲解连接器、容器和通用组件的设计和原理,有些内容可能比较偏向底层,确实难度比较大,如果对底层源码不熟悉或者不感兴趣,学习起来会有些痛苦。但是,我之所以设计了这部分内容,就是希望能够揭开Tomcat和Jetty的内部细节,因为任何一个优秀的中间件之所以可以让用户使用比较容易,其内部一定都是很复杂的。这也从侧面传递出一个信号:美好的东西都是有代价的,需要也值得我们去付出时间和精力。
我和你一样我们都身处IT行业,这个行业技术更新迭代非常快,因此我们需要以一个开放的心态持续学习。而学习恰恰又是一个反人性的过程,甚至是比较痛苦的,尤其是有些技术框架本身比较庞大,设计得非常复杂,我们在学习初期很容易遇到“挫折感”,一些技术点怎么想也想不明白,往往也会有放弃的想法。我同样经历过这个过程,我的经验是找到适合自己的学习方法非常重要,同样关键的是要保持学习的兴趣和动力。
举个我学习Spring框架的例子,记得当时我在接触Spring框架的时候,一开始就钻进一个模块开始啃起了源代码。由于Spring框架本身比较庞杂,分很多模块,当时给我最直观的感受就是看不懂,我不明白代码为什么要这么写,为什么设计得这么“绕”。这里面的问题是,首先我还没弄清楚森林长什么样子,就盯着树叶看,很可能是盲人摸象,看不到全貌和整体的设计思路。第二个问题是我还没学会用Spring,就开始研究它是如何设计的,结果可想而知,也遇到了挫折。后来我逐渐总结出一些学习新技术的小经验:在学习一门技术的时候,一定要先看清它的全貌,我推荐先看官方文档,看看都有哪些模块、整体上是如何设计的。接着我们先不要直接看源码,而是要动手跑一跑官网上的例子,或者用这个框架实现一个小系统,关键是要学会怎么使用。只有在这个基础上,才能深入到特定模块,去研究设计思路,或者深入到某一模块源码之中。这样在学习的过程中,按照一定的顺序一步一步来,就能够即时获得成就感,有了成就感你才会更加专注,才会愿意花更多时间和精力去深入研究。
因此要保持学习的兴趣,我觉得有两个方面比较重要:
第一个是我们需要带着明确的目标去学习。比如某些知识点是面试的热点,那学习目标就是彻底理解和掌握它,当被问到相关问题时,你的回答能够使得面试官对你刮目相看,有时候往往凭着某一个亮点就能影响最后的录用结果。再比如你想掌握一门新技术来解决工作上的问题,那你的学习目标应该是不但要掌握清楚原理,还要能真正的将新技术合理运用到实际工作中,解决实际问题,产生实际效果。我们学习了Tomcat和Jetty的责任链模式,是不是在实际项目中的一些场景下就可以用到这种设计呢?再比如学习了调优方法,是不是可以在生产环境里解决性能问题呢?总之技术需要变现才有学习动力。
第二个是一定要动手实践。只有动手实践才会让我们对技术有最直观的感受。有时候我们听别人讲经验和理论,感觉似乎懂了,但是过一段时间便又忘记了。如果我们动手实践了,特别是在这个过程中碰到了一些问题,通过网上查找资料,或者跟同事讨论解决了问题,这便是你积累的宝贵经验,想忘记都难。另外适当的动手实践能够树立起信心,培养起兴趣,这跟玩游戏上瘾有点类似,通过打怪升级,一点点积累起成就感。比如学习了Tomcat的线程池实现,我们就可以自己写一个定制版的线程池;学习了Tomcat的类加载器,我们也可以自己动手写一个类加载器。
专栏更新到现在,内容最难的部分已经结束,在后面的实战调优模块,我在设计内容时都安排了实战环节。毕竟调优本身就是一个很贴近实际场景的话题,应该基于特定场景,去解决某个性能问题,而不是为了调优而调优。所以这部分内容也更贴近实际工作场景,你可以尝试用我前面讲的方法,带着问题学习后面的专栏。
调优的过程中需要一些知识储备,比如我们需要掌握操作系统、JVM以及网络通信的原理,这些原理在专栏前面的文章也讲到过。虽然涉及很多原理也很复杂,并不是说要面面俱到,我们也不太容易深入到每个细节,所以最关键的是要弄懂相关参数的含义,比如JVM内存的参数、GC的参数、Linux内核的相关参数等。
除此之外,调优的过程还需要借助大量的工具,包括性能监控工具、日志分析工具、网络抓包工具和流量压测工具等,熟练使用这些工具也是每一个后端程序员必须掌握的看家本领,因此在实战环节,我也设计了一些场景来带你熟悉这些工具。
说了那么多,就是希望你保持对学习的热情,树立明确的目标,再加上亲自动手实践。专栏学习到现在这个阶段,是时候开始动手实践了,希望你每天都能积累一点,每天都能有所进步。
总结语:
从专栏上线发布到现在,不知不觉三个月时间过去了,感谢你的一路陪伴,今天到了说再见的时候,我想简单回顾一下专栏的内容,并且聊聊我的一些感受。
Tomcat和Jetty发展这么多年,已经比较成熟稳定。这些年技术发展迭代速度又很快,在一个“追新求快”的时代,Tomcat和Jetty作为JavaWeb开发的必备工具,似乎变成了“熟悉的陌生人”。对于很多新同学来说,虽然有些Tomcat和Jetty的知识点在面试中会碰到,但从侧面来说Tomcat和Jetty似乎没有那么“火”,那是不是说如今就没有必要深入学习Tomcat和Jetty了呢,只要会用就行呢?要回答这个问题,我先讲讲为什么我选择这个主题来写专栏吧。我写这个专栏的初心还是希望我们可以静下心来,细细品味经典的开源作品,从而进一步提升我们的“内功”。“内功”这个词有些抽象,具体来说就是学习大牛们如何设计、架构一个中间件软件系统,并且让这些经验可以为自己所用。作为一名IT从业者,我认为我们很有必要深入思考一下,这些大牛为什么能够创造出这些优秀的作品,并且能引领技术的发展呢。
不知道你发现没有,美好的事物往往是整洁而优雅的。但这并不等于简单,而是要将复杂的系统分解成一个个小模块,并且各个模块的职责划分也要清晰合理。与此相反的是凌乱无序,比如你看到一堆互相纠缠在一起的电线,可能会感到不适。
同样的道理,当我们在设计一个软件系统时,追求的目标也应该是整洁和优雅。我觉得首先需要合理划分功能模块,主要是分清楚“变与不变”的边界,因为变化往往会给系统实现带来混乱,因此需要将“变”的因素控制、隔离起来。如果你发现一个软件系统里有大量ifelse语句、大量的重复代码、大量的相互依赖,那么这个系统多半还有提高的空间,所以分清楚“变与不变”十分重要。
从宏观上看,中间件实现的功能基本上是稳定不变的,它们往往会实现一些协议和规范,比如Tomcat作为一个“HTTP服务器+Servlet容器”,它向开发人员屏蔽应用层协议和网络通信细节,我们拿到的是一个标准的Request和Response对象;而具体业务逻辑则作为变化点,交给我们来实现。
从微观上来看,Tomcat内部也隔离了变化点和不变点,比如Tomcat和Jetty都采用了基于组件化的设计,其目的就是为了实现“搭积木式”的高度定制化,而组件的生命周期管理有一些共性,被提取出来成为接口和抽象类,而具体子类实现变化点。
其实当下流行的微服务也是这个思路,首先按照功能将单体应用拆成微服务,拆分的过程中要注意从众多微服务中提取一些共性,而这些共性就会成为一些核心的基础服务,或者成为一些通用库。
设计模式往往是封装变化的一把利器,我在专栏里也谈到不少Tomcat和Jetty所采用的设计模式,合理地运用设计模式能让我们的代码看起来优雅且整洁。
除此之外,我们在编写程序时应该时刻考虑到高性能,尤其是开发基础的中间件系统,在大数据量、高并发情况下,可能一行代码的改动会带来明显的性能提升。高效意味着合理的数据存储和流动方式,换句话说其实就是合理地运用数据结构和算法,举个最简单的例子,在某个场景是选择数组还是链表。如果你深入了解过Tomcat,你会发现在许多实际场景中,Tomcat都会有针对性的选择,所以对于一些常见的数据结构和算法,虽然我们不需要深入到实现细节,但是一定要知道在什么场景下用哪个。
此外写高性能程序,还意味着你需要掌握操作系统底层原理,并且深入到JVM底层的实现细节,比如我们调用了一个JavaAPI,JVM和操作系统在背后为我们做了什么呢?挖得更深一点,我们对程序的理解也就更深刻,也许就是因为深入的这一小步,能够让我们在竞争中脱颖而出。
不知不觉,我从Tomcat和Jetty的学习谈到了如何优雅地设计一个复杂的系统。由点及面,你可以把Tomcat和Jetty当作一个支点,从我们身边“熟悉又陌生”的Tomcat和Jetty入手,不光掌握它们的使用,更能从它们的源码中汲取经验,提升自己的系统设计能力。学习这件事千万不能浮躁,很难做到一口吃成大胖子,最重要的是需要静下心慢慢体会和思考。我看到不少同学的留言,从提问的内容我能感受到你们的好奇心和思考,有些问题我也还要去查阅源码才能回答上来,在这个过程中我自己也主动或被动的学到不少东西,所以说多和同行们交流也非常有必要。学习永远在路上,最后祝我们一起进步!