【高并发优化手段】基于Springboot项目(二)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 【高并发优化手段】基于Springboot项目
📝 修改配置

修改文件系统参数需要以管理员身份登录系统,然后按照以下步骤进行操作:

①. 修改文件打开数:

  1. 打开命令行终端,输入以下命令:
sudo vi /etc/sysctl.conf
  1. 在打开的配置文件中添加以下代码:
# 设置系统的最大文件句柄数为 65535
fs.file-max = 65535
  1. 保存文件并关闭。
  2. 输入以下命令,使配置修改生效:
sudo sysctl -p

②. 修改文件描述符大小:

  1. 打开命令行终端,输入以下命令:
sudo vi /etc/security/limits.conf
  1. 在打开的配置文件中添加以下代码:
*    soft    nofile    65535
*    hard    nofile    65535
  1. 保存文件并关闭。
  2. 输入以下命令,使配置修改生效:
ulimit -n 65535

注意:此配置只对当前用户有效,如果要对所有用户生效,需要重启系统。

③. 修改内存缓存大小:

要修改CentOS 7系统的内存缓存大小,可以执行以下步骤:

  1. 打开终端并以root用户身份登录。
  2. 编辑 /etc/sysctl.conf 文件,如下所示:
vi /etc/sysctl.conf
  1. 在文件的末尾添加以下行:
# 设置系统脏页(未写入磁盘的页面)达到多少字节时可以开始写入磁盘
vm.dirty_background_bytes = 8388608
# 设置系统脏页达到多少字节时必须写入磁盘
vm.dirty_bytes = 25165824
# 设置可以在后台写入磁盘的脏页占总脏页的比例(即总脏页数的2%)
vm.dirty_background_ratio = 2
# 设置当系统脏页占总内存的比例超过5%时,系统必须开始写入磁盘
vm.dirty_ratio = 5
# 设置系统判定一个脏页需要写入磁盘的时间,单位为centisecond,即2000分之一秒
vm.dirty_expire_centisecs = 2000

这些参数表示内存缓存的大小,可以根据需要进行修改。上述示例将默认值设置为16 MB和48 MB。

4. 保存并关闭文件。

5. 执行以下命令以使更改生效:

sysctl -p

现在,您已成功修改了CentOS 7系统的内存缓存大小。

🎉 (3)内存参数

可以设置以下参数,以提高服务器的内存管理效率:

①. 最小内存分配单位:默认为4KB,可以设置为1KB,以节省内存开销。

②. 堆内存大小:默认为1/4的物理内存大小,可以根据应用需求和机器配置进行调整。

③. 堆内存溢出处理方式:可以选择直接退出应用,或者打印错误信息并继续运行。

🌟 三、Tomcat配置

Tomcat是Spring Boot默认的Web容器,它的配置也需要进行优化,以提高性能。

🎉 1. 调整最大连接数

