Tomcat外传:孤独的小猫咪

456 阅读11分钟

在我印象中,服务器应该是冷冰冰的大铁柜,在恒温恒湿的机房里待着,所以Tomcat是什么呢,为什么也叫服务器呢?

Tomcat学艺

Tomcat,熟悉的陌生人。我们所有的项目都运行在它上面,而我们却往往对它视而不见。现实中也是如此,我们周围充满了空气,我们无时无刻不在呼吸,但你从来没关心过它。同样的,Tomcat于我们而言,也只是在创建环境或者运行项目爆出各种错误时,才会去看看它。

上世纪90年代在大洋彼岸,有一家名唤SUN的公司,创造了一门全新的语言,叫Java。经过短短几年的发展,一跃成为市场上最炙手可热的语言。随后又悟出“Java13绝技”,也就是所谓的JavaEE规范:JDBC,JNDI,EJB,RMI,JSP,Servlets,XML,JMS,Java IDL,JTS,JTA,JavaMail,JAF。

在大洋彼岸还有一家公司,准确来说它是一个组织,专门搞开源的,叫Apache。这家公司搞出了一个叫Tomcat的服务器。这个名字取得真好啊。中国有个词叫三脚猫,专门来吐槽别人功夫不到家。巧了,Tomcat也没完全实现JavaEE规范。13种核心技术,Tomcat只实现了俩:Servlet和JSP。而其他服务器比如JBoss、Weblogic啥的都是完全支持的。所以人们往往更愿意叫Tomcat为轻量级的服务器,也有叫它Servlet/JSP容器的。

听到这,你不禁大叫:不对啊,我记得自己写的程序里有用到JDBC啊,还可以运行哩!

啊,那是因为你导了JDBC包...但是你安装了Tomcat后另外导过Servlet/JSP的包吗?没有嘛!人家实现了Servlet/JSP规范,都整到自己源码里了。

说到这,我也是泪流满面。因为我才发现自己也是个三脚猫。上面“Java13绝技”我特么也就学过JDBC/XML/JSP/Servlet...所以我更愿意称自己是JavaWeb程序员,而不是JavaEE程序员。JavaEE其实很重,我拿不动,打扰了。

我们为什么需要服务器?

在我看来,服务器最本质的作用有两个:

  • 将资源对外暴露
  • 配合各种传输协议进行响应输出 假设现在有个问题:

给你两台电脑,不通过蓝牙/QQ/微信,也不通过网盘或USB等可移动设备做中介,你要如何把一张图片从一台电脑传到另一台?

图片.png

听到这个问题,我估计大部分非科班的朋友都要懵。因为如果后期没有刻意去学习计算机网络,我们对于网络的了解基本仅限于基础班4小时的“网络编程”讲解。而大家平时又太习惯地址栏键入 www.baidu.com ,无脑一回车就上网冲浪了。现在突然让你去访问隔壁的电脑,确实有点束手无策。

解决这个问题的方法可能有多种,这里介绍其中一种:通过服务器访问。

请先了解以下三个概念:

  • IP:电子设备(计算机)在网络中的唯一标识,一个IP对应一台实体电脑
  • 端口:应用程序在计算机中的唯一标识,一个端口只能被唯一程序占用
  • 传输协议:数据传输的规则

中国有14亿人口,每个人都有唯一的身份标识:身份证,用以精确定位某个个体。同样的,网络上有几十亿台电脑,每台电脑都有自己的一串特有IP(不同局域网内可以相同),也就是说一个IP代表一台特定的实体电脑。比如《唐伯虎点秋香》中华安的编号是9527,而华府的管家从不叫他名字,而是直接喊“9527”。因为“9527”就是华安。

图片.png

虽然根据IP可以精准定位一台电脑,但是还不足以让我们访问这台电脑。就好比你知道了我的门牌号,但是我没给你开门。所谓的门,就是一个端口,而端口的背后是应用程序。

