SpringBoot默认的内嵌容器是Tomcat,也就是我们的程序实际上是运行在Tomcat里的。所以与其说SpringBoot可以处理多少请求,到不如说Tomcat可以处理多少请求。

关于Tomcat的默认配置,都在spring-configuration-metadata.json文件中,对应的配置类则是org.springframework.boot.autoconfigure.web.ServerProperties。

内嵌Tomcat配置

和处理请求数量相关的参数有四个:

server:
tomcat:
threads:
# 最少线程数,默认大小是10。该参数相当于长期工,如果并发请求的数量达不到10,就会依次使用这几个线程去处理请求。
min-spare: 10
# 最多线程数,默认大小是200。该参数相当于临时工,如果并发请求的数量在10到200之间,就会使用这些临时工线程进行处理。
max: 15
# 最大连接数,默认大小是8192。表示Tomcat可以处理的最大请求数量,超过8192的请求就会被放入到等待队列。
max-connections: 30
# 最大等待数,默认大小是100。
accept-count: 10

再来写一个简单的接口:

@GetMapping("/test")
public Response test1(HttpServletRequest request) throws Exception {
log.info("ip:{},线程:{}", request.getRemoteAddr(), Thread.currentThread().getName());
Thread.sleep(500);
return Response.buildSuccess();
}

如果并发请求数量低于server.tomcat.threads.max,则会被立即处理,超过的部分会先进行等待,如果数量超过max-connections与accept-count之和,则多余的部分则会被直接丢弃。

如何提升 Spring Boot 吞吐量?

  1. 增加内嵌 Tomcat 的最大连接数
  2. 异步执行
  3. 使用 @ComponentScan() 定位扫包
    • 使用 @ComponentScan() 定位扫包比 @SpringBootApplication 扫包更快。
  4. 默认 Tomcat 容器改为 Undertow
    • 默认 Tomcat 容器改为 Undertow(Jboss 下的服务器,Tomcat 吞吐量 5000,Undertow 吞吐量 8000)
  5. 使用 BufferedWriter 进行缓冲
  6. Deferred 方式实现异步调用
  7. 异步调用可以使用 AsyncHandlerInterceptor 进行拦截

延伸:并发问题是如何产生的?

到目前为止,就已经搞明白了SpringBoot可以同时处理多少请求的问题。但是在这里我还想基于上面的例子再延伸一下,就是为什么并发场景下会出现一些值和我们预期的不一样?

Spring容器中的Bean默认是单例的,也就是说,处理请求的Controller、Service实例就只有一份。

在并发场景下,将cookSum定义为全局变量,是所有线程共享的,当一个线程读到了cookSum=29,同时另两个线程也读到是29,三个线程都加1后写回,最终cookSum都变成了30。

private int cookSum = 0;

@GetMapping("/test")
public Response test1(HttpServletRequest request) throws Exception {
cookSum += 1;
log.info("做了{}道菜", cookSum);
Thread.sleep(500);
return Response.buildSuccess();
}

如何处理并发问题?

通常我们说的并发:指的是多个线程操作相同的资源,如何保护线程安全,合理的使用资源。

对于一些用户请求,在某些情况下是可能重复发送的,如果是查询类操作并无大碍,但其中有些是涉及写入操作的,一旦重复了,可能会导致很严重的后果,例如交易的接口如果重复请求可能会重复下单。

重复请求的场景有可能是:

  1. 黑客拦截了请求,重放
  2. 前端/客户端因为某些原因请求重复发送了,或者用户在很短的时间内重复点击了。
  3. 网关重发
  4. 网络通信异常或者后端响应慢

    ...

解决方案:

  1. 利用唯一请求编号去重(每次请求,服务端返回客户端一个唯一编号,客户端拿着这个唯一编号去请求)
  2. 业务参数做一个摘要去重(用用户ID、请求URL、请求参数等算一个key,然后MD5(key)来作唯一参数)
  3. 让前端来限制,点击之后,在一定时间内不能再次点击。
  4. 请求去重工具类,Java实现

如何保证并发的安全?

