导读:
什么是线程池?当我们使用微博,举个例子,世界杯梅西成功闯入了决赛,离封王只有一步之遥。这个可以达到每秒几十万的请求量的级别的高并发,我们往往单个服务器是扛不住的,如果加服务器又花费很高的成本,有没有简单更好的方法去降低成本实现功能?
当多个客户对某一网站进行请求访问,呈现多个用户去竞争同一个线程资源,如果队列中已经没有了存储空间,此时如何去控制线程池开辟线程来缓冲多请求的并发情况?
这些都是我们本编博客的核心内容。接下来我们开始详解。
一、线程池
线程池是什么?我的理解就是:线程池就是用来管理线程和分配资源的。
这个怎么理解?举个例子,如下图所示
现在有一定量客户进行请求,每一个请求都会放在任务队列中存储等待线程,而线程池中的任务队列就会起到缓存的作用,一方面用来处理多请求,另一方面可以去开辟更多的线程去处理任务。实际上我们都会把控住客户的请求以至于控制时间在一定范围内,如果请求时间过长,会让客户的体验大大降低,丢失客流量。但是又不能够时刻开辟大量线程去干等客户的请求,这样做会大大的增加服务器的内存负担,也会损耗性能、服务器奔溃等等不利情况。所以线程池的作用就是为了让我们平衡客户的请求和自身的成本之间的存在,不但能满足多用户的高并发请求,更能控制好自己的成本条件,增加效率。
1. 线程池中存在最大线程数和最小线程数。ThreadPoolExecutor类提供了两个参数:maximumPoolSize 和corePoolSize。最大线程数(maximumPoolSize ):就是为了防止高并发的存在,让客户不延迟请求,始终达到规定时间内进行无缝连接,在同一时间内,最大开辟的线程数量(特殊时期)。最小线程数(corePoolSize):一直存活,高并发过后线程销毁始终不会减少到为0,存在最小线程来执行客户的请求(平常时期)。
2. 那么什么是任务队列呢?任务队列究竟设置多长呢?它是有界还是无界的呢?
当然,队列的长度不能过大,如果过大则会客户请求延迟时间过长,客户体验差。短队列,类似于tomcat和数据库对响应要求不高。长队列,进行大量的数据请求访问,类似于爬虫和大数据技术。所以可以说,在队列的长度要求上究竟是建立多少的都会根据业务场景来进行设计,而不是盲目设计的。当任务队列满的时候就会请求最大线程数,开辟新线程去执行请求。
为什么这样设计呢?
在线程申请内存和销毁线程的过程中,内存占用率一下子就会飙到很高,如果不加以限制几乎所有的内存都用来开辟和销毁了,系统很容易就奔溃而导致down机。大家如果装有java可以查看jvm监视内存和cpu使用情况,就会发现实际上在程序在线程的创建和销毁过程中内存是被使用的,一旦线程的数量达到一个最大值,就会把内存所有空间都占用掉了,就会出现无法在进行操作的情况。这个大家可以有兴趣去研究一下。
二、分布式集群架构
(1)什么是分布式?
分布式就是让不同的服务器做不同的任务,如nginx的负载均衡。分布式能够很好的让服务器去执行不同的任务,不再是一台服务器承担多任务,这个完全可以降低单一服务器的承载压力,同时也提高了效率和降低了成本。
(2)什么是集群?
集群就是让不同的服务器去做相同的任务,我们在使用多服务器的环境的时候,通常可以把多服务器看成一个组,就像一个整体的大型服务器,实际上服务器内部是成千上万的服务器搭建而成,这个就是服务器集群。
下面是结合分布式和集群的系统架构。
现在模拟一个高并发情况,有一个每秒100W的高并发,通过DNF域名系统进行访问请求,突破防火墙的限制后能够直接的通过nginx分发给服务器集群中的不同的服务器。