Tomcat部署、优化、压力测试

news2024/11/15 17:44:10

目录

Tomcat概念

核心组件

Web容器

Web服务器之间解析请求的区别

Apache HTTP Server

Nginx

Tomcat

Servlet容器

JSP容器

字节码文件

Tomcat表面处理请求的过程

Tomcat底层处理请求的过程

内部结构

Tomcat部署

JRE环境配置

PATH冒号位置的区别

安装Tomcat

目录结构

常见端口号

发布站点

JMeter压力测试

Tomcat优化

优化前后对比


Tomcat概念

  • 免费、开源的Web应用服务器
  • Apache软件基金会(Apache Software Foundatio)Jakarta项目中的一个核心项目
  • 由Apache、Sun和一些公司及个人共同开发而成
  • 深受Java爱好者的喜爱,并得到部分软件开发商的认可
  • 目前比较流行的Web应用服务器

核心组件

Tomcat 由一系列的组件构成,其中核心的组件有三个:

web容器:完成web服务器的功能。

Servlet容器:名字为catalina,用于处理Servlet代码。

JSP 容器:用于将 JSP动态网页翻译成Servlet代码。


Web容器

Web 容器负责接收所有HTTP请求,根据请求的URL调用对应的Servlet映射来确定哪个Servlet来处理特定请求,或直接解析静态资源,然后将结果返回给客户端

Web服务器之间解析请求的区别
Apache HTTP Server

Apache HTTP Server服务器本身是可以独立处理静态资源请求,而对于动态资源的解析,Apache需要通过开启mod_php等模块才能动态请求

Nginx

Nginx服务器本身也可以独立处理静态资源请求,对于动态资源的解析,Nginx需要借助FastCGI等接口或者反向代理,将动态资源请求传递给后端服务器来解析,比如php-fpm、Node.js等服务器

Tomcat

Tomcat可以独立处理静态资源和动态资源的请求,Tomcat内置了Servlet和JSP的解析引擎,无需借助额外的模块或接口解析动态请求。

在实际部署中,因为Tomcat的静态解析效率不高,所以通常会将静态资源的处理交给专门的前端服务器,比如 Apache 或 Nginx,而将动态内容交给 Tomcat 这样的应用服务器,实现动静分离。


Servlet容器

在Java程序运行的时候,需要一个基本的JRE(Java运行时环境)环境,JRE不是一个单独的进程,而是一个容器,Tomcat是跑在JRE容器的环境里运行的

Servlet有一个名字:Catalina(卡特琳娜),负责加载和执行Servlet代码,并处理Servlet相关的请求。

比如将JSP代码通过JSP容器翻译成Servlet代码,然后由Servlet容器解析,最后将解析的结果返回Web容器,再由Web容器返回给用户


JSP容器

负责将JSP文件中的静态代码和Java代码编译成Servlet类。

一旦JSP文件被编译为Servlet类,它会被编译成字节码文件(.class)并可以在Servlet容器中执行。

JSP页面中包含的Java代码需要被编译成字节码,以便在Servlet容器中运行。这样做可以确保在每次请求时不需要重新解析和编译JSP页面,而是直接执行已经编译好的字节码

字节码文件

什么是字节码文件,比如使用记事本编写一个使用Main方法执行输出语句"HelloWord"的.java文件

然后在命令行使用javac命令对该文件进行编译,得到了.class为后缀的字节码(bytecode)文件。

这个.class文件就是字节码文件,可以在任何支持了JVM(Java虚拟机)的平台上运行,而无需重新编译

总结

字节码文件是Java代码最终编译的目标,它允许Java程序在JVM(Java虚拟机)上跨平台运行。


Tomcat表面处理请求的过程

  • tomcat默认端口号:8080
  1. 当用户在浏览器中输入服务器的IP地址和端口向客户端发送一个请求
  2. Tomcat服务器收到请求后通过JSP容器将请求页面的代码转换为Servlet代码
  3. 再转交给Servlet容器,Servlet基于JRE(Java运行时环境)解析请求
  4. 如果请求的内容涉及到数据库需要在Servlet代码中连接数据库获取数据
  5. 最后返回给用户