一般来说,一个端口可以定位一个软件,但一个软件可以占用多个端口(你家的门,只属于你家,但可以有前后门)。在现实生活中,你家的门如果被别人占用了或者堵了,客人(请求)就进不去了。而在程序中,如果有两个程序的端口相同,就会发生端口冲突,也就是所谓的“端口占用”。端口占用的后果往往是程序无法启动,更遑论运行。

关于端口,再举个例子: 微信和QQ都是腾讯公司的,你的电脑上同时装了这两个软件。为什么我用QQ给你发消息,你的微信收不到?正常人看起来很傻的问题,实际上并不是那么简单。

图片.png

每个应用程序都有自己的端口号(可能有多个),它们一旦运行,就要去监听这些端口。每个程序都是电脑的囚犯,看不到外面的世界,而端口就是给这些囚犯送饭的窗口。应用程序们整天躲在电脑里盯着自己的端口们,祈求着别的计算机来访时能送个大鸡腿(Request请求)。

其实QQ这些软件属于C/S架构,已经为我们屏蔽了太多底层,什么IP、端口全部都是自动封装的。相比来说,B/S架构更直观一些。比如用浏览器访问百度:

图片.png

想要访问一台服务器,必须知道它的IP。但我们人类不擅长记忆长串数字,于是人类搞了所谓的域名来指向IP。但实际请求时,最终还是要换算成IP去访问。总得来说有两种换算的途径:

  • 本机的hosts文件
  • DNS服务器

不知道有没有细心的朋友注意到了下面的细节:

图片.png

即使DNS解析域名得到对应的IP后,Request请求里还是会带上host。为什么?

因为:域名!=IP。

实际上一个IP可以对应多个域名。也就是说一台实体服务器(大铁柜),理论上可以有多个域名(虚拟主机)。实体服务器和网站是两个概念。IP只是对应实体服务器,而域名对应具体的网站。 比如上面百度服务器,虽然看起来115.239.210.27这个IP完全等同于.baidu.com,但也有可能这个IP对应的服务器上配置了两个虚拟主机:www.baidu.com 和 tieba.baidu.com。所以即使找到了IP对应的服务器实体,Request请求还是要带上host主机名,以确定是哪个虚拟主机。

图片.png

另外,如果两个域名对应同一个IP,那么必须设置其中一个域名为默认的,不然同一台服务器有两个虚拟主机,我该访问谁?

图片.png

最后,再用Tomcat举个例子。比如,现在我有一台笔记本电脑(一个实体服务器),它的本机IP是192.168.112.1,我在上面装了Tomcat。如果Tomcat不改动配置,则默认只有一个虚拟主机localhost(默认主机)。接着我开发了一个JavaWeb程序demo1部署到Tomcat,然后我同事在浏览器输入下方地址:

192.168.112.1:8080/demo1/index.html

访问我的电脑。虽然没有带host,但是localhost是默认的,于是访问它。

图片.png

不过,上面的百度服务器只是举个例子,实际上百度搜索和百度贴吧的IP是不同的,也就是说它们不在同一台服务器上。通常来说,一个IP对应一台服务器,服务器上只有一个主机,拿到IP基本就可以确定要访问哪个网站。

图片.png

图片.png

3个容易混淆的小概念

我们经常开口闭口“服务器”、“服务器”的,其实“服务器”是个很容易引发歧义的概念,我能想到的就有3点:

  • 软件概念的服务器和硬件概念的服务器
  • Web服务器?Web容器?
  • 我们开发的Web应用都是半成品!

软件概念的服务器和硬件概念的服务器

软件概念上,只要是一台硬件配置正常、装有操作系统、插着电能上网,并且安装特定软件的电脑,都可以称为服务器。比如你要学习数据库了,于是你装了MySQL服务端,那么此时你的电脑就是一个MySQL服务器。然后你又装了SVN服务端,那么此时你的电脑既是MySQL服务器,又是SVN服务器。Tomcat服务器同理。

硬件概念上,服务器本质上也是一台电脑,只不过配置高的同时长相丑了点,基本就是一个冰冷的大铁柜。我们的笔记本电脑既能看片又能玩游戏,而它们基本上专机专用。

