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. Gin框架

    目录 gin的参数获取 header参数 post Raw json 请求示例 gin的参数获取 package main import ( "fmt" "github. ...

  2. 安装assimp失败

    使用Cmake和Visual Studio编译assimp成功(包括Debug和Release),并且安装Release版本也成功,但安装debug版本失败,安装输出信息如下: 通过提示找到脚本文件, ...

  3. NASM语法

    NASM汇编语言的语法很简单,由4部分组成: label:instruction operands; comment 这4部分都是可选的.一条语句可以没有label,没有comment,甚至连inst ...

  4. CSS——引入方式

    1.行内式 <div style="color: white;background-color: #369;text-align: center">行内设置</d ...

  5. 莫烦tensorflow学习记录 (1)session会话控制、variable变量、placeholder传入值

    https://mofanpy.com/tutorials/machine-learning/tensorflow/session/ Session 会话控制 #https://mofanpy.com ...

  6. 对于UITableView和UIImageView的DrawRect重写之后的影响

    一.继承 UITableView和UIImageView , 重写 DrawRect 方法,然后里面留空 ImageView @implementation DrawImageView - (void ...

  7. 《剑指offer - 题目1》

    题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数 ...

  8. 8.5考试总结(NOIP模拟31)[Game·Time·Cover]

    我们总是在注意错过太多,却不注意自己拥有多少. 前言 考场上疯狂搞第一题,终于把人给搞没了.. T1 Game 解题思路 线段树+二分 总体来讲就是用线段树维护三个值: 没有产生贡献的 a(小 B 的 ...

  9. mac m1使用docker安装oracle

    mac m1使用docker安装oracle数据库 本学期开始学习数据库原理,老师课上讲到课堂作业使用的是oracle 11g,然而我去官网却发现只有Windows和Linux版本的,并没有发现mac ...

  10. wireshark常见使用技巧

    (1)wireshark根据报文不同字段排序 举例说明:现在有50000个1588 sync报文,我想根据报文的originalTimestamp(seconds)字段进行排序,该如何操作呢? 操作过 ...