如果该服务器实现了动静分离,比如Nginx和Tomcat,当用户向Nginx的80端口发送动态解析请求时,Nginx通过反向代理将动态请求传递给Tomcat,由Tomcat处理后返回给Nginx再返回给用户

Tomcat底层处理请求的过程

  1. 当用户通过浏览器向服务器特定端口发送请求
  2. Connector接收请求后,交给Container中的Engine容器
  3. 通过用户输入的域名判断要访问的站点
  4. 确定了要访问的站点就会将找到对应Host
  5. Host收到请求后再交给Context
  6. 由Context当中的Servlet将代码进行解析
  7. 解析完成后,将请求返回给上层容器,直到返回给Connector,由连接器返回给用户

内部结构

容器

说明

Tomcat

可以看作是一个Tomcat服务器

Service

Tomcat服务器里有一个Service容器,每一个Tomcat只有一个Service容器,是其他子容器的集合

Connector

Service的子容器,当用户在浏览器中向Tomcat发起请求,Tomcat通过Connector(连接器)接收请求,Tomcat可以有多个连接器,每个连接器可以监听特定的端口。如果要在Tomcat部署基于端口的虚拟主机,就要添加连接器,每个连接器监听不同端口

Container

Service的子容器,最多只能有一个Container,负责最终为用户提供代码的解析,但是Container又包含了很多子容器

Engine

Container的子容器,最多只能有一个Engine,负责管理基于域名的虚拟主机

Host

Engine的子容器,Host可以有多个,每个Host都是一个虚拟主机

Context

上下文,负责每一个Host对应站点的代码运行

Servlet

Context可以包含多个Servlet,负责处理来自客户端的HTTP请求,执行一些逻辑(比如业务逻辑、数据处理等),然后生成符合HTTP标准的响应返回给客户端。

需要注意的是,Tomcat只支持基于端口和基于域名的虚拟主机,而没有基于IP的虚拟主机。


Tomcat部署

导入jdk的rpm软件包,使用rpm -ivh jdk-8u171-linux-x64.rpm命令安装jdk环境

装完可以使用java -version命令测试是否正常显示版本信息,还可以在/usr/下看到名为java的文件夹,就是安装目录

JRE环境配置

为了确保Java能够正常运行,需要设置配置环境变量,在全局环境变量文件中使用export将Java家目录的路径和类库路径的添加为全局变量

并且将Java命令添加到系统查找命令的$PATH变量中,也就是echo $PATH显示的多个路径,系统会在这些路径下查找和用户输入内容所匹配的命令

最后使用source命令重新加载存放环境变量的文件,然后再输出$PATH变量的值,就可以看到Java命令的路径已经被追加到末尾了

此时JRE(Java运行时环境)就配置好了

[root@localhost ~]# vim /etc/profile
export JAVA_HOME=/usr/java/jdk1.8.0_171-amd64
export CLASSPATH=$JAVA_HOME/lib
export PATH=$PATH:$JAVA_HOME/bin

[root@localhost jdk1.8.0_171-amd64]# source /etc/profile
[root@localhost jdk1.8.0_171-amd64]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/usr/java/jdk1.8.0_171-amd64/bin

PATH冒号位置的区别

这里使用的PATH变量不是新建了一个PATH变量,而是调用了系统已有的变量,冒号(:)表示在该变量的值末尾,追加指定值,这里追加了Java命令的路径,让系统可以在终端中识别Java命令

如果将PATH变量的冒号放到末尾去追加行不行呢?

就变成了:export PATH=$JAVA_HOME/bin:$PATH

实际上是可行的,但是实现的效果相反,比如当你执行了export PATH=$JAVA_HOME/bin:$PATH

这个命令会将$JAVA_HOME/bin的路径放在现有$PATH变量的开头,就不是追加了,但是$PATH会把$JAVA_HOME/bin放在$PATH的最前面,在系统识别命令_时,优先搜索Java命令

如果当你执行了export PATH=$PATH:$JAVA_HOME/bin,则会把$JAVA_HOME/bin放到$PATH变量的末尾,当系统识别命令时,会先搜索现有路径再搜索$JAVAHOME/bin


安装Tomcat