sever:
  tomcat:
    # 1核2g内存为200,线程数经验值200;4核8g内存,线程数经验值800,以此类推
    threads:
      # 最多的工作线程数,默认大小是200。该参数相当于临时工,如果并发请求的数量在10到200之间,就会使用这些临时工线程进行处理。建议设置为 2 倍到 4 倍的 QPS
      max: 6667
      # 最少的工作线程数,默认大小是10。该参数相当于长期工,如果并发请求的数量达不到10,就会依次使用这几个线程去处理请求。如果min-spare设置得太低,那么当应用程序接收到高并发请求时,线程池将无法满足服务要求而导致请求失败。较高的min-spare值可能会导致系统响应时间变慢,因为它会创建大量线程来处理请求,这可能会占用过多的CPU和内存资源。如果将min-spare值设置得太低,则线程池可能无法及时响应请求。当系统负载较高时,有些请求可能会被暂时挂起,等待线程变得可用。如果没有足够的空闲线程,则请求将会等待更长时间。设置较高的min-spare值会占用更多的内存资源。如果线程池中的线程数超出了系统的实际需求,则会浪费内存资源。因此,将min-spare值设置为10至20是一种平衡内存和线程利用率的方式。
      min-spare: 20
      # 最大连接数,默认大小是8192。表示Tomcat可以处理的最大请求数量,超过8192的请求就会被放入到等待队列。如果设置为-1,则禁用maxconnections功能,表示不限制tomcat容器的连接数。建议设置为 2 倍到 4 倍的 QPS。如果设置的值太低,将会限制服务器处理客户端请求的能力,从而可能导致应用程序出现性能问题。如果设置的值太高,则会浪费服务器资源,因为服务器的处理能力可能不足以处理所有的连接。通过经验和测试,2到4倍的QPS值通常会在服务器处理客户端请求时提供最佳性能和稳定性。这个范围也会提供一定的缓冲以应对突发流量,从而在服务器资源短缺时避免过载。
    max-connections: 6667
    # 等待队列的长度,默认大小是100。建议设置为 2 至 5 倍的 max-connections。将accept-count设置为2至5倍的max-connections可以确保Tomcat能够处理足够的连接请求,同时避免因过多排队连接导致的性能问题。但是,设置过高的accept-count会增加系统负担和内存压力,同时也可能会引起其他问题,如拒绝服务攻击等。至于为什么建议不超过5倍,是因为实际上超过这个范围的设置已经很少能带来明显的性能提升,反而会增加系统负担。同时,设置过高的accept-count还可能会导致频繁的连接请求失败和性能下降,甚至可能会导致Tomcat崩溃。
    accept-count: 13334

🎉 2. 配置压缩

Spring Boot使用内嵌的Tomcat作为其默认的Web容器,支持HTTP协议下的数据压缩。

要启用数据压缩,需要在application.properties文件中添加以下配置:

server.compression.enabled=true
server.compression.mime-types=application/json,application/xml,text/html,text/xml,text/plain
server.compression.min-response-size=2048

解释一下每一个配置项的含义:

  • server.compression.enabled:启用数据压缩,默认为false。
  • server.compression.mime-types:需要压缩的数据类型列表,支持多个值,用逗号分隔。
  • server.compression.min-response-size:响应数据的最小大小(字节),只有响应数据大小超过该值才会进行压缩。

配置完成后,当客户端请求的Accept-Encoding头中包含“gzip”或“deflate”时,Tomcat会自动压缩响应数据并返回。

需要注意的是,如果使用了反向代理服务器(如Nginx),则需要确保代理服务器不会重复压缩响应数据,否则可能会导致网页无法正确加载。可以通过设置代理服务器的“proxy_set_header Accept-Encoding ”和“proxy_set_header TE ”选项来解决该问题。

🎉 3. 配置缓存

Spring Boot的默认配置会自动将静态资源缓存一段时间,并指定缓存路径。默认情况下,静态资源的缓存时间是1小时(3600秒),缓存路径为“/static/”和“/public/” 。

如果需要自定义静态资源的缓存配置,可以在application.properties中添加如下配置:

# 🌟 配置静态资源缓存时间为10分钟
spring.resources.cache.cachecontrol.max-age=600
# 🌟 配置缓存路径
spring.resources.static-locations=classpath:/static/,classpath:/public/

在上述配置中,通过spring.resources.cache.cachecontrol.max-age可以配置缓存时间,单位为秒;通过spring.resources.static-locations可以配置缓存路径。在配置路径时,需要指定静态资源存放的位置,多个位置可以使用逗号分隔。

需要注意的是,如果静态资源名带有版本号或者时间戳等动态变化的参数,那么缓存路径需要指定到该参数前面的部分,否则可能会导致缓存无效。

🌟 四、线程池配置

在高并发场景下,线程池的配置也是非常重要的,可以大大提高系统的并发处理能力。

Spring Boot默认使用Tomcat线程池,它提供了以下参数可以进行调整:

(1)最大工作线程数(maxThreads):表示Tomcat可以处理的并发请求数量,超过最大线程数的请求将会被拒绝。可以根据预期并发请求量进行调整,建议设置为CPU核心数量的2~4倍。

(2)最小工作线程数(minSpareThreads):表示Tomcat最少保持的空闲工作线程。可以根据预期并发请求量进行调整,建议设置为CPU核心数量。