Controller默认是单例的,单例是不安全的,会导致属性重复使用。

  1. 不要在controller中定义成员变量。
  2. 万一必须要定义一个非静态成员变量时候,则通过注解@Scope(“prototype”),将其设置为多例模式。
  3. 在Controller中使用ThreadLocal变量

如何处理高并发问题?

高并发就是通过严谨的设计来保证系统能够同时并行处理很多的请求。

也就是说系统能够在某一时间段内提供很多请求,但是不会影响系统的性能。

通常我们说的高并发:指的是系统运行过程中,短时间内遇到大量的操作请求的情况。如12306的抢票等,这时候,系统会执行大量的操作(数据库操作,资源请求等),如何处理高并发场景?

在提升系统性能方面我们一直关注的是系统的查询性能,通过数据库的分布式改造,各类缓存的原理和使用技巧。究其原因在于我们遇到的大部分场景都是读多写少,尤其是在一个系统的初级阶段。

高并发(写)请求的场景,其中《秒杀抢购》就是最典型的场景。

提供以下两种解决方案:

  • 使用锁的方式,比如分布式锁,也可以利用redis本身操作原子性的特点
  • 写入消息队列,在消息队列中做减库存的操作,做异步校验

在用户下单的时候,用了redis的原子性减库存,如果不支付,一般可以设置一个定时器,定时器时间一到,就把库存加上,同时定义订单失败。

比如1000件商品,系统生成1000个令牌,拿到令牌的用户可以进入消息队列,其他未拿到令牌的直接返回已抢完。

1、一般对于并发处理都需要加锁,否则会导致共享变量不可见问题,尽量将锁的力度变小。

2、如果确认不能或不想加锁,则做串行化处理,解决方案就是消息队列。

高并发量网站解决方案

  1. 尽量使用缓存,包括用户缓存,信息缓存等,多花点内存来做缓存,可以大量减少与数据库的交互,提高性能。
  2. 用jprofiler等工具找出性能瓶颈,减少额外的开销。
  3. 优化数据库查询语句,减少直接使用hibernate等工具的直接生成语句(仅耗时较长的查询做优化)。
  4. 优化数据库结构,多做索引,提高查询效率。
  5. 统计的功能尽量做缓存,或按每天一统计或定时统计相关报表,避免需要时进行统计的功能。
  6. 能使用静态页面的地方尽量使用,减少容器的解析(尽量将动态内容生成静态html来显示)。
  7. 解决以上问题后,使用服务器集群来解决单台的瓶颈问题。

高并发的的瓶颈在哪里?

  1. 可能是服务器网络带宽不够(可以增加网络带宽,DNS域名解析分发多台服务器。)
  2. 可能web线程连接数不够(负载均衡,前置代理服务器nginx、apache等等)
  3. 可能数据库连接查询上不去(数据库查询优化,读写分离,分表等等)

如果有高访问,高并发的需求,就尽量别用java来做。

java不适合做这种方面的工作,它在web上的用途更多是用来做行业性软件开发,对讲求效率方面的网站性工作不太适合。如果非要用java做的话可以考虑以下几个思路:

  1. 调优;
  2. 采用集群模式布署;
  3. 写好网站的程序;
  4. 不要做实时性要求比较高的工作,降低对严谨性方面的要求。