导入Tomcat的tar.gz包,由于该包是直接解压使用的,所以使用tar zxvf apache-tomcat-9.0.8.tar.gz命令直接解压,然后通过mv apache-tomcat-9.0.8 /usr/local/tomcat命令将该包移动到/usr/local/下,重命名为tomcat

目录结构

进入tomcat目录,使用ll命令可以查看tomcat的目录结构

目录或文件

说明

bin

用于存放Tomcat的可执行文件,比如启动和停止脚本 (startup.sh、shutdown.sh)

以及其他管理和维护 Tomcat 服务器的工具

conf

用于存放Tomcat的配置文件

lib

用于存放Tomcat运行时需要Java类库和依赖的JAR文件

logs

用于存储Tomcat的日志文件

temp

用于存放 Tomcat 运行时生成的临时文件,比如编译后的 JSP 文件等。

webapps

存放Tomcat的默认web应用程序部署目录,将你的WAR包放入后,Tomcat 会自动解压并运行这些应用。

work

用于存放Tomcat运行时生成的servlet编译文件。

LICENSE

这是 Tomcat 的许可证文件,包含了软件使用和分发的许可条款。

RELEASE-NOTES

这是该版本 Tomcat 的发行说明,描述了新功能、改进和已知问题等信息。

RUNNING.txt

这个文件提供了关于如何运行 Tomcat 服务器的简要说明和提示。

常见端口号

打开/usr/local/tomcat/conf/server.xml文件,在Tomcat的配置文件中可以看到多个容器的标签内都有Port的属性

这个Port属性就定义了在某个阶段监听的端口号,下面一一列出重要的端口号

端口号

说明

8005

只能在本地用命令行关闭Tomcat服务的端口

8009

Tomcat服务器通过Connector连接器组件与客户程序建立连接使用的端口

8080

Tomcat的web服务端默认端口号(HTTP)

8443

访问Tomcat的HTTPS的端口

发布站点

这里我们要通过基于域名的虚拟主机发布两个站点,先创建存放第一个站点的目录www,新建index.jsp文件,添加www.benet.com内容

再创建bbs站点,步骤同上

[root@localhost tomcat]# cd webapps/
[root@localhost webapps]# mkdir www
[root@localhost webapps]# cd www
[root@localhost www]# vim index.jsp
www.benet.com
[root@localhost www]# cd ..
[root@localhost webapps]# mkdir bbs
[root@localhost webapps]# cd bbs
[root@localhost bbs]# vim index.jsp
bbs.benet.com
打开配置文件
[root@localhost ~]# vim /usr/local/tomcat/conf/server.xml

在tomcat的配置文件中添加站点,在第148行可以看到Host容器,修改name属性的域名为www.benet.com,添加Context(上下文)标签,指定该域名的网页文件位置,开启自动重载,然后再创建一个Host标签,修改name等参数,用于第二个站点的发布

  • Context标签内的path属性的作用是:虚拟路径,指定了在Web服务器上访问该Web应用程序的路径,如果 path 设置为 ""(空),则该应用程序将作为根应用程序处理。如果设置为 "/myapp",则用户访问http://www.benet.com/myapp地址时,该站点才会可用
  • reloadable:当类的内容发行改动时,会自动重载,而不需要人为重启
      <Host name="www.benet.com"  appBase="webapps"
            unpackWARs="true" autoDeploy="true"> 
            <Context docBase="/usr/local/tomcat/webapps/www" path="" reloadable="true" />
            <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="www_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />

      </Host>

      <Host name="bbs.benet.com"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
            <Context docBase="/usr/local/tomcat/webapps/bbs" path="" reloadable="true" />
        
            <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="bbs_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />

      </Host>

首先关闭防火墙,允许tomcat流量通过。最后运行tomcat的bin目录下的startup.sh,启动tomcat

[root@localhost tomcat]# systemctl stop firewalld
[root@localhost tomcat]# cd bin/

[root@localhost bin]# ./startup.sh
[root@localhost bin]# netstat -anpt | grep java
tcp6       0      0 127.0.0.1:8005          :::*                    LISTEN      19470/java          
tcp6       0      0 :::8009                 :::*                    LISTEN      19470/java          
tcp6       0      0 :::8080                 :::*                    LISTEN      19470/java

使用Linux或Windows主机都可以测试,但前提是在主机上的Hosts文件添加对应解析条目