(3)最大连接数(maxConnections):表示Tomcat可以处理的最大请求数量,超过最大连接数的请求将会被放入等待队列。可以根据预期并发请求量进行调整,建议设置为maxThreads的2~4倍。

(4)等待队列长度(acceptCount):表示Tomcat等待队列的长度,超过等待队列长度的请求将会被拒绝。可以根据预期并发请求量进行调整,建议设置为maxConnections的2~4倍。

# 🌟 server配置
server:
  compression:
    # 启用数据压缩,默认为false。配置完成后,当客户端请求的Accept-Encoding头中包含“gzip”或“deflate”时,Tomcat会自动压缩响应数据并返回。
    enabled: true
    # 需要压缩的数据类型列表,支持多个值,用逗号分隔。
    mime-types: application/json,application/xml,text/html,text/xml,text/plain
    # 响应数据的最小大小(字节),只有响应数据大小超过该值才会进行压缩。
    min-response-size: 2048
  # 服务端口
  port: 8097
  tomcat:
    # 1核2g内存为200,线程数经验值200;4核8g内存,线程数经验值800,以此类推
    threads:
      # 最多的工作线程数,默认大小是200。该参数相当于临时工,如果并发请求的数量在10到200之间,就会使用这些临时工线程进行处理。建议设置为 2 倍到 4 倍的 QPS
      max: 6667
      # 最少的工作线程数,默认大小是10。该参数相当于长期工,如果并发请求的数量达不到10,就会依次使用这几个线程去处理请求。如果min-spare设置得太低,那么当应用程序接收到高并发请求时,线程池将无法满足服务要求而导致请求失败。较高的min-spare值可能会导致系统响应时间变慢,因为它会创建大量线程来处理请求,这可能会占用过多的CPU和内存资源。如果将min-spare值设置得太低,则线程池可能无法及时响应请求。当系统负载较高时,有些请求可能会被暂时挂起,等待线程变得可用。如果没有足够的空闲线程,则请求将会等待更长时间。设置较高的min-spare值会占用更多的内存资源。如果线程池中的线程数超出了系统的实际需求,则会浪费内存资源。因此,将min-spare值设置为10至20是一种平衡内存和线程利用率的方式。
      min-spare: 20
      # 最大连接数,默认大小是8192。表示Tomcat可以处理的最大请求数量,超过8192的请求就会被放入到等待队列。如果设置为-1,则禁用maxconnections功能,表示不限制tomcat容器的连接数。建议设置为 2 倍到 4 倍的 QPS。如果设置的值太低,将会限制服务器处理客户端请求的能力,从而可能导致应用程序出现性能问题。如果设置的值太高,则会浪费服务器资源,因为服务器的处理能力可能不足以处理所有的连接。通过经验和测试,2到4倍的QPS值通常会在服务器处理客户端请求时提供最佳性能和稳定性。这个范围也会提供一定的缓冲以应对突发流量,从而在服务器资源短缺时避免过载。
    max-connections: 6667
    # 等待队列的长度,默认大小是100。建议设置为 2 至 5 倍的 max-connections。将accept-count设置为2至5倍的max-connections可以确保Tomcat能够处理足够的连接请求,同时避免因过多排队连接导致的性能问题。但是,设置过高的accept-count会增加系统负担和内存压力,同时也可能会引起其他问题,如拒绝服务攻击等。至于为什么建议不超过5倍,是因为实际上超过这个范围的设置已经很少能带来明显的性能提升,反而会增加系统负担。同时,设置过高的accept-count还可能会导致频繁的连接请求失败和性能下降,甚至可能会导致Tomcat崩溃。
    accept-count: 13334
# 🌟 mybatis配置
mybatis:
  configuration:
    # 日志输出实现使用stdoutImpl
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    # 启用下划线转驼峰
    map-underscore-to-camel-case: true
