代码人生

Spring Boot中的并发性问题

代码人生 http://www.she9.com 2018-06-23 10:17 出处:网络 编辑:@技术狂热粉
在使用SpringBoot构建服务时,我们必须处理并发性。有一种误解认为,由于使用servlet并为每个请求分配一个新的线程,所以不需要考虑并发性。在本文中,我将给出一些关于在SpringBoot中处理多线程的实用建议,以及如


Spring Boot中的并发性问题


在使用Spring Boot构建服务时,我们必须处理并发性。有一种误解认为,由于使用servlet并为每个请求分配一个新的线程,所以不需要考虑并发性。在本文中,我将给出一些关于在Spring Boot中处理多线程的实用建议,以及如何避免它可能产生的问题。


Spring Boot并发性基础


在考虑Spring Boot应用程序中的并发性时,需要考虑的关键领域是:


最大线程数——这是分配给应用程序请求的最大线程数。


共享外部资源——对外部共享资源(如数据库)的调用


异步方法调用——这些方法调用在等待响应时将线程释放回线程池


共享的内部资源——调用内部共享资源——比如缓存和应用程序状态共享


我们将逐一研究它们,看看它们如何影响我们使用Spring Boot编写应用程序的方式。


1、Spring Boot应用程序中线程的最大数量


首先要注意的是,您正在处理的线程数量是有限制的。


如果您使用Tomcat作为您的嵌入式服务器(默认),那么您可以使用server.tomcat.max-threads 属性控制要允许的最大线程数。默认设置为0,即使用Tomcat中的默认值200。


了解这一点很重要,因为您可能需要扩展这个数字,以便有效地使用服务提供的资源。当处理外部资源时,它也会变得有问题……


2、共享外部资源的问题


调用数据库和其他REST EndPoint需要花费大量时间。


您正在处理的线程数量有限,这意味着您真的希望避免长时间运行的、缓慢的、同步的请求。如果您正在等待一些缓慢的进程来完成并保持线程,那么您可能没有充分利用您的服务器。


如果您有许多长时间运行的线程在等待响应,那么您可能最终会遇到这样的情况:真正快速的、简单的请求正在等待很长时间,“永远等待”的请求终止。


如何改进这一点?

3、异步方法调用


同时请求多个东西也是很有帮助的。理想情况下,如果您需要调用三个服务:服务A、服务B和服务C;你不想那样做:


调用服务A


等待来自服务A的响应


调用服务B


等待B服务的响应


调用服务C


等待服务C的响应


编写来自A、B和C的响应,完成处理


如果每个服务响应时间为3秒,那么整个过程将花费9秒。

最好做到以下几点:


调用服务A


调用服务B


C调用服务


等待服务A、B和C的响应


编写来自A、B和C的响应,完成处理


在这种情况下,您不需要等待完成就可以进行三次调用,并且假设服务A、B和C不是相互依赖的,响应需要3秒。


异步和反应性微服务的概念本身就很有趣。我建议检查:

这些都很吸引人,但是我们在本文中关注Spring Boot…


4、在Spring引导中进行异步调用


如何在Spring引导中启用异步方法调用?您希望在@SpringBootApplication注释下的应用程序类上从@EnableAsync注释开始。


启用此功能后,可以在返回CompletableFuture<>的服务中使用@Async注释。因为您有@EnableAsync,所以@Async方法将在后台线程池中运行。


如果您充分利用了异步执行,您将避免许多不必要的性能下降,使您的服务尽可能快速和响应。


对于在Spring Boot中实现这个功能,我建议您从官方Spring网站上查看这个示例。


https://spring.io/guides/gs/async-method/


5、内部资源共享


虽然前几节讨论的是我们通常无法控制的东西——外部资源,但我们完全控制了系统的内部资源。


知道我们控制了内部资源,最好的建议是避免与共享资源相关的问题,不要共享它们!


Spring服务和控制器默认是单例的。意识到这一点并非常小心是很重要的。当服务中出现可变状态时,您需要像处理任何标准应用程序那样处理它。


共享状态的其他潜在来源是缓存和自定义、服务器范围的组件(通常是监视、安全等)。


如果你绝对需要分享一些状态,以下是我的建议:


(一)、处理不可变对象。如果对象是不可变的,则可以避免许多与并发相关的问题。如果你需要改变一些东西——只需创建一个新的对象。


(二)、了解你用的集合对象。并非所有集合都是线程安全的。一个常见的陷阱是使用HashMap假设它是线程安全的(不是)。如果需要并发访问,可以使用HashTable代替。


 (三)、不要假设第三方库是线程安全的。大多数代码不是,必须控制对共享状态的访问。


 (四)如果你确实需要——学习并发性的相关知识。我建议在读一下《 Java Concurrency in Practice》这本书。尽管写于2006年,但在2018年仍然很有用。


总结


Spring中的并发性和多线程是非常重要的主题。在本文中,我想强调在编写SpringBoot应用程序时需要注意的关键领域。如果您希望在构建高需求、高质量的服务时获得成功,您需要围绕这个主题做出有意识的决策和权衡。

我希望通过这篇文章让你知道如何开始。



请关注公众号:程序你好
0

精彩评论

暂无评论...
验证码 换一张
取 消