192.168.10.101 www.benet.com bbs.benet.com

使用域名:端口号的方式来访问Tomcat服务器


JMeter压力测试

JMeter是基于JAVA开发的压力测试软件。用于在Windows系统上运行,在短时间内向服务器发送大量请求,来测试服务器压力承受的能力

打开一台Win10虚拟机或直接在宿主机上测试,解压apachejmeter31.zip软件包,进入bin目录下,双击运行jmeter.bat批处理文件启动该工具

首先添加一个用户线程组

线程数:每个线程代表一个虚拟用户,将线程组的进程数设置为100,JMeter将会模拟100个并发用户同时对目标系统进行请求,这里用我们使用4000个线程

Ramp-up Period(in seconds):每秒钟,1个线程发送多少个请求

那么请求总量就是4000 * 20 = 80000,也就是说总共向服务器在短时间内发送80000个请求让服务器来响应

右键测试计划是针对整个测试计划添加聚合报告和图形结果,用于显示整个测试计划的测试结果

添加测试的请求

写入要测试的域名和端口号

测试该线程组时时可以把针对整个测试计划的图形结果和聚合报告删除,右键线程组,添加只针对线程组的聚合报告和图形结果

最终效果如下

然后右键线程组,选Start

如果是第一次测试,会提示你保存该线程组,方便以后使用,然后压力测试就已经开始了

当上方的箭头图标变绿了以后,代表测试已经结束,可以查看结果报告

打开聚合报告会显示出测试结果,把优化前的测试结果截图保存,用于和一会优化后的结果对比

Tomcat优化

打开tomcat配置文件

[root@localhost ~]# cd /usr/local/tomcat/conf/
[root@localhost conf]# vim server.xml

将连接器改为以下内容,进行优化

<Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" 
               minSpareThreads="50"
               enableLookups="false"  
               disableUploadTimeout="true"
               acceptCount="300" 
               maxThreads="500" 
               processorCache="500"
               URIEncoding="UTF-8" 
               compression="on"
               compressionMinSize="2048" 
               compressableMimeType="text/html,text/xml,text/javascript,text/css,tex t/plain,image/gif,image/jpg,image/png" />

参数

说明

connectionTimeout="20000"

指定了连接超时时间,单位是毫秒。在20秒内如果连接没有建立成功,则超时。

redirectPort="8443"

指定了当需要进行重定向时使用的端口号,一般用于HTTPS协议的情况,这里是8443端口

minSpareThreads="50"

指定了最小空闲线程数。Tomcat会尽量保持至少这么多个线程处于空闲状态,以备处理新的请求。

enableLookups="false"

设置是否允许DNS查询。这里设置为false,表示不允许Tomcat对客户端的IP地址进行DNS查询。

disableUploadTimeout="true"

禁用上传超时。设置为true时,Tomcat将不会对上传操作设置超时限制。

acceptCount="300"

指定了在处理满负荷的情况下,能接受的最大连接请求数。当达到这个数目后,新的连接请求将会被拒绝。

maxThreads="500"

指定了连接器处理的最大线程数。当达到这个数目时,新的连接请求会进入等待队列(如果已满则会拒绝连接)

processorCache="500"

指定了处理器缓存的大小。Tomcat在内部使用处理器对象池来重复使用已经创建的处理器。这里设置为500,表示最多可以缓存500个处理器对象。

URIEncoding="UTF-8"

指定了URL的编码格式。这里设置为UTF-8

compression="on"

启用响应内容的压缩功能

compressionMinSize="2048"

设置触发压缩的最小响应内容大小,单位是字节。当响应内容大于这个值时才会进行压缩

compressableMimeType

指定可以进行压缩的MIME类型

重启tomcat

[root@localhost conf]# ../bin/shutdown.sh
[root@localhost conf]# ../bin/startup.sh

先访问tomcat能否在浏览器正常访问,确保修改后的配置文件能够正常运行tomcat

优化前后对比

确保修改的配置文件能够正常运行tomcat后,可以进行优化的压力测试,此时打开JMeter工具

第二次测试之前先清除全部,否则第二次测试的结果会和第一次的重叠

右键线程组 ——》Start

开始压力测试