SpringBoot能同时处理多少请求的更多相关文章

  1. SpringBoot学习笔记(七):SpringBoot使用AOP统一处理请求日志、SpringBoot定时任务@Scheduled、SpringBoot异步调用Async、自定义参数

    SpringBoot使用AOP统一处理请求日志 这里就提到了我们Spring当中的AOP,也就是面向切面编程,今天我们使用AOP去对我们的所有请求进行一个统一处理.首先在pom.xml中引入我们需要的 ...

  2. SpringBoot 拦截器获取http请求参数

    SpringBoot 拦截器获取http请求参数-- 所有骚操作基础 目录 SpringBoot 拦截器获取http请求参数-- 所有骚操作基础 获取http请求参数是一种刚需 定义拦截器获取请求 为 ...

  3. Springboot 配置 ssl 实现HTTPS 请求 & Tomcat配置SSL支持https请求

    SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议.TLS与 ...

  4. SpringBoot设置支持跨域请求

    跨域:现代浏览器出全的考虑,在http/https请求时必须遵守同源策略,否则即使跨域的http/https 请求,默认情况下是被禁止的,ip(域名)不同.或者端口不同.协议不同(比如http.htt ...

  5. SpringBoot 基于web应用开发(请求参数获取,静态资源,webjars)

    SpringBoot 基于web应用开发 一.Lombok使用 1.导入依赖库 <dependency>    <groupId>org.projectlombok</g ...

  6. Springboot跨域 ajax jsonp请求

    SpringBoot配置: <dependency> <groupId>org.springframework.boot</groupId> <artifac ...

  7. springboot——发送put、delete请求

    在springmvc中我们要发送put和delete请求,需要先配置一个过滤器HiddenHttpMethodFilter,而springboot中,已经帮我们自动配置了,所以我们可以不用配置这个过滤 ...

  8. SpringBoot项目启动后再请求远程接口的实现方式

    场景 有一个SpringBoot项目需要在启动后请求另一个远程服务拿取配置,而不是加载过程中去请求,可能会出现类没有实例化的场景,因此需要实现项目完全启动后再进行请求的场景. 解决 一般会有两种实现方 ...

  9. springboot Aop 统一处理Web请求日志

    1.增加依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...

  10. springboot 接收post和get请求

    接收post请求: @RequestMapping(value = "/api/v1/create_info", method = RequestMethod.POST) publ ...

随机推荐

  1. 2019年最新前端面试题,js程序设计题

    都说机会是留给有准备的人的. 一年之计在于春,面对众多的前端技术,需要时刻充电自己. 我现在整理一些前端js面试程序题. 1.判断一个字符串中出现最多的字符,并计算出现的次数? 2.用css伪类实现下 ...

  2. 使用DP-Modeler、ModelFun模方软件修复实景三维模型教程

    P-Modeler   DP-Modeler是武汉天际航自主研发的一款集精细化单体建模与Mesh网格模型修饰于一体的软件.支持三维模型一键水面修复.道路置平.建筑局部修饰.删除底部碎片.植被处理.桥隧 ...

  3. 记录一次uniapp使用scrollview

    在uni-app框架下,使用scroll-view进行下拉加载时,不要设置 scroll-top 或者 scroll-left 否则会出现,页面抖动的情况

  4. UE4 C++调用手柄震动

    近期封装输入相关逻辑,简单归纳下. 蓝图实现 内容界面右键Miscellaneous->Force Feedback Effect,创建力反馈对象并填写相关参数: 然后在蓝图中用Spawn Fo ...

  5. 5GC 系统架构

    目录 文章目录 目录 前文列表 4G/5G 核心网对比 4G/5G 核心网融合架构 5GC 架构 AMF 功能 SMF 功能 NSSF 功能 UPF 功能 AF.PCF & NEF 功能 BS ...

  6. 深入Django项目实战与最佳实践

    title: 深入Django项目实战与最佳实践 date: 2024/5/19 21:41:38 updated: 2024/5/19 21:41:38 categories: 后端开发 tags: ...

  7. spring boot整合maybatis plus 的 文件生成代码

    /** * 代码生成 */public class AutoGenerator_ { public static void main(String[] args) { AutoGenerator ge ...

  8. C# npoi追加写入时报错 因为文件格式或文件扩展名无效。

    造成原因:workbook对象打开后,没有手动close造成的. 使用的npoi版本:2.6.0 ,环境 win10 .net core 5.0    

  9. C# 炸弹人 winform版

    实现这个游戏的基本功能包含几个对象:玩家,怪物,墙砖,炸弹,通关的门.玩家通过上下左右方向键移动,放置炸弹,被怪物杀死,被炸弹炸死.怪物随机方向移动,能杀死玩家.炸弹有爆炸功能,炸弹的火花长度.通过的 ...

  10. Go post重定向的两种方式

    1.Location 2.http.Redirect 代码 /index -> /login -> /home package main import ( "fmt" ...