# 🌟 mybatis-plus配置
mybatis-plus:
  # mapper文件所在路径
  mapper-locations: classpath*:/mapper/*.xml
  # 实体类所在包路径
  typeAliasesPackage: com.example.redpacketrain.model
  global-config:
    # 数据库表字段名转换为驼峰命名
    db-column-underline: true
    # 字段插入策略,填充器顺序执行
    field-strategy: 1
    # ID类型 0:"数据库ID自增",1:"用户输入ID",2:"全局唯一ID(UUID)"
    id-type: 0
# 🌟 actuator暴露端点配置
management:
  endpoints:
    web:
      exposure:
        # 包含所有端点
        include: '*'
# 🌟 spring配置
spring:
  profiles:
    # 配置文件的前缀,默认是application.name的值,如果配了prefix,就取prefix的值。开发环境dev,测试环境test,生产环境prod。
    # nacos会根据当前环境去拼接配置名称查找相应配置文件,示例:{spring.application.name}-{spring.profiles.active}-{spring.cloud.nacos.config.file-extension},获取到值:nacos-config-dev.yml
    active: dev
  application:
    # 配置应用的名称,用于获取配置
    name: red-packet-rain
  jackson:
    # 日期格式
    date-format: yyyy-MM-dd HH:mm:ss
    # 时区
    time-zone: GMT+8
  main:
    # 允许覆盖bean定义
    allow-bean-definition-overriding: true
  devtools:
    restart:
      # 启用自动重启
      enable: true
  redis:
    # 数据库
    database: 0
    # 主机地址
    host: r-uf63c2kc5bhsl6sw94pd.tairpdb.rds.aliyuncs.com
    # 密码
    password: 2023@Liao
    # 端口
    port: 6379
    timeout: 60000
  datasource:
    # 数据库驱动
    driver-class-name: com.mysql.jdbc.Driver
    # 用户名
    username: root
    # 密码
    password: 2023@Liao
    # 数据库连接地址
    url: jdbc:mysql://rm-uf6613ss8xgiqpdkiao.mysql.rds.aliyuncs.com:3306/red-packet-rain?characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=GMT%2B8
    # 初始连接数
    initial-size: 100
    # 最大连接数
    max-active: 300
    # 最小空闲连接数
    min-idle: 100
    # 最长等待时间
    max-wait: 60000
    # 连接池配置
    pool-prepared-statements: true # 启用预编译语句池
    max-pool-prepared-statement-per-connection-size: 20 # 每个连接的预编译语句数
    time-between-eviction-runs-millis: 60000 # 检查需要关闭的连接间隔毫秒数
    min-evictable-idle-time-millis: 300000 # 连接在池中最小生存时间
    test-while-idle: true  # 空闲连接是否在连接池被空闲连接回收器进行检测
    test-on-borrow: false # 申请连接时是否检测连接可用性
    test-on-return: false # 归还连接时是否检测连接可用性
    # Druid 监控配置
    stat-view-servlet:
      enabled: true # 启用监控
      url-pattern: /druid/* # 访问路径
    # 过滤器配置
    filter:
      stat:
        log-slow-sql: true # 开启慢 SQL 记录
        slow-sql-millis: 1000 # 慢 SQL 阈值
        merge-sql: false # 是否合并 SQL
      wall:
        config:
          multi-statement-allow: true # 是否允许多个 SQL 语句同时执行
  cloud:
    sentinel:
      transport:
        # 添加sentinel的控制台地址
        dashboard: 139.224.215.67:8080
    stream:
      default-binder: rocketmq #选择默认绑定器
      rocketmq:
        binder:
          transaction:
            producer:
              transactionalIdPrefix: tx- #事务ID的前缀,用于区分不同的应用
              corePoolSize: 5 #事务Producer线程池初始大小
              maxPoolSize: 10 #事务Producer线程池最大大小
          # RocketMQ的NameServer地址
          name-server: rmq-cn-uax3f2kxe03.cn-shanghai.rmq.aliyuncs.com:8080
          access-key: tAPs290605b36eJh
          secret-key: 08qWfJh5ZQ793h0U
      binders: #可以绑定多个消息中间件
        rocketmq: #表示定义的名称,用于binding整合 名字可以自定义 在此处配置要绑定的rocket的服务信息
          type: rocketmq
      bindings: # 服务的整合处理
        rocketmqOutput: # 通道名称
          # 消息发往的目的地,对应topic 在发送消息的配置里面,group是不用配置的
          destination: rocket-destination
          # 设置消息类型,本次为json,文本则设置“text/plain” 如果我们需要传输json的信息,那么在发送消息端需要设置content-type为json(其实可以不写,默认content-type就是json)
          content-type: application/json
          default-binder: rocketmq # 如果没设定,就使用default-binder默认的
          # 指定了消息分区的数量
          partitionCount: 2
          # 指定分区键的表达式规则,我们可以根据实际的输出消息规则来配置SpEL来生成合适的分区键;
          partition-key-expression: headers.id3
        rocketmqInput:
          # 消息发往的目的地,对应topic
          destination: rocket-destination
          # 设置消息类型,本次为json,如果是文本则设置“text/plain”
          content-type: application/json
          # 设置要绑定的消息服务的具体设置
          default-binder: rocketmq
          # 分组名称,在rocket当中其实就是交换机绑定的队列名称
          group: my-rocketmq-group
          consumer:
            # 初始/最少/空闲时消费者数量,默认为1
            concurrency: 2
            # 重试次数
            max-attempts: 3
            # 通过该参数开启消费者分区功能;
            partitioned: true
file:
  path: D://opt
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1月前
|
Java 数据库连接 Maven
springBoot:项目建立&配置修改&yaml的使用&resource 文件夹(二)
本文档介绍了如何创建一个基于Maven的项目,并配置阿里云仓库、数据库连接、端口号、自定义启动横幅及多环境配置等。同时,详细说明了如何使用YAML格式进行配置,以及如何处理静态资源和模板文件。文档还涵盖了Spring Boot项目的`application.properties`和`application.yaml`文件的配置方法,包括设置数据库驱动、URL、用户名、密码等关键信息,以及如何通过配置文件管理不同环境下的应用设置。
|
15天前
|
Java 应用服务中间件
SpringBoot获取项目文件的绝对路径和相对路径
SpringBoot获取项目文件的绝对路径和相对路径
53 1
SpringBoot获取项目文件的绝对路径和相对路径
|
5天前
|
存储 运维 安全
Spring运维之boot项目多环境(yaml 多文件 proerties)及分组管理与开发控制
通过以上措施,可以保证Spring Boot项目的配置管理在专业水准上,并且易于维护和管理,符合搜索引擎收录标准。
17 2
|
10天前
|
分布式计算 关系型数据库 MySQL
SpringBoot项目中mysql字段映射使用JSONObject和JSONArray类型
SpringBoot项目中mysql字段映射使用JSONObject和JSONArray类型 图像处理 光通信 分布式计算 算法语言 信息技术 计算机应用
32 8
|
15天前
|
缓存 监控 Java
|
1月前
|
JavaScript 前端开发 Java
解决跨域问题大集合:vue-cli项目 和 java/springboot(6种方式) 两端解决(完美解决)
这篇文章详细介绍了如何在前端Vue项目和后端Spring Boot项目中通过多种方式解决跨域问题。
340 1
解决跨域问题大集合:vue-cli项目 和 java/springboot(6种方式) 两端解决(完美解决)
|
17天前
|
JavaScript 前端开发 Java
SpringBoot项目的html页面使用axios进行get post请求
SpringBoot项目的html页面使用axios进行get post请求
40 2
|
17天前
|
前端开发 Java Spring
SpringBoot项目thymeleaf页面支持词条国际化切换
SpringBoot项目thymeleaf页面支持词条国际化切换
45 2
|
17天前
|
JSON Java 数据库
SpringBoot项目使用AOP及自定义注解保存操作日志
SpringBoot项目使用AOP及自定义注解保存操作日志
33 1
|
19天前
|
JavaScript Java 项目管理
Java毕设学习 基于SpringBoot + Vue 的医院管理系统 持续给大家寻找Java毕设学习项目(附源码)
基于SpringBoot + Vue的医院管理系统,涵盖医院、患者、挂号、药物、检查、病床、排班管理和数据分析等功能。开发工具为IDEA和HBuilder X,环境需配置jdk8、Node.js14、MySQL8。文末提供源码下载链接。

热门文章

最新文章