待上方箭头图标变成绿色之后,表示测试结束

此时将优化后的聚合报告也截图保存,然后放到Word文档里,可以进行对比

参数

说明

Label

表示每个HTTP请求或事务的名称或标识。用来区分不同请求或事务的名称。

Samples

表示测试中一共发出了多少个请求,单位一般为毫秒

Average

平均响应时间,越小越好

Median

中位数,也就是 50% 用户的响应时间

90% Line

90% 用户的响应时间

95% Line

95% 用户的响应时间

99% Line

99% 用户的响应时间

Min

最小响应时间

Max

最大响应时间

Error %

本次测试中出现错误的请求的数量/请求的总数

Throughput

吞吐量,表示每秒完成的请求数。单位是请求/秒

Received KB/sec

每秒接收的数据量,单位是KB/秒。

Sent KB/sec

每秒发送的数据量,单位是KB/秒。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1946123.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

连接Redis异常:JedisMovedDataException

redis.clients.jedis.exceptions.JedisMovedDataException: MOVED 5798 192.168.187.138:6379 在使用JAVA API连接redis的时候&#xff0c;出现了异常&#xff1a; 问题的原因 JAVA API实现是redis集群实现方式&#xff0c;而在配置文中就配置的是单结点的方式。 Moved表示使…

MySQL的高可用(MHA)

高可用模式下的故障切换&#xff0c;基于主从复制。 单点故障和主从复制不能切换的问题。 至少需要三台。 故障切换过程0-30秒 vip地址&#xff0c;根据vip地址所在的主机&#xff0c;确定主备。 主 vip 备 vip 主和备不是优先级确定的&#xff0c;主从复制的时候就确定…

使用infercnv对单细胞转录组进行拷贝数变异推断(上,原理)

InferCNV 是一个专门设计用于鉴定肿瘤样本中拷贝数变异&#xff08;Copy Number Variations, CNVs&#xff09;的R包&#xff0c;特别是在单细胞RNA测序&#xff08;scRNA-seq&#xff09;数据分析领域。它通过比较肿瘤细胞与正常细胞&#xff08;或参照细胞&#xff09;的基因…

【Leetcode】十八、动态规划:不同路径 + 全1的最大正方形

文章目录 1、动态规划2、leetcode509&#xff1a;斐波那契数列3、leetcode62&#xff1a;不同路径4、leetcode121&#xff1a;买卖股票的最佳时机5、leetcode70&#xff1a;爬楼梯6、leetcode279&#xff1a;完全平方数7、leetcode221&#xff1a;最大正方形 1、动态规划 只能…

CTFSHOW 萌新 web5 解题思路和方法

点击题目链接&#xff0c;发现页面代码&#xff0c;根据最后一行的提示当id1000时返回flag值&#xff0c;但是前面if判断intval(id)的值不得超过999&#xff0c;故需要对其进行绕过。 我们发现题目中相比前几题中过滤条件更为严格&#xff0c;但是没有过滤取反运算符。此时我们…

matlab 绘制参数方程

