企业级 Tomcat (上):WEB 技术栈 + 架构演进 + 生产级安装部署

目录

[一 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))

坑点(Gotchas)

[企业级生产应用(Enterprise Scenario)](#企业级生产应用(Enterprise Scenario))

课后防宕机指南(Troubleshooting)

生活类比

[1.2.2 CSS (Cascading Style Sheets) 层叠样式表](#1.2.2 CSS (Cascading Style Sheets) 层叠样式表)

板块核心解释

坑点(Gotchas)

企业级生产应用

[1.2.3 JavaScript](#1.2.3 JavaScript)

同步

异步

板块核心解释

坑点(Gotchas)

企业级生产应用

[二 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 单体架构和微服务比较)

微服务的优点

微服务缺点:

常见的微服务框架

Dubbo

[Spring cloud](#Spring cloud)

板块核心解释

企业级生产应用

[三 tomcat 的功能介绍](#三 tomcat 的功能介绍)

板块核心解释

[3.1 安装 Tomcat](#3.1 安装 Tomcat)

[1. 安装 java 环境](#1. 安装 java 环境)

[代码逐行解析(Line-by-Line Breakdown)](#代码逐行解析(Line-by-Line Breakdown))

坑点(Gotchas)

[企业级生产应用(Enterprise Scenario)](#企业级生产应用(Enterprise Scenario))

课后防宕机指南(Troubleshooting)

生活类比

[2. 安装并启动 tomcat](#2. 安装并启动 tomcat)

[代码逐行解析(Line-by-Line Breakdown)](#代码逐行解析(Line-by-Line Breakdown))

坑点(Gotchas)

企业级生产应用

课后防宕机指南(Troubleshooting)

[3. 查看端口](#3. 查看端口)

代码逐行解析

坑点(Gotchas)

[4. 访问 tomcat](#4. 访问 tomcat)

板块核心解释

[3.2 tomcat 的文件结构和组成](#3.2 tomcat 的文件结构和组成)

目录结构

目录详细解释

坑点(Gotchas)

企业级生产应用

[3.3 生成 tomcat 的启动文件](#3.3 生成 tomcat 的启动文件)

[1. 生成 tomcat 的主配置文件](#1. 生成 tomcat 的主配置文件)

代码逐行解析

坑点(Gotchas)

[2. 生成启动文件](#2. 生成启动文件)

[代码逐行解析(Line-by-Line Breakdown)](#代码逐行解析(Line-by-Line Breakdown))

坑点(Gotchas)

[企业级生产应用(Enterprise Scenario)](#企业级生产应用(Enterprise Scenario))

课后防宕机指南(Troubleshooting)

生活类比

[3. 生成 tomcat 用户并设定软件安装目录权限](#3. 生成 tomcat 用户并设定软件安装目录权限)

代码逐行解析

坑点(Gotchas)

[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)
  1. 字符编码错误 :将UTF-8写成gbkutf8(无横杠),会导致所有中文显示为乱码,且难以排查。
  2. 缺失 DOCTYPE 声明:浏览器会自动进入怪异模式,页面布局在不同浏览器中出现严重偏移,CSS 样式失效。
  3. 标签不闭合 :如<meta>不写闭合斜杠(HTML5 允许,但 XHTML 不允许),会导致旧浏览器解析出错。
企业级生产应用(Enterprise Scenario)
  • 千万级并发场景:所有静态 HTML 页面都会被 CDN 缓存,用户请求直接命中 CDN 节点,无需回源到 Tomcat 服务器,减轻 90% 以上的静态资源压力。
  • 进阶优化
    1. 压缩 HTML 代码,删除空格、注释和换行,减少文件体积。
    2. 使用语义化标签(<header><nav><main>)替代通用<div>,提升 SEO 和可维护性。
    3. 配置 HTTP 缓存头(Cache-Control),让浏览器长期缓存静态 HTML 页面。
课后防宕机指南(Troubleshooting)
  1. 错误现象 :页面中文全部显示为问号或乱码
    • 排查思路:检查<meta charset="UTF-8">是否存在且拼写正确;检查服务器返回的 HTTP 响应头中的Content-Type是否包含charset=UTF-8;检查 HTML 文件本身的编码是否为 UTF-8(无 BOM)。
  2. 错误现象 :页面在 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)
  1. 样式优先级冲突:行内样式 > ID 选择器 > 类选择器 > 标签选择器,优先级计算错误会导致样式不生效。
  2. 盒模型差异 :旧 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)
  1. 跨域问题:由于浏览器的同源策略,AJAX 请求只能发送到当前页面所在的域名,否则会被浏览器拦截,这是前端开发最常见的问题之一。
  2. 异步回调地狱:多个异步请求嵌套调用,会导致代码层级过深,难以维护和调试。
企业级生产应用
  • 千万级并发场景:所有 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

官网: http://tomcat.apache.org/

官网文档: 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)
  1. Java 版本不兼容:Tomcat 9 需要 Java 8 及以上版本,Tomcat 10 需要 Java 11 及以上版本,安装错误的 Java 版本会导致 Tomcat 启动失败。
  2. 使用 JRE 而非 JDK :虽然 Tomcat 可以运行在 JRE 上,但 JSP 编译需要 JDK 的javac编译器,只安装 JRE 会导致 JSP 页面无法访问。
  3. yum 自动升级 Java:使用 yum 安装的 Java 会随系统更新自动升级,可能导致版本变化,影响 Tomcat 的稳定性。
企业级生产应用(Enterprise Scenario)
  • 千万级并发场景 :生产环境不会使用 yum 安装 OpenJDK,而是手动安装 Oracle JDK 或 Amazon Corretto,解压到/usr/local/jdk目录,手动配置 JAVA_HOME 环境变量,避免 yum 自动升级。
  • 进阶优化
    1. 配置 JVM 参数(堆内存、新生代大小、垃圾回收器),根据服务器配置调整,提升 Tomcat 的性能。
    2. 使用 JDK 的 jstat、jmap、jstack 等工具监控 JVM 的运行状态,及时发现内存泄漏和性能问题。
    3. 开启 JVM 的 GC 日志,方便排查垃圾回收导致的卡顿问题。
课后防宕机指南(Troubleshooting)
  1. 错误现象 :执行java -version提示command not found
    • 排查思路:检查 Java 是否安装成功;检查 PATH 环境变量是否包含 Java 的 bin 目录;检查/usr/bin/java软链接是否存在且指向正确的路径。
  2. 错误现象 :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 startcatalina.sh会设置 CATALINA_BASE、CATALINA_HOME、JRE_HOME 等环境变量,然后启动 JVM 进程,加载 Tomcat 的核心类(bootstrap.jar),初始化 Catalina 容器,监听 8080 端口 启动 Tomcat 服务器,开始接收客户端的 HTTP 请求
坑点(Gotchas)
  1. 端口被占用:Tomcat 默认监听 8080 端口,如果该端口被其他进程(如 Nginx、其他 Tomcat 实例)占用,Tomcat 会启动失败。
  2. 防火墙未开放端口:CentOS 默认开启 firewalld 防火墙,未开放 8080 端口会导致外部无法访问 Tomcat。
  3. 使用 root 用户启动 Tomcat:root 用户拥有系统最高权限,如果 Tomcat 被黑客攻击,黑客会获得整个服务器的控制权,存在严重的安全隐患。
企业级生产应用
  • 千万级并发场景:生产环境会修改 Tomcat 的默认端口(8080 改为其他端口),避免被黑客扫描;使用普通用户启动 Tomcat,提升安全性;配置 Tomcat 的连接器参数(最大连接数、线程数),提升并发处理能力。
  • 进阶优化
    1. 开启 APR(Apache Portable Runtime)模式,使用本地库处理网络请求,大幅提升 Tomcat 的性能。
    2. 配置 Tomcat 的访问日志,记录所有 HTTP 请求的详细信息,方便排查问题和分析访问量。
    3. 禁用 Tomcat 的默认应用(ROOT、docs、examples),删除不必要的管理页面,提升安全性。
课后防宕机指南(Troubleshooting)
  1. 错误现象 :执行./startup.sh提示 Tomcat started,但访问 8080 端口连接被拒绝
    • 排查思路:执行netstat -antlupe | grep java查看 Tomcat 是否监听 8080 端口;检查防火墙是否开放 8080 端口(firewall-cmd --list-ports);检查 SELinux 是否阻止 Tomcat 绑定端口(setenforce 0临时关闭 SELinux 测试)。
  2. 错误现象 :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)
  1. netstat 命令未安装 :CentOS 7 及以上版本默认不安装 netstat,需要执行yum install net-tools -y安装。
  2. 只监听 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
目录详细解释
  1. bin 目录 :存放 Tomcat 的所有可执行脚本,核心是catalina.sh(Linux)和catalina.bat(Windows),所有启动、停止、重启等操作都是通过调用这个脚本实现的。
  2. lib 目录:存放 Tomcat 运行所需的所有 Java 类库(jar 包),包括 Servlet API、JSP API、Tomcat 核心类库等。所有部署在 Tomcat 上的 web 应用都会共享这个目录下的 jar 包。
  3. conf 目录 :存放 Tomcat 的全局配置文件,核心配置文件包括:
    • server.xml:Tomcat 的主配置文件,配置连接器、引擎、主机等核心组件。
    • context.xml:全局的上下文配置文件,所有部署的 web 应用都会继承这个配置。
    • web.xml:全局的 web 应用配置文件,定义了默认的 Servlet、过滤器、错误页面等。
    • tomcat-users.xml:配置 Tomcat 的用户和角色,用于管理控制台的身份认证。
  4. logs 目录 :存放 Tomcat 的所有日志文件,重要的日志文件包括:
    • catalina.out:Tomcat 的标准输出和错误日志,所有 System.out.println () 的输出和异常堆栈信息都会打印到这个文件。
    • localhost_access_log.*.txt:Tomcat 的访问日志,记录所有 HTTP 请求的详细信息,包括客户端 IP、请求时间、请求 URL、响应状态码、响应时间等。
    • localhost.*.loglocalhost主机的日志,记录 web 应用的初始化和销毁信息。
  5. webapps 目录:Tomcat 的默认应用部署目录,将 war 包放在这个目录下,Tomcat 会自动解压并部署应用。默认包含 ROOT(根应用)、docs(文档)、examples(示例)、manager(管理应用)、host-manager(主机管理应用)五个应用。
  6. work 目录:存放 JSP 编译生成的 Servlet 字节码文件。Tomcat 会将每个 JSP 文件编译成一个 Java 类,然后编译成字节码文件,存放在 work 目录下。第一次访问 JSP 时会比较慢,因为需要编译,提前预热访问可以让 Tomcat 预编译所有 JSP,提升用户体验。
  7. temp 目录:存放 Tomcat 运行时产生的临时文件,如文件上传的临时文件等。
坑点(Gotchas)
  1. 修改 lib 目录下的 jar 包:随意修改或删除 lib 目录下的 jar 包会导致 Tomcat 启动失败或运行异常。
  2. catalina.out 文件过大:Tomcat 默认不会轮转 catalina.out 文件,长时间运行会导致文件过大,占满磁盘空间,甚至导致系统崩溃。
  3. 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)
  1. JAVA_HOME 路径写错 :必须指向 JRE 或 JDK 的根目录,不能指向 bin 目录,否则 Tomcat 会提示JAVA_HOME is not defined correctly
  2. 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)
  1. 服务文件修改后未重新加载 :修改tomcat.service文件后,必须执行systemctl daemon-reload命令,让 systemd 重新加载配置,否则修改不会生效。
  2. User 和 Group 不存在 :如果指定的 tomcat 用户和组不存在,systemd 会无法启动 Tomcat 服务,提示User tomcat not found
  3. PrivateTmp 导致的文件找不到 :开启 PrivateTmp 后,Tomcat 的临时文件会存放在/tmp/systemd-private-*-tomcat.service-*/tmp/目录下,而不是/tmp目录,排查问题时容易找不到临时文件。
企业级生产应用(Enterprise Scenario)
  • 千万级并发场景 :生产环境必须使用 systemd 管理 Tomcat 服务,添加Restart=always配置,实现服务异常自动重启;配置LimitNOFILE=65535,提升文件描述符数量,支持更多并发连接;配置CPUQuotaMemoryLimit,限制 Tomcat 服务的 CPU 和内存使用,避免影响其他服务。
  • 进阶优化
    1. 使用 systemd 的 socket 激活功能,只有当有请求到来时才启动 Tomcat,节省系统资源。
    2. 配置 systemd 的日志,将 Tomcat 的日志输出到 journald,方便统一管理和查询。
    3. 使用 systemd 的模板单元,在同一台服务器上部署多个 Tomcat 实例,每个实例使用不同的端口和配置。
课后防宕机指南(Troubleshooting)
  1. 错误现象 :执行systemctl start tomcat失败,提示Failed to start Tomcat.service: Unit Tomcat.service not found.
    • 排查思路:检查tomcat.service文件是否放在/lib/systemd/system/目录下;检查文件名是否正确(区分大小写);执行systemctl daemon-reload重新加载 systemd 配置。
  2. 错误现象 :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)
  1. 权限设置过宽:不要将 Tomcat 目录的权限设置为 777,这会导致任何用户都可以修改 Tomcat 的配置和应用,存在严重的安全隐患。
  2. 递归修改权限的影响 :执行chown -R会修改所有文件的所有者,包括 webapps 目录下的应用,如果应用中有需要特殊权限的文件,可能会导致应用运行异常。

4. 用启动脚本开启服务
bash 复制代码
[root@tomcatB ~]# systemctl enable --now tomcat
代码逐行解析
  • systemctl enable --now tomcatenable设置 Tomcat 服务开机自启,--now表示立即启动服务,相当于同时执行systemctl enable tomcatsystemctl start tomcat
  • 底层动作:systemd 会在/etc/systemd/system/multi-user.target.wants/目录下创建一个指向/lib/systemd/system/tomcat.service的软链接,实现开机自启;然后执行ExecStart指定的命令启动 Tomcat 服务。
相关推荐
FinAnalyzer1 小时前
Finanalyzer:开源版 OpenBB Workspace 来了!
开源
JAMSAN09301 小时前
AI服务器MLCC:从“电子大米”到“算力石油”的价值重估
运维·人工智能·数据分析·智能硬件
华纳云IDC服务商1 小时前
高防服务器清洗流量导致丢包怎么办?
运维·服务器·网络
KuaCpp1 小时前
C++进阶(上)
linux·c++
一直跑1 小时前
codex服务器运用(服务器上不了外网chatgpt)
运维·服务器·chatgpt
云服务器代理商1 小时前
腾讯云香港服务器选择指南:延迟优势、配置价格与开通思路
服务器·云计算·腾讯云·腾讯云服务器·香港节点·腾讯云国际·腾讯云海外
草莓熊Lotso1 小时前
【Linux网络】深入理解 TCP 协议(一):报头设计与可靠性基石
linux·运维·服务器·c语言·网络·c++·tcp/ip
风曦Kisaki1 小时前
#Linux监控与安全Day02:Zabbix 自动发现,Zabbix 报警机制,Zabbix 主动监控,监控 Nginx 服务
linux·运维·nginx·安全·自动化·云计算·zabbix
gis分享者1 小时前
Linux 网络层 IP 协议与网段划分实战指南
linux·运维·tcp/ip