目录
[一 WEB 技术](#一 WEB 技术)
[1.1 HTTP 协议和 B/S 结构](#1.1 HTTP 协议和 B/S 结构)
[1.2 前端三大核心技术](#1.2 前端三大核心技术)
[1.2.1 HTML](#1.2.1 HTML)
[代码逐行解析(Line-by-Line Breakdown)](#代码逐行解析(Line-by-Line Breakdown))
[企业级生产应用(Enterprise Scenario)](#企业级生产应用(Enterprise Scenario))
[1.2.2 CSS (Cascading Style Sheets) 层叠样式表](#1.2.2 CSS (Cascading Style Sheets) 层叠样式表)
[1.2.3 JavaScript](#1.2.3 JavaScript)
[二 WEB 框架](#二 WEB 框架)
[2.1 web 资源和访问](#2.1 web 资源和访问)
[2.2 后台应用架构](#2.2 后台应用架构)
[2.2.1 单体架构](#2.2.1 单体架构)
[2.2.2 微服务](#2.2.2 微服务)
[2.2.3 单体架构和微服务比较](#2.2.3 单体架构和微服务比较)
[Spring cloud](#Spring cloud)
[三 tomcat 的功能介绍](#三 tomcat 的功能介绍)
[3.1 安装 Tomcat](#3.1 安装 Tomcat)
[1. 安装 java 环境](#1. 安装 java 环境)
[代码逐行解析(Line-by-Line Breakdown)](#代码逐行解析(Line-by-Line Breakdown))
[企业级生产应用(Enterprise Scenario)](#企业级生产应用(Enterprise Scenario))
[2. 安装并启动 tomcat](#2. 安装并启动 tomcat)
[代码逐行解析(Line-by-Line Breakdown)](#代码逐行解析(Line-by-Line Breakdown))
[3. 查看端口](#3. 查看端口)
[4. 访问 tomcat](#4. 访问 tomcat)
[3.2 tomcat 的文件结构和组成](#3.2 tomcat 的文件结构和组成)
[3.3 生成 tomcat 的启动文件](#3.3 生成 tomcat 的启动文件)
[1. 生成 tomcat 的主配置文件](#1. 生成 tomcat 的主配置文件)
[2. 生成启动文件](#2. 生成启动文件)
[代码逐行解析(Line-by-Line Breakdown)](#代码逐行解析(Line-by-Line Breakdown))
[企业级生产应用(Enterprise Scenario)](#企业级生产应用(Enterprise Scenario))
[3. 生成 tomcat 用户并设定软件安装目录权限](#3. 生成 tomcat 用户并设定软件安装目录权限)
[4. 用启动脚本开启服务](#4. 用启动脚本开启服务)
一 WEB 技术
1.1 HTTP 协议和 B/S 结构
操作系统有进程子系统,使用多进程就可以充分利用硬件资源。进程中可以多个线程,每一个线程可以被 CPU 调度执行,这样就可以让程序并行的执行。这样一台主机就可以作为一个服务器为多个客户端提供计算服务。
客户端和服务端往往处在不同的物理主机上,它们分属不同的进程,这些进程间需要通信。跨主机的进程间通信需要使用网络编程。最常见的网络编程接口是 Socket。
Socket 称为套接字,本意是插座。也就是说网络通讯需要两端,如果一端被动的接收另一端请求并提供计算和数据的称为服务器端,另一端往往只是发起计算或数据请求,称为客户端。
这种编程模式称为 Client/Server 编程模式,简称 C/S 编程。开发的程序也称为 C/S 程序。C/S 编程往往使用传输层协 (TCP/UDP), 较为底层,比如:QQ, 迅雷,云音乐,云盘,foxmail,xshell 等
1990 年 HTTP 协议和浏览器诞生。在应用层使用文本跨网络在不同进程间传输数据,最后在浏览器中将服务器端返回的 HTML 渲染出来。由此,诞生了网页开发。
网页是存储在 WEB 服务器端的文本文件,浏览器发起 HTTP 请求后,到达 WEB 服务程序后,服务程序根据 URL 读取对应的 HTML 文件,并封装成 HTTP 响应报文返回给浏览器端。
起初网页开发主要指的是 HTML、CSS 等文件制作,目的就是显示文字或图片,通过超级链接跳转到另一个 HTML 并显示其内容。
后来,网景公司意识到让网页动起来很重要,傍着 SUN 的 Java 的名气发布了 JavaScript 语言,可以在浏览器中使用 JS 引擎执行的脚本语言,可以让网页元素动态变化,网页动起来了。
为了让网页动起来,微软使用 ActiveX 技术、SUN 的 Applet 都可以在浏览器中执行代码,但都有安全性问题。能不能直接把内容直接在 WEB 服务器端组织成 HTML, 然后把 HTML 返回给浏览器渲染呢?
最早出现了 CGI (Common Gateway Interface) 通用网关接口,通过浏览器中输入 URL 直接映射到一个服务器端的脚本程序执行,这个脚本可以查询数据库并返回结果给浏览器端。这种将用户请求使用程序动态生成的技术,称为动态网页技术。先后出现了 ASP、PHP、JSP 等技术,这些技术的使用不同语言编写的程序都运行在服务器端,所以称为 WEB 后端编程。有一部分程序员还是要编写 HTML、CSS、JavaScript, 这些代码运行在浏览器端,称为 WEB 前端编程。合起来称为 Browser/Server 编程,即 B/S 编程。
板块核心解释
- 进程与线程的本质:进程是操作系统分配资源的最小单位,线程是 CPU 调度的最小单位。多进程利用多核 CPU 的并行计算能力,多线程降低进程切换的开销,两者结合让单台服务器同时处理数千个客户端请求成为可能。
- Socket 类比:就像电话系统,Socket 是两端的 "电话线接口",服务器端 Socket 是 "总机",监听来电;客户端 Socket 是 "分机",主动拨号建立连接,数据通过这条 "虚拟电话线" 传输。
- C/S vs B/S 核心差异:C/S 需要客户端安装专用程序,直接使用传输层协议,性能高但升级麻烦;B/S 只需浏览器,基于 HTTP 应用层协议,跨平台、零安装,是当前互联网的主流架构。
- 动态网页技术演进:CGI 是第一代动态技术,每个请求都会 fork 一个新进程,性能极差;ASP/PHP/JSP 将脚本嵌入 HTML,由服务器解析执行,大幅提升了性能,催生了现代 WEB 后端开发。
1.2 前端三大核心技术
1.2.1 HTML
HTML (HyperText Markup Language) 超文本标记语言,它不同于一般的编程语言。超文本即超出纯文本的范畴,例如:描述文本颜色、大小、字体等信息,或使用图片、音频、视频等非文本内容。
HTML 由一个个的标签 (标记) 组成,这些标签各司其职,有的提供网页信息,有的负责文字,有的负责图片,有的负责网页布局,所以一个 HTML 文件,是由格式标签和数据组成。
html
预览
bash
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<h1>老李老李出门见喜</h1>
</body>
</html>
超文本需要显示,就得有软件能够呈现超文本定义的排版格式,例如显示:图片、表格,显示字体的大小、颜色,这个软件就是浏览器。
超文本的诞生是为了解决纯文本不能格式显示的问题,是为了好看,但是只有通过网络才能分享超文本的内容,所以制定了 HTTP 协议。
代码逐行解析(Line-by-Line Breakdown)
表格
| 代码行 | 底层触发动作 | 作用 |
|---|---|---|
<!DOCTYPE html> |
触发浏览器的标准渲染模式(Standards Mode),而非怪异模式(Quirks Mode) | 告诉浏览器当前文档使用 HTML5 规范解析,避免浏览器用旧的不兼容规则渲染页面 |
<html lang="en"> |
浏览器将页面语言标记为英语,搜索引擎抓取时会识别语言属性,屏幕阅读器会切换对应语音引擎 | 提升 SEO 效果和无障碍访问体验 |
<head> |
浏览器开始解析页面元数据,这部分内容不会显示在页面主体中 | 存放页面配置、字符编码、标题、外部资源引用等 |
<meta charset="UTF-8"> |
浏览器将文档的字符编码设置为 UTF-8,后续所有文本内容都会按照 UTF-8 解码 | 解决中文乱码问题,是 HTML 页面必须的配置 |
<title>首页</title> |
浏览器将标签页标题设置为 "首页",同时搜索引擎会将其作为页面核心标题收录 | 提升用户体验和 SEO 排名 |
</head> |
元数据解析结束,开始解析页面主体内容 | - |
<body> |
浏览器开始渲染页面可见内容 | 所有页面显示的元素都必须放在 body 标签内 |
<h1>老李老李出门见喜</h1> |
浏览器将文本渲染为一级标题样式,同时搜索引擎会将其视为页面最重要的内容 | 定义页面主标题,兼顾样式和语义化 |
</body></html> |
文档解析结束 | 标记 HTML 文档的结束 |
坑点(Gotchas)
- 字符编码错误 :将
UTF-8写成gbk或utf8(无横杠),会导致所有中文显示为乱码,且难以排查。 - 缺失 DOCTYPE 声明:浏览器会自动进入怪异模式,页面布局在不同浏览器中出现严重偏移,CSS 样式失效。
- 标签不闭合 :如
<meta>不写闭合斜杠(HTML5 允许,但 XHTML 不允许),会导致旧浏览器解析出错。
企业级生产应用(Enterprise Scenario)
- 千万级并发场景:所有静态 HTML 页面都会被 CDN 缓存,用户请求直接命中 CDN 节点,无需回源到 Tomcat 服务器,减轻 90% 以上的静态资源压力。
- 进阶优化 :
- 压缩 HTML 代码,删除空格、注释和换行,减少文件体积。
- 使用语义化标签(
<header>、<nav>、<main>)替代通用<div>,提升 SEO 和可维护性。 - 配置 HTTP 缓存头(
Cache-Control),让浏览器长期缓存静态 HTML 页面。
课后防宕机指南(Troubleshooting)
- 错误现象 :页面中文全部显示为问号或乱码
- 排查思路:检查
<meta charset="UTF-8">是否存在且拼写正确;检查服务器返回的 HTTP 响应头中的Content-Type是否包含charset=UTF-8;检查 HTML 文件本身的编码是否为 UTF-8(无 BOM)。
- 排查思路:检查
- 错误现象 :页面在 Chrome 中正常,在 IE 中布局混乱
- 排查思路:检查是否缺失
<!DOCTYPE html>声明;检查 CSS 是否使用了 IE 不支持的属性;使用开发者工具查看浏览器的渲染模式。
- 排查思路:检查是否缺失
生活类比
HTML 就像一本书的骨架和内容,标签是章节标题、段落、图片的标记,浏览器是读者,按照标记的顺序和格式阅读这本书。没有 HTML,就只有一堆零散的文字和图片,无法组织成可读的内容。
1.2.2 CSS (Cascading Style Sheets) 层叠样式表
HTML 本身为了格式化显示文本,但是当网页呈现大家面前的时候,需求 HTML 提供更多样式能力。这使得 HTML 变得越来越臃肿。这促使了 CSS 的诞生。
1994 年,W3C 成立,CSS 设计小组所有成员加入 W3C, 并努力研发 CSS 的标准,微软最终加入。
1996 年 12 月发布 CSS 1.0。
1998 年 5 月发布 CSS 2.0
CSS 3 采用了模块化思想,每个模块都在 CSS 2 基础上分别增强功能。所以,这些模块是陆续发布的。
不同厂家的浏览器使用的引擎,对 CSS 的支持不一样,导致网页布局、样式在不同浏览器不一样。因此,想要保证不同用户使用不同浏览器看到的网页效果一直非常困难。
板块核心解释
- CSS 诞生的本质 :实现结构与样式分离。HTML 只负责页面结构和内容,CSS 负责所有样式(颜色、字体、布局、动画),让代码更易维护、复用性更高。
- CSS3 模块化:将 CSS 拆分为选择器、盒模型、Flex 布局、Grid 布局、动画等独立模块,每个模块可以单独升级,避免了 CSS2 整体更新慢的问题。
- 浏览器兼容性问题 :Chrome 用 Blink 引擎,Firefox 用 Gecko 引擎,旧 IE 用 Trident 引擎,不同引擎对 CSS 属性的实现存在差异,需要加前缀(如
-webkit-、-moz-)兼容。
坑点(Gotchas)
- 样式优先级冲突:行内样式 > ID 选择器 > 类选择器 > 标签选择器,优先级计算错误会导致样式不生效。
- 盒模型差异 :旧 IE 使用怪异盒模型(
box-sizing: border-box),标准浏览器使用内容盒模型(box-sizing: content-box),导致元素宽高计算不一致。
企业级生产应用
- 千万级并发场景:CSS 文件会被压缩、合并,并通过 CDN 分发,同时配置强缓存,用户只需下载一次 CSS 文件,后续访问直接从浏览器缓存读取。
- 进阶优化:使用 CSS 预处理器(Sass/Less)提高开发效率;使用 CSS Modules 解决样式冲突问题;使用 CSS Grid 和 Flex 布局替代传统的 float 布局,提升布局性能。
1.2.3 JavaScript
Javascript 简称 JS, 是一种动态的弱类型脚本解释性语言,和 HTML、CSS 并称三大 WEB 核心技术,得到了几乎主流浏览器支持。
1994 年,网景 Netscape 公司成立并发布了 Netscape Navigator 浏览器,占据了很大的市场份额,网景意识到 WEB 需要动态,需要一种技术来实现。
1995 年 9 月网景浏览器 2 发布测试版本发布了 LiveScript, 随即在 12 月的测试版就更名为 JavaScript。同时期,微软推出 IE 并支持 JScript、VBScript, 与之抗衡。
1997 年,网景、微软、SUN、Borland 公司和其他组织在 ECMA (European Computer Manufacturers Association 欧洲计算机制造商协会) 确定了 ECMAScript 的本程序设计语言的标准。JavaScript 和 JScript 都成为 ECMAScript 标准的实现。
2008 年后随着 chrome 浏览器的 V8 引擎发布。
V8 JS 引擎不是解释执行,而是本地编译,在 V8 引擎做了很多优化,JS 程序在其上运行堪比本地二进制程序。V8 引擎使用 C++ 开发,可以嵌入到任何 C++ 程序中。基于 V8 引擎,2009 年基于服务器 javascript 的运行环境 Node.js 诞生,创建了第一版 npm (Node.js 包管理器和开源库生态系统), 提供了大量的库供程序员使用。从此,便可以在服务器端真正大规模使用 JavaScript 编程了。也就是说 JavaScript 也可以真正称为服务器端编程语言了,成为目前唯一的前,后端通用的语言。
同步
交互式网页,用户提交了请求,就是想看到查询的结果。服务器响应到来后是一个全新的页面内容,哪怕 URL 不变,整个网页都需要重新渲染。例如,用户填写注册信息,只是 2 次密码不一致,提交后,整个注册页面重新刷新,所有填写项目重新填写 (当然有办法让用户减少重填)。这种交互非常不友好。从代价的角度看,就是为了注册的一点点信息,结果返回了整个网页内容,不但浪费了网络带宽,还需要浏览器重新渲染网页,太浪费资源了,影响了用户体验和感受。上面这些请求的过程,就是同步过程,用户发起请求,页面整个刷新,直到服务器端响应的数据到来并重新渲染。
异步
1996 年微软实现了 iframe 标签,可以在一个网页使用 iframe 标签局部异步加载内容。
1999 年微软推出异步数据传输的 ActiveX 插件技术,太笨重了,但是也火了很多年。有一个组件 XMLHttpRequest 被大多数浏览器支持。
传统的网页如果需要更新内容,必需重载整个网页面。Ajax 的出现,改变这一切,同时极大的促进了 Javascript 的发展。Ajax 即 "Asynchronous Javascript And XML"(异步 JavaScript 和 XML), 是指一种创建交互式、快速动态网页应用的网页开发技术,最早起源于 1998 年微软的 Outlook Web Access 开发团队。Ajax 通过在后台与服务器进行少量数据交换,可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。Javascript 通过调用浏览器内置的 WEB API 中的 XMLHttpRequest 对象实现 Ajax 技术。早期 Ajax 结合数据格式 XML, 目前更多的使用 JSON。利用 AJAX 可实现前后端开发的彻底分离,改变了传统的开发模式。
AJAX 是一种技术的组合,技术的重新发现,而不是发明,但是它深远的影响了整个 WEB 开发。
板块核心解释
- V8 引擎的革命性:将 JS 代码直接编译为本地机器码,而非逐行解释执行,同时引入了即时编译(JIT)和垃圾回收优化,让 JS 的性能提升了 10 倍以上,为 Node.js 的诞生奠定了基础。
- 同步 vs 异步:同步请求就像你去餐厅吃饭,点完菜必须站在柜台等,直到菜做好才能走;异步请求就像扫码点餐,点完菜可以找座位坐下,菜做好了服务员会喊你,你可以同时做其他事情。
- AJAX 的本质:浏览器提供的一个异步 HTTP 客户端,让 JS 可以在后台发送 HTTP 请求,接收服务器返回的数据,然后动态修改页面 DOM,实现局部刷新。
- 前后端分离:前端只负责页面渲染和用户交互,后端只负责提供数据接口(JSON 格式),两者通过 HTTP 协议通信,实现了开发团队的解耦和并行开发。
坑点(Gotchas)
- 跨域问题:由于浏览器的同源策略,AJAX 请求只能发送到当前页面所在的域名,否则会被浏览器拦截,这是前端开发最常见的问题之一。
- 异步回调地狱:多个异步请求嵌套调用,会导致代码层级过深,难以维护和调试。
企业级生产应用
- 千万级并发场景:所有 AJAX 接口都会通过 Nginx 反向代理,实现接口的负载均衡和缓存;同时使用 WebSocket 替代轮询,实现实时通信,降低服务器压力。
- 进阶优化:使用 Promise 和 async/await 解决回调地狱问题;使用 Axios 封装 AJAX 请求,统一处理错误和拦截;使用 CDN 缓存静态 JS 文件,提升加载速度。
二 WEB 框架
2.1 web 资源和访问

图片服务器 静态WEB服务器
WEB
WEB BROWSER WEB服务器
JS
DEVICE AP
业务服务器 数据库服务器
图片备注:从上到下依次为:客户端(PC 浏览器 / 手机 APP)→ 静态 WEB 服务器 / 图片服务器 → 业务服务器 → 数据库服务器
从静态服务器请求 HTML、CSS、JS 等文件发送到浏览器端,浏览器端接收后渲染在浏览器上从图片服务器请求图片资源显示 从业务服务器访问动态内容,动态内容是请求后有后台服务访问数据库后得到的,最终返回到浏览器端
手机 App 访问
内置了 HTML 和 JS 文件,不需要从静态 WEB 服务器下载 JS 或 HTML。为的就是减少文件的发送,现代前端开发使用的 JS 文件太多或太大了 有必要就从图片服务器请求图片,从业务服务器请求动态数据
客户需求多样,更多的内容还是需要由业务服务器提供,业务服务器往往都是由一组服务器组成。
板块核心解释
- WEB 资源分层:将静态资源(HTML/CSS/JS/ 图片)和动态资源(接口数据)分离,由不同的服务器负责,充分发挥不同服务器的优势:静态服务器(Nginx)擅长处理高并发的静态文件请求,业务服务器(Tomcat)擅长处理复杂的业务逻辑。
- APP 访问优化:将静态资源内置到 APP 中,减少网络请求,提升 APP 的启动速度和用户体验;动态数据通过 API 接口从业务服务器获取,保证数据的实时性。
- 业务服务器集群:单台业务服务器的并发能力有限,通过集群部署和负载均衡,将请求分发到多台服务器,提升系统的整体并发能力和可用性。
企业级生产应用
- 千万级并发场景:静态资源全部托管到 CDN,图片服务器使用对象存储(如阿里云 OSS、腾讯云 COS),业务服务器部署在 K8s 集群中,实现自动扩缩容。
- 进阶优化:使用 CDN 的边缘计算能力,在 CDN 节点上处理简单的逻辑,进一步减少回源请求;使用缓存(Redis)缓存热点数据,减少数据库访问压力。
2.2 后台应用架构

单体应用 SOA Microservice
2.2.1 单体架构
传统架构 (单机系统), 一个项目一个工程:比如商品、订单、支付、库存、登录、注册等等,统一部署,一个进程 all in one 的架构方式,把所有的功能单元放在一个应用里。然后把整个应用部署到一台服务器上。 如果负载能力不行,将整个应用进行水平复制,进行扩展,然后通过负载均衡实现访问。
Java 实现:JSP、Servlet, 打包成一个 jar、war 部署
易于开发和测试:也十分方便部署;当需要扩展时,只需要将 war 复制多份,然后放到多个服务器上,再做个负载均衡就可以了。
如果某个功能模块出问题,有可能全站不可访问,修改 Bug 后、某模块功能修改或升级后,需要停掉整个服务,重新整体重新打包、部署这个应用 war 包,功能模块相互之间耦合度高,相互影响,不适合当今互联网业务功能的快速迭代。
特别是对于一个大型应用,我们不可能把所有内容都放在一个应用里面,我们如何维护、如何分工合作都是问题。如果项目庞大,管理难度大
web 应用服务器:开源的 tomcat、jetty、glassfish。商用的有 weblogic、websphere、Jboss
板块核心解释
- 单体架构的本质:所有功能模块打包在一个应用中,运行在同一个 JVM 进程中,共享同一个数据库。
- 单体架构的适用场景:小型项目、初创公司、业务简单且迭代慢的系统,开发和维护成本低。
- 单体架构的致命问题:耦合度高,一个模块的 bug 会导致整个系统崩溃;升级困难,必须停机部署;扩展能力有限,只能整体水平扩展,无法针对某个高并发模块单独扩展。
生活类比
单体架构就像一个小餐馆,老板一个人既当厨师又当服务员还当收银员,所有事情都自己做。餐馆小的时候效率很高,但是当顾客越来越多,老板就忙不过来了,而且如果老板生病了,整个餐馆就关门了。
2.2.2 微服务

Microservices common characteristics of this architectural style
- 属于 SOA (Service Oriented Architecture) 的子集
- 微服务化的核心就是将传统的一站式应用,根据业务拆分成一个一个的服务,彻底去掉耦合,每一个微服务提供单个业务功能,一个服务只做一件事。每个服务都围绕着具体业务进行构建,并且能够被独立地部署到生产环境、类生产环境等
- 从技术角度讲就是一种小而独立的处理过程,类似与进程的概念,能够自行单独启动或销毁
- 微服务架构 (分布式系统), 各个模块 / 服务,各自独立出来,"让专业的人干专业的事", 独立部署。分布式系统中,不同的服务可以使用各自独立的数据库。
- 服务之间采用轻量级的通信机制 (通常是基于 HTTP 的 RESTful API)。
- 微服务设计的思想改变了原有的企业研发团队组织架构。传统的研发组织架构是水平架构,前端、后端、DBA、测试分别有自己对应的团队,属于水平团队组织架构。而微服务的设计思想对团队的划分有着一定的影响,使得团队组织架构的划分更倾向于垂直架构,比如用户业务是一个团队来负责,支付业务是一个团队来负责。但实际上在企业中并不会把团队组织架构拆分得这么绝对,垂直架构只是一种理想的架构
- 微服务的实现框架有多种,不同的应用架构,部署方式也有不同
板块核心解释
- 微服务的本质:按业务领域拆分应用,每个服务独立开发、独立部署、独立运行,服务之间通过轻量级协议通信。
- 康威定律:系统设计的架构会复制组织的沟通架构。微服务架构要求团队也是垂直划分的,每个团队负责一个完整的业务服务,从前端到后端到测试,减少跨团队沟通成本。
- SOA vs 微服务:SOA 是面向服务的架构,强调服务的复用和集成,通常使用 ESB 作为服务总线;微服务是 SOA 的轻量化实现,强调服务的独立和自治,使用 HTTP RESTful API 替代 ESB,避免了 ESB 的单点故障和性能瓶颈。
生活类比
微服务架构就像一个大型连锁餐厅,拆分成了后厨(订单服务)、收银台(支付服务)、仓库(库存服务)、前台(用户服务)等多个部门,每个部门只负责自己的事情,有自己的员工和设备。如果收银台坏了,后厨还能继续做饭,不会导致整个餐厅关门;如果顾客太多,可以单独增加收银台的数量,不用扩建整个餐厅。
2.2.3 单体架构和微服务比较

A monolithic application puts all its functionality into a single process...
A microservices architecture puts each element of functionality into a separate service...
... and scales by replicating the monolith on multiple servers
... and scales by distributing these services across servers, replicating as needed.
图片备注:单体架构 vs 微服务架构对比图,左侧为单体架构:一个进程包含所有功能,连接一个数据库,多台服务器复制整个单体;右侧为微服务架构:多个独立的服务进程,每个服务连接自己的数据库,服务可以单独复制扩展
monolith -single database
microservices - application databases
微服务的优点
- 每个服务足够内聚,足够小,代码容易理解。这样能聚焦一个适当的业务功能或业务需求。
- 开发简单、开发效率提高,一个服务可能就是专业的只干一件事,微服务能够被小团队单独开发,这个小团队可以是 2 到 5 人的开发人员组成
- 微服务是松耦合的,是有功能意义的服务,无论是在开发阶段或部署阶段都是独立的。
- 微服务能使用不同的语言开发
- 易于和第三方集成,微服务运行容易且灵活的方式集成自动部署,通过持续集成工具,如: Jenkins、Hudson、Bamboo
- 微服务易于被一个开发人员理解、修改和维护,这样小团队能够更关注自己的工作成果,无需通过合作才能体现价值
- 微服务允许你利用融合最新技术。微服务只是业务逻辑的代码,不会和 HTML/CSS 或其他界面组件混合,即前后端分离
- 每个微服务都有自己的存储能力,可以有自己的数据库,也可以有统一数据库
微服务缺点:
- 微服务把原有的一个项目拆分成多个独立工程,增加了开发、测试、运维、监控等的复杂度
- 微服务架构需要保证不同服务之间的数据一致性,引入了分布式事务和异步补偿机制,为设计和开发带来一定挑战
- 开发人员和运维需要处理分布式系统的复杂性,需要更强的技术能力
- 微服务适用于复杂的大系统,对于小型应用使用微服务,进行盲目的拆分只会增加其维护和开发成本
常见的微服务框架
Dubbo
- 阿里开源贡献给了 ASF, 目前已经是 Apache 的顶级项目
- 一款高性能的 Java RPC 服务框架,微服务生态体系中的一个重要组件
- 将单体程序分解成多个功能服务模块,模块间使用 Dubbo 框架提供的高性能 RPC 通信
- 内部协调使用 Zookeeper, 实现服务注册、服务发现和服务治理
Spring cloud
- 一个完整的微服务解决方案,相当于 Dubbo 的超集
- 微服务框架,将单体应用拆分为粒度更小的单一功能服务
- 基于 HTTP 协议的 REST (Representational State Transfer 表述性状态转移) 风格实现模块间通信
板块核心解释
- Dubbo vs Spring Cloud:Dubbo 是高性能的 RPC 框架,专注于服务之间的通信,性能高但生态不完整;Spring Cloud 是完整的微服务生态,包含服务注册发现、配置中心、熔断降级、网关、链路追踪等组件,功能全面但性能略低于 Dubbo。
- 微服务的适用场景:大型复杂系统、业务迭代快、团队规模大的互联网公司,如电商、金融、社交等领域。
- 分布式事务:微服务架构下,一个业务操作可能涉及多个服务和多个数据库,无法使用传统的本地事务保证数据一致性,需要使用最终一致性方案(如 Seata、Saga)。
企业级生产应用
- 千万级并发场景:使用 Spring Cloud Alibaba 作为微服务框架,Nacos 作为服务注册发现和配置中心,Sentinel 作为熔断降级组件,Gateway 作为 API 网关,SkyWalking 作为链路追踪工具。
- 进阶优化:使用 gRPC 替代 HTTP RESTful API,提升服务间通信性能;使用服务网格(Istio)实现服务治理的下沉,让业务代码更专注于业务逻辑。
三 tomcat 的功能介绍

Apache Tomcat Tomcat 服务器是一个免费的开放源代码的 Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,Tomcat 具有处理 HTML 页面的功能,它还是一个 Servlet 和 JSP 容器
起始于 SUN 公司的一个 Servlet 的参考实现项目 Java Web Server, 开发者是 James Duncan Davidson, 在 1999 年,将项目贡献给了 apache 软件基金会 (ASF), 和 ASF 现有的项目 JServ 合并,并开源成为顶级项目
Tomcat 仅仅实现了 Java EE 规范中与 Servlet、JSP 相关的类库,是 JavaEE 不完整实现。
1999 年发布初始版本是 Tomcat 3.0, 实现了 Servlet 2.2 和 JSP 1.1 规范。
Tomcat 4.x 发布时,内建了 Catalina (Servlet 容器) 和 Jasper (JSP engine) 等
当前 Tomcat 的正式版本已经更新到 9.0.x 版本,但当前企业中主流版本为 8.x 和 7.x
官网文档: https://tomcat.apache.org/tomcat-8.5-doc/index.html
帮助文档:
https://cwiki.apache.org/confluence/display/tomcat/ https://cwiki.apache.org/confluence/display/tomcat/FAQ
板块核心解释
- Tomcat 的本质:一个 Servlet/JSP 容器,负责接收客户端的 HTTP 请求,将请求转发给对应的 Servlet 处理,并将 Servlet 生成的响应返回给客户端。
- Java EE 规范:Java EE 是一套企业级 Java 开发的规范,包含 Servlet、JSP、EJB、JMS 等多个子规范。Tomcat 只实现了 Servlet 和 JSP 规范,因此被称为轻量级应用服务器;而 WebLogic、WebSphere 实现了完整的 Java EE 规范,被称为重量级应用服务器。
- 核心组件:Catalina 是 Servlet 容器,负责处理 Servlet 的生命周期;Jasper 是 JSP 引擎,负责将 JSP 文件编译成 Servlet。
3.1 安装 Tomcat


推荐从 Apache 官网下载源码包直接安装启动
1. 安装 java 环境
bash
#安装java环境
[root@tomcat ~]# yum install java-1.8.0-openjdk.x86_64 -y
#查看java版本
[root@tomcatA ~]# java -version
openjdk version "1.8.0_402"
OpenJDK Runtime Environment (build 1.8.0_402-b06)
OpenJDK 64-Bit Server VM (build 25.402-b06, mixed mode)
#查看java的环境目录
[root@tomcatA ~]# which java
/usr/bin/java
[root@tomcatA ~]# ll /usr/bin/java
lrwxrwxrwx 1 root root 22 Jul 30 10:41 /usr/bin/java -> /etc/alternatives/java
#java的运行环境
[root@tomcatA ~]# cd /etc/alternatives/jre
[root@tomcatA jre]# ls
ASSEMBLY_EXCEPTION bin lib LICENSE THIRD_PARTY_README
代码逐行解析(Line-by-Line Breakdown)
| 代码行 | 底层触发动作 | 作用 |
|---|---|---|
yum install java-1.8.0-openjdk.x86_64 -y |
yum 从/etc/yum.repos.d/配置的仓库中下载指定版本的 OpenJDK RPM 包,自动解决依赖关系,安装到系统默认路径;-y自动确认所有交互提示,无需人工输入 |
安装 Tomcat 运行所需的 Java 环境,Tomcat 是纯 Java 程序,必须依赖 JVM 才能运行 |
java -version |
调用/usr/bin/java可执行文件,加载 JVM 虚拟机,输出 JDK 的版本信息 |
验证 Java 环境是否安装成功,确认版本是否符合 Tomcat 的要求(Tomcat 9 需要 Java 8+) |
which java |
在系统的 PATH 环境变量中查找java可执行文件的绝对路径 |
确认 Java 命令的位置,方便后续配置 JAVA_HOME 环境变量 |
ll /usr/bin/java |
查看/usr/bin/java文件的详细信息,发现它是一个软链接,指向/etc/alternatives/java |
CentOS 使用 alternatives 工具管理多个 Java 版本,/etc/alternatives/java是当前系统默认的 Java 版本 |
cd /etc/alternatives/jre |
切换到 JRE 的实际安装目录 | 查看 JRE 的目录结构,确认 JRE 安装完整 |
ls |
列出 JRE 目录下的文件和子目录 | 验证 JRE 包含 bin(可执行文件)、lib(类库)等核心目录 |
坑点(Gotchas)
- Java 版本不兼容:Tomcat 9 需要 Java 8 及以上版本,Tomcat 10 需要 Java 11 及以上版本,安装错误的 Java 版本会导致 Tomcat 启动失败。
- 使用 JRE 而非 JDK :虽然 Tomcat 可以运行在 JRE 上,但 JSP 编译需要 JDK 的
javac编译器,只安装 JRE 会导致 JSP 页面无法访问。 - yum 自动升级 Java:使用 yum 安装的 Java 会随系统更新自动升级,可能导致版本变化,影响 Tomcat 的稳定性。
企业级生产应用(Enterprise Scenario)
- 千万级并发场景 :生产环境不会使用 yum 安装 OpenJDK,而是手动安装 Oracle JDK 或 Amazon Corretto,解压到
/usr/local/jdk目录,手动配置 JAVA_HOME 环境变量,避免 yum 自动升级。 - 进阶优化 :
- 配置 JVM 参数(堆内存、新生代大小、垃圾回收器),根据服务器配置调整,提升 Tomcat 的性能。
- 使用 JDK 的 jstat、jmap、jstack 等工具监控 JVM 的运行状态,及时发现内存泄漏和性能问题。
- 开启 JVM 的 GC 日志,方便排查垃圾回收导致的卡顿问题。
课后防宕机指南(Troubleshooting)
- 错误现象 :执行
java -version提示command not found- 排查思路:检查 Java 是否安装成功;检查 PATH 环境变量是否包含 Java 的 bin 目录;检查
/usr/bin/java软链接是否存在且指向正确的路径。
- 排查思路:检查 Java 是否安装成功;检查 PATH 环境变量是否包含 Java 的 bin 目录;检查
- 错误现象 :Tomcat 启动失败,日志提示
Unsupported major.minor version 52.0- 排查思路:这是 Java 版本不兼容的错误,52.0 对应 Java 8,说明 Tomcat 是用 Java 8 编译的,而当前系统的 Java 版本低于 8,升级 Java 版本即可解决。
生活类比
安装 Java 环境就像给你的汽车(Tomcat)加汽油(JVM),没有汽油,汽车根本无法启动。不同型号的汽车需要不同标号的汽油,不同版本的 Tomcat 也需要对应版本的 Java。
2. 安装并启动 tomcat
bash
#解压并生成tomcat的程序目录
[root@tomcatA ~]# tar zxf apache-tomcat-9.0.107.tar.gz -C /usr/local/
[root@tomcatA ~]# cd /usr/local/
[root@tomcatA local]# ls
apache-tomcat-9.0.107 bin etc games include lib lib64 libexec sbin share src
[root@tomcatA local]# mv apache-tomcat-9.0.107/ tomcat
[root@tomcatA local]# ls
bin etc games include lib lib64 libexec sbin share src tomcat
#启动tomcat
[root@tomcatA local]# cd tomcat/
[root@tomcatA tomcat]# cd bin/
[root@tomcatA bin]# ls
bootstrap.jar commons-daemon-native.tar.gz makebase.sh tomcat-juli.jar
catalina.bat configtest.bat setclasspath.bat tomcat-native.tar.gz
catalina.sh configtest.sh setclasspath.sh tool-wrapper.bat
catalina-tasks.xml daemon.sh shutdown.bat tool-wrapper.sh
ciphers.bat digest.bat shutdown.sh version.bat
ciphers.sh digest.sh startup.bat version.sh
commons-daemon.jar makebase.bat startup.sh
[root@tomcatA bin]# ./startup.sh
Using CATALINA_BASE: /usr/local/tomcat
Using CATALINA_HOME: /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME: /usr
Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Using CATALINA_OPTS:
Tomcat started.
代码逐行解析(Line-by-Line Breakdown)
表格
| 代码行 | 底层触发动作 | 作用 |
|---|---|---|
tar zxf apache-tomcat-9.0.107.tar.gz -C /usr/local/ |
tar命令读取 gzip 压缩的 tar 包,解压所有文件到/usr/local/目录;z表示 gzip 压缩,x表示解压,f表示指定文件,-C表示指定解压目录 |
将 Tomcat 程序解压到系统的/usr/local目录,这是 Linux 系统中存放第三方软件的标准目录 |
mv apache-tomcat-9.0.107/ tomcat |
将解压后的目录重命名为tomcat |
去掉版本号,方便后续管理和配置,避免升级时修改所有配置文件中的路径 |
cd bin/ |
切换到 Tomcat 的 bin 目录 | bin 目录存放 Tomcat 的启动、停止等核心脚本 |
ls |
列出 bin 目录下的所有文件 | 查看 Tomcat 的核心脚本,如startup.sh(启动)、shutdown.sh(停止)、catalina.sh(核心控制脚本) |
./startup.sh |
执行startup.sh脚本,该脚本会调用catalina.sh start;catalina.sh会设置 CATALINA_BASE、CATALINA_HOME、JRE_HOME 等环境变量,然后启动 JVM 进程,加载 Tomcat 的核心类(bootstrap.jar),初始化 Catalina 容器,监听 8080 端口 |
启动 Tomcat 服务器,开始接收客户端的 HTTP 请求 |
坑点(Gotchas)
- 端口被占用:Tomcat 默认监听 8080 端口,如果该端口被其他进程(如 Nginx、其他 Tomcat 实例)占用,Tomcat 会启动失败。
- 防火墙未开放端口:CentOS 默认开启 firewalld 防火墙,未开放 8080 端口会导致外部无法访问 Tomcat。
- 使用 root 用户启动 Tomcat:root 用户拥有系统最高权限,如果 Tomcat 被黑客攻击,黑客会获得整个服务器的控制权,存在严重的安全隐患。
企业级生产应用
- 千万级并发场景:生产环境会修改 Tomcat 的默认端口(8080 改为其他端口),避免被黑客扫描;使用普通用户启动 Tomcat,提升安全性;配置 Tomcat 的连接器参数(最大连接数、线程数),提升并发处理能力。
- 进阶优化 :
- 开启 APR(Apache Portable Runtime)模式,使用本地库处理网络请求,大幅提升 Tomcat 的性能。
- 配置 Tomcat 的访问日志,记录所有 HTTP 请求的详细信息,方便排查问题和分析访问量。
- 禁用 Tomcat 的默认应用(ROOT、docs、examples),删除不必要的管理页面,提升安全性。
课后防宕机指南(Troubleshooting)
- 错误现象 :执行
./startup.sh提示 Tomcat started,但访问 8080 端口连接被拒绝- 排查思路:执行
netstat -antlupe | grep java查看 Tomcat 是否监听 8080 端口;检查防火墙是否开放 8080 端口(firewall-cmd --list-ports);检查 SELinux 是否阻止 Tomcat 绑定端口(setenforce 0临时关闭 SELinux 测试)。
- 排查思路:执行
- 错误现象 :Tomcat 启动后 CPU 使用率 100%
- 排查思路:使用
top命令查看 Java 进程的 CPU 使用率;使用jstack命令生成线程栈,查看是否有死循环或死锁;检查是否有内存泄漏,导致频繁的 Full GC。
- 排查思路:使用
3. 查看端口
bash
[root@tomcat ~]# netstat -antlupe | grep java
tcp6 0 0 :::8080 :::* LISTEN 0 68636 32887/java
代码逐行解析
netstat -antlupe:列出所有 TCP 和 UDP 连接,显示进程 ID 和进程名,以及用户和端口信息。-a:显示所有连接和监听端口-n:以数字形式显示 IP 地址和端口号,不进行域名解析-t:只显示 TCP 连接-l:只显示监听状态的端口-u:只显示 UDP 连接-p:显示进程 ID 和进程名-e:显示扩展信息,如用户和 inode 号
grep java:过滤出包含 java 的行,即 Java 进程监听的端口。- 输出结果说明:
tcp6 0 0 :::8080 :::* LISTEN 0 68636 32887/java表示 Java 进程(PID 32887)正在监听 IPv6 的 8080 端口,等待客户端连接。
坑点(Gotchas)
- netstat 命令未安装 :CentOS 7 及以上版本默认不安装 netstat,需要执行
yum install net-tools -y安装。 - 只监听 IPv6 端口:Tomcat 默认同时监听 IPv4 和 IPv6 的 8080 端口,但有些系统会优先使用 IPv6,导致 IPv4 的客户端无法访问。
4. 访问 tomcat

Tomcat 默认欢迎页面截图,显示上述内容
板块核心解释
- 访问 Tomcat 默认的 8080 端口,看到这个欢迎页面,说明 Tomcat 已经成功安装并启动。
- 这个欢迎页面是 Tomcat 自带的 ROOT 应用,位于
webapps/ROOT目录下。
3.2 tomcat 的文件结构和组成
目录结构
表格
| 目录 | 说明 |
|---|---|
| bin | 服务启动、停止等相关程序和文件 |
| lib | 库目录 |
| conf | 配置文件 |
| logs | 日志目录 |
| webapps | 应用程序,应用部署目录,相当于 nginx 的默认发布目录 |
| work | jsp 编译后的结果文件,建议提前预热访问 |
查看 tomcat 相关目录和文件
bash
[root@tomcat ~]# ls /usr/local/tomcat/
bin conf lib logs README.md RUNNING.txt temp webapps work
BUILDING.txt CONTRIBUTING.md LICENSE NOTICE RELEASE-NOTES
目录详细解释
- bin 目录 :存放 Tomcat 的所有可执行脚本,核心是
catalina.sh(Linux)和catalina.bat(Windows),所有启动、停止、重启等操作都是通过调用这个脚本实现的。 - lib 目录:存放 Tomcat 运行所需的所有 Java 类库(jar 包),包括 Servlet API、JSP API、Tomcat 核心类库等。所有部署在 Tomcat 上的 web 应用都会共享这个目录下的 jar 包。
- conf 目录 :存放 Tomcat 的全局配置文件,核心配置文件包括:
server.xml:Tomcat 的主配置文件,配置连接器、引擎、主机等核心组件。context.xml:全局的上下文配置文件,所有部署的 web 应用都会继承这个配置。web.xml:全局的 web 应用配置文件,定义了默认的 Servlet、过滤器、错误页面等。tomcat-users.xml:配置 Tomcat 的用户和角色,用于管理控制台的身份认证。
- logs 目录 :存放 Tomcat 的所有日志文件,重要的日志文件包括:
catalina.out:Tomcat 的标准输出和错误日志,所有 System.out.println () 的输出和异常堆栈信息都会打印到这个文件。localhost_access_log.*.txt:Tomcat 的访问日志,记录所有 HTTP 请求的详细信息,包括客户端 IP、请求时间、请求 URL、响应状态码、响应时间等。localhost.*.log:localhost主机的日志,记录 web 应用的初始化和销毁信息。
- webapps 目录:Tomcat 的默认应用部署目录,将 war 包放在这个目录下,Tomcat 会自动解压并部署应用。默认包含 ROOT(根应用)、docs(文档)、examples(示例)、manager(管理应用)、host-manager(主机管理应用)五个应用。
- work 目录:存放 JSP 编译生成的 Servlet 字节码文件。Tomcat 会将每个 JSP 文件编译成一个 Java 类,然后编译成字节码文件,存放在 work 目录下。第一次访问 JSP 时会比较慢,因为需要编译,提前预热访问可以让 Tomcat 预编译所有 JSP,提升用户体验。
- temp 目录:存放 Tomcat 运行时产生的临时文件,如文件上传的临时文件等。
坑点(Gotchas)
- 修改 lib 目录下的 jar 包:随意修改或删除 lib 目录下的 jar 包会导致 Tomcat 启动失败或运行异常。
- catalina.out 文件过大:Tomcat 默认不会轮转 catalina.out 文件,长时间运行会导致文件过大,占满磁盘空间,甚至导致系统崩溃。
- work 目录权限不足:如果 Tomcat 用户没有 work 目录的写权限,JSP 无法编译,会导致 JSP 页面访问失败。
企业级生产应用
- 千万级并发场景:将 webapps 目录移到单独的磁盘分区,避免系统盘被占满;配置 logrotate 实现 catalina.out 和访问日志的自动轮转和归档;将 work 目录挂载到 tmpfs(内存文件系统),提升 JSP 编译和访问速度。
- 进阶优化:禁用 webapps 下的默认应用(ROOT、docs、examples、manager、host-manager),删除不必要的文件,提升安全性;配置 Tomcat 的虚拟主机,在同一个 Tomcat 实例上部署多个 web 应用。
3.3 生成 tomcat 的启动文件
1. 生成 tomcat 的主配置文件
bash
[root@tomcat ~]# vim /usr/local/tomcat/conf/tomcat.conf
JAVA_HOME=/etc/alternatives/jre
代码逐行解析
JAVA_HOME=/etc/alternatives/jre:设置 Tomcat 启动时使用的 JRE 路径。Tomcat 启动脚本会读取这个环境变量,从这个路径加载 JVM 虚拟机。- 底层动作:当 Tomcat 启动时,
catalina.sh脚本会读取tomcat.conf文件中的环境变量,将JAVA_HOME设置为指定的路径,然后使用$JAVA_HOME/bin/java命令启动 JVM 进程。
坑点(Gotchas)
- JAVA_HOME 路径写错 :必须指向 JRE 或 JDK 的根目录,不能指向 bin 目录,否则 Tomcat 会提示
JAVA_HOME is not defined correctly。 - JRE 和 JDK 混淆:如果需要编译 JSP,必须将 JAVA_HOME 指向 JDK 的根目录,而不是 JRE。
2. 生成启动文件
bash
[root@tomcat ~]# vim /lib/systemd/system/tomcat.service
[Unit]
Description=Tomcat
After=syslog.target network.target
[Service]
Type=forking
EnvironmentFile=/usr/local/tomcat/conf/tomcat.conf
ExecStart=/usr/local/tomcat/bin/startup.sh
ExecStop=/usr/local/tomcat/bin/shutdown.sh
PrivateTmp=true
User=tomcat
Group=tomcat
[Install]
WantedBy=multi-user.target
代码逐行解析(Line-by-Line Breakdown)
| 代码行 | 底层触发动作 | 作用 |
|---|---|---|
[Unit] |
systemd 开始解析单元的基本信息 | 定义服务的描述和依赖关系 |
Description=Tomcat |
设置服务的描述信息,在执行systemctl status tomcat时会显示 |
方便管理员识别服务 |
After=syslog.target network.target |
告诉 systemd,Tomcat 服务必须在 syslog 服务和网络服务启动之后再启动 | 确保 Tomcat 启动时系统日志和网络已经可用,避免 Tomcat 无法绑定端口或无法写入日志 |
[Service] |
systemd 开始解析服务的执行参数 | 定义服务的启动、停止、运行用户等参数 |
Type=forking |
告诉 systemd,Tomcat 服务是一个后台守护进程,启动脚本会 fork 一个子进程,然后父进程退出,子进程作为服务的主进程运行 | systemd 会跟踪 fork 后的子进程,监控服务的运行状态 |
EnvironmentFile=/usr/local/tomcat/conf/tomcat.conf |
告诉 systemd,从指定的文件中读取环境变量 | 将 Tomcat 的环境变量配置与 systemd 服务文件分离,方便管理 |
ExecStart=/usr/local/tomcat/bin/startup.sh |
指定服务的启动命令 | 当执行systemctl start tomcat时,systemd 会执行这个命令启动 Tomcat |
ExecStop=/usr/local/tomcat/bin/shutdown.sh |
指定服务的停止命令 | 当执行systemctl stop tomcat时,systemd 会执行这个命令停止 Tomcat |
PrivateTmp=true |
告诉 systemd,为 Tomcat 服务创建一个独立的临时目录,挂载在/tmp和/var/tmp上,服务停止后自动删除这个目录 |
提升安全性,避免 Tomcat 与其他进程共享临时目录,防止敏感信息泄露和文件冲突 |
User=tomcat |
指定 Tomcat 服务运行的用户 | 避免使用 root 用户运行 Tomcat,提升系统安全性 |
Group=tomcat |
指定 Tomcat 服务运行的用户组 | 与 User 配合,控制 Tomcat 对文件和目录的访问权限 |
[Install] |
systemd 开始解析服务的安装信息 | 定义服务的开机自启配置 |
WantedBy=multi-user.target |
告诉 systemd,当系统进入多用户模式时,自动启动 Tomcat 服务 | 实现 Tomcat 的开机自启 |
坑点(Gotchas)
- 服务文件修改后未重新加载 :修改
tomcat.service文件后,必须执行systemctl daemon-reload命令,让 systemd 重新加载配置,否则修改不会生效。 - User 和 Group 不存在 :如果指定的 tomcat 用户和组不存在,systemd 会无法启动 Tomcat 服务,提示
User tomcat not found。 - PrivateTmp 导致的文件找不到 :开启 PrivateTmp 后,Tomcat 的临时文件会存放在
/tmp/systemd-private-*-tomcat.service-*/tmp/目录下,而不是/tmp目录,排查问题时容易找不到临时文件。
企业级生产应用(Enterprise Scenario)
- 千万级并发场景 :生产环境必须使用 systemd 管理 Tomcat 服务,添加
Restart=always配置,实现服务异常自动重启;配置LimitNOFILE=65535,提升文件描述符数量,支持更多并发连接;配置CPUQuota和MemoryLimit,限制 Tomcat 服务的 CPU 和内存使用,避免影响其他服务。 - 进阶优化 :
- 使用 systemd 的 socket 激活功能,只有当有请求到来时才启动 Tomcat,节省系统资源。
- 配置 systemd 的日志,将 Tomcat 的日志输出到 journald,方便统一管理和查询。
- 使用 systemd 的模板单元,在同一台服务器上部署多个 Tomcat 实例,每个实例使用不同的端口和配置。
课后防宕机指南(Troubleshooting)
- 错误现象 :执行
systemctl start tomcat失败,提示Failed to start Tomcat.service: Unit Tomcat.service not found.- 排查思路:检查
tomcat.service文件是否放在/lib/systemd/system/目录下;检查文件名是否正确(区分大小写);执行systemctl daemon-reload重新加载 systemd 配置。
- 排查思路:检查
- 错误现象 :Tomcat 服务启动成功,但无法写入日志,提示
Permission denied- 排查思路:检查
/usr/local/tomcat/logs目录的所有者和组是否为 tomcat:tomcat;检查 tomcat 用户是否有 logs 目录的读写权限。
- 排查思路:检查
生活类比
生成 systemd 启动文件就像给你的餐厅(Tomcat)注册了一个营业执照,规定了餐厅的营业时间(开机自启)、负责人(tomcat 用户)、经营范围(资源限制),还请了一个保安(systemd),如果餐厅意外关门(服务崩溃),保安会立即重新开门(自动重启)。
3. 生成 tomcat 用户并设定软件安装目录权限
bash
运行
bash
[root@tomcatB bin]# useradd -s /sbin/nologin -M tomcat
[root@tomcatB bin]# chown tomcat.tomcat /usr/local/tomcat/ -R
代码逐行解析
表格
| 代码行 | 底层触发动作 | 作用 |
|---|---|---|
useradd -s /sbin/nologin -M tomcat |
创建一个名为 tomcat 的用户,-s /sbin/nologin指定用户的登录 shell 为/sbin/nologin,禁止该用户登录系统;-M不创建用户的家目录 |
创建一个专门用于运行 Tomcat 的普通用户,提升系统安全性,避免 Tomcat 被攻击后黑客获得登录权限 |
chown tomcat.tomcat /usr/local/tomcat/ -R |
递归修改/usr/local/tomcat/目录及其所有子目录和文件的所有者和组为 tomcat:tomcat |
让 tomcat 用户拥有 Tomcat 目录的所有权限,能够读写日志、临时文件和部署的应用 |
坑点(Gotchas)
- 权限设置过宽:不要将 Tomcat 目录的权限设置为 777,这会导致任何用户都可以修改 Tomcat 的配置和应用,存在严重的安全隐患。
- 递归修改权限的影响 :执行
chown -R会修改所有文件的所有者,包括 webapps 目录下的应用,如果应用中有需要特殊权限的文件,可能会导致应用运行异常。
4. 用启动脚本开启服务
bash
[root@tomcatB ~]# systemctl enable --now tomcat
代码逐行解析
systemctl enable --now tomcat:enable设置 Tomcat 服务开机自启,--now表示立即启动服务,相当于同时执行systemctl enable tomcat和systemctl start tomcat。- 底层动作:systemd 会在
/etc/systemd/system/multi-user.target.wants/目录下创建一个指向/lib/systemd/system/tomcat.service的软链接,实现开机自启;然后执行ExecStart指定的命令启动 Tomcat 服务。