matlab 绘制参数方程 绘制参数方程绘制结果 绘制参数方程 clc; clear; close all;axis_length 100;% 定义参数t的范围 t 0:0.01:100;% 计算x和y的值 x t.^2 1; y 4*t - t.^2;% 绘制函数图像 plot(x, y); xlabel(x); ylabel(y); title(Plot of the curve xt^21, y4t-t^2…

运维朋友最喜欢的一集:trzsz-ssh!!【送源码】

软件介绍 trzsz-ssh&#xff08;tssh&#xff09;是一个替代openssh的SSH客户端软件&#xff0c;支持trzsz、批量登录、密码记忆、zmodem等功能。可实现方便的本地与远程服务器文件传输&#xff0c;支持多系统跨平台运行&#xff0c;提供良好的交互体验和进度显示。优势包括tmu…

普发Pfeiffer真空TSH071TSU261TSH521泵站电路图安装操作使用说明

普发Pfeiffer真空TSH071TSU261TSH521泵站电路图安装操作使用说明

0724, 大型补作业现场

sock编程 struct sockaddr struct sockaddr_in --> struct in_addr struct hostent htonl() htons() ntohl() ntohs() int inet_aton(const char* cp,struct in_addr * inp); in_addr_t inet_addr(const char* cp); const char* inet_ntop…

深入理解算数表达式求值:后缀表达式的转换与计算

归纳编程学习的感悟&#xff0c; 记录奋斗路上的点滴&#xff0c; 希望能帮到一样刻苦的你&#xff01; 如有不足欢迎指正&#xff01; 共同学习交流&#xff01; &#x1f30e;欢迎各位→点赞 &#x1f44d; 收藏⭐ 留言​&#x1f4dd;没人会嘲笑竭尽全力的人&#xff01; 前…

软件渗透测试包括的内容和作用简析

在当今信息技术迅速发展的时代&#xff0c;软件安全已成为企业和用户关注的重中之重。尤其是渗透测试作为一种专业的安全测试方法&#xff0c;日益受到企业们的重视。   软件渗透测试是一种模拟恶意攻击者的方式&#xff0c;对软件及其相关系统进行评估&#xff0c;以发现可能…

html基础及python web开发

1.标签 ①p标签 段落标签&#xff0c;分隔段与段。 <p>...</p> ②h标签 标题标签h1-6&#xff0c;大小依次减小 <h1>...</h1> <h2>...</h2> <h3>...</h3> <h4>...</h4> <h5>...</h5> <h6>.…

数据结构的概念和术语

目录 一.前言 二.数据结构的基本概念 三.数据结构的术语 一.前言 数据结构是一门研究非数值计算的程序设计中计算机的操作对象以及它们之间的关系和操作的学科。数据结构的基本数据结构包括两部分&#xff0c;线性结构跟非线性结构。 二.数据结构的基本概念 数据结构主要包括…

MarkTool集合篇

MarkTool目前包含以下几种工具 1、TCP客户端 2、TCP服务端 3、UDP客户端 4、Web客户端 5、Web服务端 6、串口网口 7、PLC 8、获取本机设备 9、Log 10、密钥 11、系统设置 11-1、基本设置 11-2、角色设置 11-3、用户设置 11-4、log记录 开启软件需要找我解密&#…

怎样做好仓库管理工作?如何利用仓库管理系统进行有效管理?

我前前后后跑遍了十几家仓储设备公司&#xff0c;跟那些制造业的朋友们聊了个痛快&#xff0c;从他们那儿学到了不少仓库管理的实践方法。 回来自己整理了一套仓库管理更高效的实用方法&#xff0c;现在就来跟大家伙儿聊聊仓库管理中那些常见问题&#xff0c;以及我是怎么琢磨…

(前缀和) LeetCode 238. 除自身以外数组的乘积

一. 题目描述 原题链接 给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&…

HarmonyOS网络请求的简单用法,HttpUtil简单封装

请求网络获取数据 点击按钮发送一个post请求&#xff0c;发送一条string由于此处的返回result.data本身就是一个string&#xff0c;因此不需要转换类型 Button(请求网络).margin({ top: 10 }).fontSize(24).fontWeight(FontWeight.Bold).onClick(() > {httpRequestPost(http…

算法从零到精通 (一) ~ 快慢双指针

1. 前言 快慢双指针是一种常用的算法技巧&#xff0c;通常用于解决涉及链表或数组的问题。它的基本思想是使用两个指针&#xff0c;一个移动速度快&#xff08;快指针&#xff09;&#xff0c;一个移动速度慢&#xff08;慢指针&#xff09;&#xff0c;来解决特定的问题。这两…

【高可用】利用AOP实现数据库读写分离

最近项目中需要做【高可用】数据库读写分离相关的需求&#xff0c;特地整理了下关于读写分离的相关知识。项目中采用4台数据库&#xff1a;1个master&#xff0c;2个slave&#xff0c;1个readOnly&#xff0c;其中master数据库会自动定时同步到readOnly节点。可以通过中间件(Sh…

Mysql —— 事务

目录 什么是事务&#xff1f; 两种方式实现事务&#xff1a; 方法一 方法二&#xff1a; 事务四大特性(简称ACID) 并发事务问题&#xff08;面试题&#xff09; 事务隔离级别 什么是事务&#xff1f; 事务是一组操作的集合&#xff0c;它是一个不可分割的工作单位&#xff…