Web服务器?Web容器?

其实,Tomcat服务器 = Web服务器 + Servlet/JSP容器(Web容器)。

Web服务器的作用是接收客户端的请求,给客户端作出响应。但是很明显,服务器不止静态资源呀,所以客户端发起请求后,如果是动态资源,Web服务器不可能直接把它响应回去(比如JSP),因为浏览器只认识静态资源。所以对于JavaWeb程序而言,还需要JSP/Servlet容器,JSP/Servlet容器的基本功能是把动态资源转换成静态资源。我们JavaWeb工程师需要使用Web服务器和JSP/Servlet容器,而通常这两者会集于一身,比如Tomcat。

Web服务器接收、响应客户端请求,Web容器装载Servlet/JSP,让它们去处理动态资源:

图片.png

所以刚才我们画的百度服务器,其实细节还可以更丰满些:

图片.png

图片.png

我们开发的Web应用都是半成品!

我们写代码的时候,都知道相同代码最好抽取成公共方法以复用。现在我们来想一想,上百上千的Web应用有什么共性吗?

首先,资源肯定不同,无法抽取。比如优酷主打视频,知乎基本都是文字。

其次,业务也肯定不同,比如百度主要是搜索,淘宝是电商。但是有一点是一样的,这些网站都需要“接收用户请求”+“响应用户请求”。

嗯?桥多麻袋!!这两个概念,好像哪里见过!不错,就是上面的Web服务器。仔细回想一下,我们开发JavaWeb时,你操心过如何接收HTTP请求和响应HTTP请求吗?显然没有嘛!因为你一直忙着debug。所以,我们用Java开发的Web应用只是一个半成品,类似于一个插件,而服务器则像一个收发器:

图片.png

什么是动态资源?

其实对于何谓动态资源,我也没有很精准的概念。要讲清楚一个东西是什么,有时是比较难的事。不如先说它不是什么。

动态资源不等同于动态页面。所谓动态页面,就是页面会动,而会动的页面不一定是动态资源。比如我可以用JQuery执行一段代码,让一个Div不断放大缩小,但是很显然它还是一个HTML页面。

所谓动态资源,其实最显著的特征就是它能动态地生成HTML!比如JSP。动态资源有个“特色”:它的数据是“可拼装”的、而且“可以随时间变化”。下面用号称可以抗住8个明星同时出轨的新浪服务器举个例子:

图片.png

突然,新浪《花花世界》专栏的小编发现,原来和bravo1988有绯闻的不是刘亦菲,而是佟丽娅,于是打开专栏做了修改:

图片.png

此时,粉丝们再次打开《花花世界》专栏,看到的就是:佟丽娅深夜买醉bravo。 上面这个例子很好地说明了动态资源(JSP)的两个特性:

  • 可拼装:${name}"深夜买醉bravo"
  • 随时间变化:刘亦菲→佟丽娅

那么为什么说HTML就是静态资源呢?我也可以修改HTML页面使它发生改变啊!很好,很有想法。那么请小编先学会Linux,然后远程连接服务器进入到Tomcat目录下修改吧。

图片.png

动态资源和静态资源虽然都在服务器里,但是动态资源包含变量(“可拼装”特性),而变量维系着数据库和程序之间的联系。

如果把JSP比作电子广告牌,变量比作一根电线,而电线连接着一台电脑(数据库服务器)。那么只要电脑上重新编辑文本,广告牌的内容也会变,此谓动态。而静态资源就像一张布告,当初写什么就是什么,任他风吹雨打,都不会再改变了。

图片.png

动手实现"Tomcat"

最后,还有个很无聊的问题留给大家思考:JavaSE阶段,我们无论做什么,都是上来先敲main()。学了JavaWeb后,我想问问,你有多久没敲main()了?她去哪了呢?

图片.png

我是bravo1988,下次见。

よろしく・つづく

我昨晚梦见你了.gif