Spring Boot的并发编程

使用Spring Boot构建服务时,我们必须处理并发!通常有这样的误解:由于使用Servlet,而Servlet背后是一个线程池支持,线程池会为每个请求分配的新线程,请求之间不存在冲突,因此无需考虑并发性,本文提供一些关于处理Spring Boot中多线程处理的实用建议。 Spring Boot并发基础知识 在考虑Spring Boot应用程序中的并发性时,值得考虑的关键因素有: 最大线程数 - 这是为处理对应用程序的请求而分配的最大线程数 共享外部资源 - 调用外部共享资源(如数据库) 异步方法调用 - 这些是在等待响应时将线程释放回线程池的方法调用 共享内部资源 - 调用内部共享资源 - 例如高速缓存和可能共享的应用程序状态 我们会逐个检查,看看这些条件是如何影响我们使用Spring Boot编写应用程序的方式。 Spring Boot Application中的最大线程数 首先要注意的是,你正在处理有限数量的线程。 如果你使用Tomcat作为嵌入式服务器(默认),则可以使用属性server.tomcat.max-threads 来控制要允许的线程数。0为默认设置 - 表示使用Tomcat时默认值为200。 了解这一点很重要,因为你可能需要增加此数字以有效地使用提供服务的资源。特别是处理外部资源时也会出现问题...... 共享外部资源的问题 调用数据库和其他REST端点可能需要很长时间。 你正在处理的有限数量的线程意味着:你确实需要避免长时间运行,包括缓慢的同步请求,因为运行缓慢占据线程时间长,有限数量的线程会很快用光。如果你必须等待一些缓慢的过程来完成请求,那么意味着你可能无法充分利用服务器潜力。 如果你有许多等待响应的长时间运行的线程,你可能最终会遇到这样一种情况:真正快速、简单的请求反而需要等待很长时间,这些请求处于“永远等待”,当你发现它们时很奇怪,因为它们的运行时间并不长,怎么会被堵塞呢? 如何改进? 异步方法调用 一次请求做多件事通常会有所帮助,理想情况下,如果需要调用三种服务:服务A,服务B和服务C; 你不要这样做: 1.调用服务A. 2.等待服务A的响应 3.调用服务B 4.等待服务B的响应 5.调用服务C. 6.等待服务C的响应 7.组合A,B和C的响应并完成处理 如果每个服务调用需要3秒钟来响应,整个过程将需要9秒。按照下面步骤来做要好得多: 1.调用服务A. 2.调用服务B 3.调用服务C. 4.等待服务A,B和C的响应 5.组合A,B和C的响应并完成处理 在这种情况下,你可以在不等待请求全部完成的情况下进行三次调用,并假设服务A,B和C不相互依赖,三次调用并行进行,这样需要3秒钟就能响应。 异步和响应式微服务的想法本身就很有趣。建议使用Spring Boot2的WebFlux。 在Spring Boot中进行异步调用 如何在Spring Boot中启用异步方法调用?在应用入口类上使用@EnableAsync 注释,与@SpringBootApplication 注释一起使用。 启用后,可以在服务中使用@Async,这个服务返回CompletableFuture<>。因为之前使用了@EnableAsync ,所以这些@Async 方法将在后台线程池中运行。 充分利用异步执行,避免许多不必要的性能下降,使服务尽可能快速和响应。 共享内部资源 虽然前面章节提出的办法我们通常无法用来控制外部资源,但我们可以完全控制系统的内部资源。 意识到我们可以控制内部资源,避免发生与共享相关问题的最佳建议是不要共享它们! Spring服务和控制器默认为单例! 重要的是要意识到这一点并且要非常小心,在你的服务中存在可变状态的那一刻(banq注:只能把状态放在外部资源如数据库,在内部放置可变状态要小心,包括内部放置一个JDK的线程池,JDK的线程池也是一种可变状态,有启动 销毁等状态生命周期),你需要像在任何标准应用程序中那样处理它。 使用共享状态的其他潜在案例是高速缓存和自定义的服务器范围组件(通常是监视、安全性等方面)。 如果你绝对需要分享一些状态,下面是建议: 1. 处理不可变对象。 如果对象是不可变的,则可以避免许多与并发相关的问题。如果你需要改变一些东西 - 只需创建一个新对象。 2.了解你的集合Collection。并非所有集合都是线程安全的。 3. 不要假设第三方库是线程安全的。大多数都不是,并且必须控制对共享状态的访问。 4. 如果你要依赖它 - 学习正确的并发性编程。 总结 Spring中的并发和多线程是重要的主题。在本文中,主要强调在编写Spring Boot应用程序时需要注意的关键地方。如果你想成功构建高实时、高质量的服务,需要围绕这一主题做出有意识的决策和权衡。

原文发布于微信公众号 - Linyb极客之路(gh_c420b2cf6b47)

原文发表时间:2018-08-20

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏精讲JAVA

一文理解Netty模型架构

本文基于Netty4.1展开介绍相关理论模型,使用场景,基本组件、整体架构,知其然且知其所以然,希望给读者提供学习实践参考。

1572
来自专栏风中追风

分布式环境下的解决方案——分布式锁

锁是一个抽象的概念,锁的实现,需要依存于一个可以存储锁的空间。在多线程中是内存,在多进程中是内存或者磁盘。更重要的是,这个空间是可以被访问到的。多线程中,不同的...

3658
来自专栏Laoqi's Linux运维专列

Memcached基础了解

1163
来自专栏Vamei实验室

Linux进程间通信

我们在Linux信号基础中已经说明,信号可以看作一种粗糙的进程间通信(IPC, interprocess communication)的方式,用以向进程封闭的内...

27310
来自专栏Jackson0714

PHP内核之旅-1.生命周期

1252
来自专栏海说

Servlet/JSP

Servlet/JSP为Java EE中接收、转发、响应客户端请求的的技术,是基于Web容器所提供的服务。 Servlet与JSP关系 Servlet是使用Ja...

2050
来自专栏Android开发实战

android Ndk JNI 入门

相信很多人对于NDK 开发都是懵逼的,比如都知道把加密的逻辑以及密钥放在so文件中,但是你知道怎么生成so文件吗?你知道开发jni吗?你熟悉jni语法吗?怎么配...

1552
来自专栏小特工作室

Navi.Soft31.WinCE框架.开发手册(含下载地址)

1.概述 1.1应用场景 随着物联网的普及,越来越多的制造商对货品从原料配备,加工生产,销售出库等环节的要求和把控越来越高.在此情况之下,传统的ERP软件已经无...

1985
来自专栏Java架构师历程

ssh工作原理

1.通过Configuration().configure();读取并解析hibernate.cfg.xml配置文件

1423
来自专栏惨绿少年

用户与磁盘

第1章 linux文件属性相关 1.1 linux文件属性 1.2 磁盘的使用过程 1、磁盘(房子) 2、分区(划分隔断) 3、格式化创建文件系统(装修) 4、...

2740

扫码关注云+社区

领取腾讯云代金券