关注分享主机优惠活动
国内外VPS云服务器

tomcat集群监控和弹性扩展详解

如何为tomcat配置合适的线程池分为CPU密集型和IO密集型任务。

对于CPU密集型的应用,需要大量的CPU,运算速度非常快。如果线程池太多,保存和切换上下文的开销会太高,影响性能。可以适当减少线程数量。

IO密集型应用常见于常见的业务系统,如查询mysql、redis等。,然后在内存中进行简单的数据组装和逻辑判断。这时候因为epoll,dma等的支持。,耗时长的线程不会长时间占用CPU时间,所以可以适当增加线程数量。

关于线程数应该有多大,网上有很多方案。

tomcat集群监控和弹性扩展详解-主机频道

在实际情况下,我们使用wrk等压力测量工具进行压力测量。具有相对复杂的压力测量逻辑和相对高的请求量的接口首先被配置为相对保守的值。

第一,估计目前接口处理平均需要300MS,1S一个线程平均处理3个请求,最多100个线程1S可以处理300个TPS。

粗略估计每个请求将消耗多少内容空间。如果是2KB,每秒将消耗600KB来估计触发YGC的频率。假设年轻一代是1GB,大约29分钟就会触发YGC。

然后看100个线程连续处理300TPS时的CPU消耗。

每隔几分钟观察一次内存GC,或者CPU利用率稳定在50%左右,假设此时线程池中的70个线程都在运行。

然后监控系统采集到线程池的线程利用率达到80%开始扩展。由于扩展可能需要1-2分钟来启动新服务器并提供服务,因此有必要预留服务器资源来处理灵活扩展期间的流量。

实际场景相对复杂,最好在前期设定一个相对保守的扩展阈值。如果在达到这个阈值之前发现服务器撑不住,可以实时降低阈值。

同时,我们还可以观察达到容量阈值时的真实在线CPU和内存使用情况,并基于Prometheus+grafana进行监控。如果扩容时CPU使用率和内存使用率的GC评估率较低,我们可以重新配置中心,动态调整线程池的大小。

所以与其找一个准确的配置方式来计算线程池的数量,不如提供一个可以动态调整的线程池作为tomcat的线程池。

如何监控tomcat线程池的工作状态spring boot在启动时会调用Tomcat ProtocolHandlerController的实现类。在这里,您可以自定义tomcat线程池或获取Tomcat线程池。

公共类MyTomcatProtocolHandlerCustomizer实现TomcatProtocolHandlerCustomizer & lt;ProtocolHandler >{ private final ThreadPoolExecutor tomcatThreadPoolExecutor;public TomcatProtocolHandlerCustomizer(ThreadPoolExecutor tomcatThreadPoolExecutor){ this . tomcatThreadPoolExecutor = tomcatThreadPoolExecutor;} @ Override public void customize(protocol handler protocol handler){ protocol handler . set executor(tomcatThreadPoolExecutor);} public ThreadPoolExecutor getThreadPoolExecutor(){ return tomcatThreadPoolExecutor;}}然后将线程池加载到容器bean中,并在promethues monitoring中注册它。每秒收集时,回调获取线程池的最新指标。

Promethues每秒收集一次容器的线程池运行指标和服务器测得的CPU利用率。当达到定义的容量扩展阈值时,将启动新的POD。

Grafana每秒收集promethues的数据聚合图标显示。

@ bean public AllServersThreadPoolCollector AllServersThreadPoolCollector(@ Qualifier(value = " GrpcThreadPoolExecutor ")ThreadPoolExecutor,@ Qualifier(value = " jdTomcatThreadPoolExecutor ")org . Apache . Tomcat . util . threads . ThreadPoolExecutor TomcatThreadPoolExecutor,meter registry){ return new AllServersThreadPoolCollector(GrpcThreadPoolExecutor,jdTomcatThreadPoolExecutor,registry);} public void init(){ try { create gauge(this," grpc_tomcat_core_pool_size ",pool -& amp;gt;this . getcorepoolsize());createGauge(this," grpc_tomcat_maximum_pool_size ",pool -& amp;gt;this . getmaximumpoolsize());createGauge(this," grpc_tomcat_busy_pool_size ",pool -& amp;gt;this . getactivecount());createGauge(this," grpc_tomcat_wait_queue_size ",pool -& amp;gt;this . getwaitqueuesize());} catch (Exception e) {log.error("未能注册所有服务器监控",e);} } private void create gauge(AllServersThreadPoolCollector weak ref,String metric,ToDoubleFunction & amplt;AllServersThreadPoolCollector & amp;gt;measure) { Gauge.builder(公制,weakRef,度量)。注册(this . registry);} public int getWaitQueueSize(){ return grpcthreadpoolexecutor . get queue()。size()+tomcatthreadpoolexecutor . get queue()。size();}

Tomcat线程池扩展和收缩Java线程池支持直接修改corePoolSize和maximumPoolSize。

修改后的corePoolSize(1)数量小于maximumPoolSize,并引发异常。

(2)如果corePoolSize - original = delta,delta大于0,则创建等待队列任务数和delta线程数来处理等待任务。

(3)如果运行线程数>:CorePoolSize则中断冗余线程。

修改maximumpoolsize时出错(1)maximum poolsize小于corePoolSize。

(2)如果运行线程大于maximumPoolSize,则中断一些空闲线程。

基于这些机制,线程池内容可以在运行时动态调整。

不需要担心在会议中切断正在运行的任务,因为每次线程池工作线程执行一个任务

tomcat如何避免原生线程池的缺陷?本机线程池是如何工作的?

(1)如果运行线程的数量少于核心线程,则创建一个工作线程来执行任务。

(2)运行线程数>:=核心线程,所有任务都积压在队列中。

(3)如果队列已满,继续创建非核心线程工作器来执行任务。

如果tomcat采用原生线程池,10个核心线程,100个最大线程,200个队列,100个请求,那么系统只能同时处理10个请求,剩下的90个线程要放到队列中,让10个核心线程排队慢慢处理,那么延迟会很高。

tomcat如何优化线程池,核心在于阻塞队列的实现,因为阻塞队列已满,会不断创建非核心工作线程处理任务。

(1)如果运行线程的数量少于核心线程,则创建一个工作线程来执行任务。

(2)当前已经创建的核心+非核心线程数等于最大线程数,将任务推入队列。

(3)正在处理的请求数小于核心+非核心线程数,任务被压入队列。

(4)如果当前创建的核心+非核心线程的数量小于线程的最大数量,则创建工作者线程来处理该请求。

总之,当高并发流量到来时,将创建具有最大数量线程的工作线程来处理请求,以减少尾部延迟。超过最大线程数后,任务将被推入队列进行处理。

以上是tomcat集群监控和弹性伸缩的详细内容。更多关于tomcat集群监控弹性伸缩的信息,请关注主机频道zhujipindao的其他相关文章。com!

未经允许不得转载:主机频道 » tomcat集群监控和弹性扩展详解

评论 抢沙发

评论前必须登录!